Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
BaseChildFactory.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import com.google.common.collect.Lists;
22 import com.google.common.eventbus.EventBus;
23 import com.google.common.eventbus.Subscribe;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.function.Predicate;
30 import java.util.logging.Level;
32 import java.util.prefs.PreferenceChangeEvent;
33 import java.util.stream.Collectors;
34 import org.openide.nodes.ChildFactory;
35 import org.openide.util.NbBundle.Messages;
37 import org.sleuthkit.datamodel.Content;
38 
45 public abstract class BaseChildFactory<T extends Content> extends ChildFactory.Detachable<T> {
46 
47  private static final Logger logger = Logger.getLogger(BaseChildFactory.class.getName());
48 
49  private Predicate<T> filter;
50  private boolean isPageChangeEvent;
51  private boolean isPageSizeChangeEvent;
52 
53  private final PagingSupport pagingSupport;
54 
59  private static Map<String, EventBus> nodeNameToEventBusMap = new ConcurrentHashMap<>();
60 
61  @Messages({
62  "# {0} - node name", "BaseChildFactory.NoSuchEventBusException.message=No event bus for node: {0}"
63  })
64  public static class NoSuchEventBusException extends Exception {
65 
66  public NoSuchEventBusException(String nodeName) {
67  super(Bundle.BaseChildFactory_NoSuchEventBusException_message(nodeName));
68  }
69  }
70 
78  public static void register(String nodeName, Object subscriber) {
79  EventBus bus = nodeNameToEventBusMap.get(nodeName);
80  if (bus == null) {
81  bus = new EventBus(nodeName);
82  nodeNameToEventBusMap.put(nodeName, bus);
83  }
84  bus.register(subscriber);
85  }
86 
96  public static void post(String nodeName, Object event) throws NoSuchEventBusException {
97  EventBus bus = nodeNameToEventBusMap.get(nodeName);
98  if (bus == null) {
99  throw new NoSuchEventBusException(nodeName);
100  }
101  bus.post(event);
102  }
103 
104  public BaseChildFactory(String nodeName) {
108  this(nodeName, x -> true);
109  }
110 
111  public BaseChildFactory(String nodeName, Predicate<T> filter) {
112  pagingSupport = new PagingSupport(nodeName);
113  pagingSupport.initialize();
114  isPageChangeEvent = false;
115  isPageSizeChangeEvent = false;
116  this.filter = filter;
117  }
118 
119  @Override
120  protected void addNotify() {
121  onAdd();
122  }
123 
124  @Override
125  protected void removeNotify() {
126  onRemove();
127  }
128 
134  protected abstract List<T> makeKeys();
135 
139  protected abstract void onAdd();
140 
145  protected abstract void onRemove();
146 
147  @Override
148  protected boolean createKeys(List<T> toPopulate) {
154  if (!isPageChangeEvent && !isPageSizeChangeEvent) {
155  List<T> allKeys = makeKeys();
156 
157  pagingSupport.splitKeysIntoPages(allKeys.stream().filter(filter).collect(Collectors.toList()));
158  }
159 
160  toPopulate.addAll(pagingSupport.getCurrentPage());
161 
162  // Reset page change and page size change event flags
163  isPageChangeEvent = false;
164  isPageSizeChangeEvent = false;
165 
166  return true;
167  }
168 
172  public static class RefreshKeysEvent {
173  }
174 
179  public static class PageChangeEvent {
180 
181  private final int pageNumber;
182 
183  public PageChangeEvent(int newPageNumber) {
184  pageNumber = newPageNumber;
185  }
186 
187  public int getPageNumber() {
188  return pageNumber;
189  }
190  }
191 
195  public static class PageCountChangeEvent {
196 
197  private final int pageCount;
198 
199  public PageCountChangeEvent(int newPageCount) {
200  pageCount = newPageCount;
201  }
202 
203  public int getPageCount() {
204  return pageCount;
205  }
206  }
207 
211  public static class PageSizeChangeEvent {
212 
213  private final int pageSize;
214 
215  public PageSizeChangeEvent(int newPageSize) {
216  pageSize = newPageSize;
217  }
218 
219  public int getPageSize() {
220  return pageSize;
221  }
222  }
223 
228  private class PagingSupport {
229 
230  private final String nodeName;
231  private int pageSize;
232  private int currentPage;
233  private List<List<T>> pages;
234 
243  PagingSupport(String nodeName) {
244  currentPage = 1;
246  pages = new ArrayList<>();
247  this.nodeName = nodeName;
248  }
249 
250  void initialize() {
255  UserPreferences.addChangeListener((PreferenceChangeEvent evt) -> {
256  if (evt.getKey().equals(UserPreferences.RESULTS_TABLE_PAGE_SIZE)) {
258  }
259  });
260 
261  register(nodeName, this);
262  }
263 
269  List<T> getCurrentPage() {
270  if (!pages.isEmpty()) {
271  return pages.get(currentPage - 1);
272  }
273 
274  return Collections.emptyList();
275  }
276 
282  void splitKeysIntoPages(List<T> keys) {
283  int oldPageCount = pages.size();
284 
289  if (keys.isEmpty() && !pages.isEmpty()) {
296  pages = new ArrayList<>();
297  } else {
298  pages = Lists.partition(keys, pageSize > 0 ? pageSize : keys.size());
299  }
300 
301  if (pages.size() != oldPageCount) {
302  try {
303  // Number of pages has changed so we need to send out a notification.
304  post(nodeName, new PageCountChangeEvent(pages.size()));
305  } catch (NoSuchEventBusException ex) {
306  logger.log(Level.WARNING, "Failed to post page change event.", ex);
307  }
308  }
309  }
310 
317  @Subscribe
319  if (event != null) {
320  currentPage = event.getPageNumber();
321  isPageChangeEvent = true;
322  refresh(true);
323  }
324  }
325 
332  @Subscribe
334  if (event != null) {
335  int newPageSize = event.getPageSize();
336  if (pageSize == newPageSize) {
337  // No change...nothing to do.
338  return;
339  }
340 
341  pageSize = newPageSize;
342  splitKeysIntoPages(pages.stream().flatMap(List::stream).collect(Collectors.toList()));
343 
344  currentPage = 1;
345  isPageSizeChangeEvent = true;
346  refresh(true);
347  }
348  }
349 
350  @Subscribe
352  if (event != null) {
353  refresh(true);
354  }
355  }
356  }
357 }
static Map< String, EventBus > nodeNameToEventBusMap
static void post(String nodeName, Object event)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addChangeListener(PreferenceChangeListener listener)
BaseChildFactory(String nodeName, Predicate< T > filter)

Copyright © 2012-2021 Basis Technology. Generated on: Tue Jan 19 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.