Autopsy  4.20.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 finalize() throws Throwable {
126  super.finalize();
127  onRemove();
128  }
129 
135  protected abstract List<T> makeKeys();
136 
140  protected abstract void onAdd();
141 
146  protected abstract void onRemove();
147 
148  @Override
149  protected boolean createKeys(List<T> toPopulate) {
155  if (!isPageChangeEvent && !isPageSizeChangeEvent) {
156  List<T> allKeys = makeKeys();
157 
158  pagingSupport.splitKeysIntoPages(allKeys.stream().filter(filter).collect(Collectors.toList()));
159  }
160 
161  toPopulate.addAll(pagingSupport.getCurrentPage());
162 
163  // Reset page change and page size change event flags
164  isPageChangeEvent = false;
165  isPageSizeChangeEvent = false;
166 
167  return true;
168  }
169 
173  public static class RefreshKeysEvent {
174  }
175 
180  public static class PageChangeEvent {
181 
182  private final int pageNumber;
183 
184  public PageChangeEvent(int newPageNumber) {
185  pageNumber = newPageNumber;
186  }
187 
188  public int getPageNumber() {
189  return pageNumber;
190  }
191  }
192 
196  public static class PageCountChangeEvent {
197 
198  private final int pageCount;
199 
200  public PageCountChangeEvent(int newPageCount) {
201  pageCount = newPageCount;
202  }
203 
204  public int getPageCount() {
205  return pageCount;
206  }
207  }
208 
212  public static class PageSizeChangeEvent {
213 
214  private final int pageSize;
215 
216  public PageSizeChangeEvent(int newPageSize) {
217  pageSize = newPageSize;
218  }
219 
220  public int getPageSize() {
221  return pageSize;
222  }
223  }
224 
229  private class PagingSupport {
230 
231  private final String nodeName;
232  private int pageSize;
233  private int currentPage;
234  private List<List<T>> pages;
235 
244  PagingSupport(String nodeName) {
245  currentPage = 1;
247  pages = new ArrayList<>();
248  this.nodeName = nodeName;
249  }
250 
251  void initialize() {
256  UserPreferences.addChangeListener((PreferenceChangeEvent evt) -> {
257  if (evt.getKey().equals(UserPreferences.RESULTS_TABLE_PAGE_SIZE)) {
259  }
260  });
261 
262  register(nodeName, this);
263  }
264 
270  List<T> getCurrentPage() {
271  if (!pages.isEmpty()) {
272  return pages.get(currentPage - 1);
273  }
274 
275  return Collections.emptyList();
276  }
277 
283  void splitKeysIntoPages(List<T> keys) {
284  int oldPageCount = pages.size();
285 
290  if (keys.isEmpty() && !pages.isEmpty()) {
297  pages = new ArrayList<>();
298  } else {
299  pages = Lists.partition(keys, pageSize > 0 ? pageSize : keys.size());
300  }
301 
302  if (pages.size() != oldPageCount) {
303  try {
304  // Number of pages has changed so we need to send out a notification.
305  post(nodeName, new PageCountChangeEvent(pages.size()));
306  } catch (NoSuchEventBusException ex) {
307  logger.log(Level.WARNING, "Failed to post page change event.", ex);
308  }
309  }
310  }
311 
318  @Subscribe
320  if (event != null) {
321  currentPage = event.getPageNumber();
322  isPageChangeEvent = true;
323  refresh(true);
324  }
325  }
326 
333  @Subscribe
335  if (event != null) {
336  int newPageSize = event.getPageSize();
337  if (pageSize == newPageSize) {
338  // No change...nothing to do.
339  return;
340  }
341 
342  pageSize = newPageSize;
343  splitKeysIntoPages(pages.stream().flatMap(List::stream).collect(Collectors.toList()));
344 
345  currentPage = 1;
346  isPageSizeChangeEvent = true;
347  refresh(true);
348  }
349  }
350 
351  @Subscribe
353  if (event != null) {
354  refresh(true);
355  }
356  }
357  }
358 }
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-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.