diff --git a/0.9.16/.buildinfo b/0.9.16/.buildinfo new file mode 100644 index 0000000..adc1008 --- /dev/null +++ b/0.9.16/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 3b9b08749f0679d7043ac15e47c23e4a +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/0.9.16/.doctrees/changes.doctree b/0.9.16/.doctrees/changes.doctree new file mode 100644 index 0000000..97caef5 Binary files /dev/null and b/0.9.16/.doctrees/changes.doctree differ diff --git a/0.9.16/.doctrees/contact.doctree b/0.9.16/.doctrees/contact.doctree new file mode 100644 index 0000000..7e6524a Binary files /dev/null and b/0.9.16/.doctrees/contact.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts.doctree b/0.9.16/.doctrees/dev/concepts.doctree new file mode 100644 index 0000000..01f9828 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/all_in_one_debugging.doctree b/0.9.16/.doctrees/dev/concepts/all_in_one_debugging.doctree new file mode 100644 index 0000000..e3da047 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/all_in_one_debugging.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/anatomy_of_a_plugin.doctree b/0.9.16/.doctrees/dev/concepts/anatomy_of_a_plugin.doctree new file mode 100644 index 0000000..aa4e90a Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/anatomy_of_a_plugin.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/data_transformations.doctree b/0.9.16/.doctrees/dev/concepts/data_transformations.doctree new file mode 100644 index 0000000..4e6b318 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/data_transformations.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/extraction_plugins.doctree b/0.9.16/.doctrees/dev/concepts/extraction_plugins.doctree new file mode 100644 index 0000000..c2915c9 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/extraction_plugins.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/hql_lite.doctree b/0.9.16/.doctrees/dev/concepts/hql_lite.doctree new file mode 100644 index 0000000..02ea33f Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/hql_lite.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/isolation.doctree b/0.9.16/.doctrees/dev/concepts/isolation.doctree new file mode 100644 index 0000000..c60276f Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/isolation.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/kubernetes_autoscaling.doctree b/0.9.16/.doctrees/dev/concepts/kubernetes_autoscaling.doctree new file mode 100644 index 0000000..c8463e6 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/kubernetes_autoscaling.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/plugin_naming_convention.doctree b/0.9.16/.doctrees/dev/concepts/plugin_naming_convention.doctree new file mode 100644 index 0000000..266ce87 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/plugin_naming_convention.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/plugin_types.doctree b/0.9.16/.doctrees/dev/concepts/plugin_types.doctree new file mode 100644 index 0000000..14f7dfe Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/plugin_types.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/test_framework.doctree b/0.9.16/.doctrees/dev/concepts/test_framework.doctree new file mode 100644 index 0000000..28ed3de Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/test_framework.doctree differ diff --git a/0.9.16/.doctrees/dev/concepts/traces.doctree b/0.9.16/.doctrees/dev/concepts/traces.doctree new file mode 100644 index 0000000..be6b6c4 Binary files /dev/null and b/0.9.16/.doctrees/dev/concepts/traces.doctree differ diff --git a/0.9.16/.doctrees/dev/examples.doctree b/0.9.16/.doctrees/dev/examples.doctree new file mode 100644 index 0000000..78b0fe5 Binary files /dev/null and b/0.9.16/.doctrees/dev/examples.doctree differ diff --git a/0.9.16/.doctrees/dev/faq.doctree b/0.9.16/.doctrees/dev/faq.doctree new file mode 100644 index 0000000..2c5ec82 Binary files /dev/null and b/0.9.16/.doctrees/dev/faq.doctree differ diff --git a/0.9.16/.doctrees/dev/introduction.doctree b/0.9.16/.doctrees/dev/introduction.doctree new file mode 100644 index 0000000..ac58e85 Binary files /dev/null and b/0.9.16/.doctrees/dev/introduction.doctree differ diff --git a/0.9.16/.doctrees/dev/java.doctree b/0.9.16/.doctrees/dev/java.doctree new file mode 100644 index 0000000..c2a1ada Binary files /dev/null and b/0.9.16/.doctrees/dev/java.doctree differ diff --git a/0.9.16/.doctrees/dev/java/api_changelog.doctree b/0.9.16/.doctrees/dev/java/api_changelog.doctree new file mode 100644 index 0000000..9fc988c Binary files /dev/null and b/0.9.16/.doctrees/dev/java/api_changelog.doctree differ diff --git a/0.9.16/.doctrees/dev/java/debugging.doctree b/0.9.16/.doctrees/dev/java/debugging.doctree new file mode 100644 index 0000000..1bd6022 Binary files /dev/null and b/0.9.16/.doctrees/dev/java/debugging.doctree differ diff --git a/0.9.16/.doctrees/dev/java/javadoc.doctree b/0.9.16/.doctrees/dev/java/javadoc.doctree new file mode 100644 index 0000000..4df1122 Binary files /dev/null and b/0.9.16/.doctrees/dev/java/javadoc.doctree differ diff --git a/0.9.16/.doctrees/dev/java/packaging.doctree b/0.9.16/.doctrees/dev/java/packaging.doctree new file mode 100644 index 0000000..00ab1cc Binary files /dev/null and b/0.9.16/.doctrees/dev/java/packaging.doctree differ diff --git a/0.9.16/.doctrees/dev/java/prerequisites.doctree b/0.9.16/.doctrees/dev/java/prerequisites.doctree new file mode 100644 index 0000000..507036c Binary files /dev/null and b/0.9.16/.doctrees/dev/java/prerequisites.doctree differ diff --git a/0.9.16/.doctrees/dev/java/snippets.doctree b/0.9.16/.doctrees/dev/java/snippets.doctree new file mode 100644 index 0000000..36a6948 Binary files /dev/null and b/0.9.16/.doctrees/dev/java/snippets.doctree differ diff --git a/0.9.16/.doctrees/dev/java/testing.doctree b/0.9.16/.doctrees/dev/java/testing.doctree new file mode 100644 index 0000000..25d75c6 Binary files /dev/null and b/0.9.16/.doctrees/dev/java/testing.doctree differ diff --git a/0.9.16/.doctrees/dev/python.doctree b/0.9.16/.doctrees/dev/python.doctree new file mode 100644 index 0000000..a926397 Binary files /dev/null and b/0.9.16/.doctrees/dev/python.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.data_context.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.data_context.doctree new file mode 100644 index 0000000..62200d6 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.data_context.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.doctree new file mode 100644 index 0000000..e0c6738 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.doctree new file mode 100644 index 0000000..e1f84c6 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.extraction_trace.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.extraction_trace.doctree new file mode 100644 index 0000000..deb2b53 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.extraction_trace.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.plugin_info.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.plugin_info.doctree new file mode 100644 index 0000000..50f06dc Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.plugin_info.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.search_result.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.search_result.doctree new file mode 100644 index 0000000..d07a53a Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.search_result.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.search_sort_option.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.search_sort_option.doctree new file mode 100644 index 0000000..79b14ca Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.search_sort_option.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.trace_searcher.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.trace_searcher.doctree new file mode 100644 index 0000000..64c441e Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.trace_searcher.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.tracelet.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.tracelet.doctree new file mode 100644 index 0000000..9c09b2a Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.tracelet.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.transformation.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.transformation.doctree new file mode 100644 index 0000000..ccafc3d Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.transformation.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.transformer.doctree b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.transformer.doctree new file mode 100644 index 0000000..dd66ed2 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api/hansken_extraction_plugin.api.transformer.doctree differ diff --git a/0.9.16/.doctrees/dev/python/api_changelog.doctree b/0.9.16/.doctrees/dev/python/api_changelog.doctree new file mode 100644 index 0000000..c254b03 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/api_changelog.doctree differ diff --git a/0.9.16/.doctrees/dev/python/debugging.doctree b/0.9.16/.doctrees/dev/python/debugging.doctree new file mode 100644 index 0000000..c9e9824 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/debugging.doctree differ diff --git a/0.9.16/.doctrees/dev/python/getting_started.doctree b/0.9.16/.doctrees/dev/python/getting_started.doctree new file mode 100644 index 0000000..9170350 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/getting_started.doctree differ diff --git a/0.9.16/.doctrees/dev/python/hanskenpy.doctree b/0.9.16/.doctrees/dev/python/hanskenpy.doctree new file mode 100644 index 0000000..a59a7d7 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/hanskenpy.doctree differ diff --git a/0.9.16/.doctrees/dev/python/packaging.doctree b/0.9.16/.doctrees/dev/python/packaging.doctree new file mode 100644 index 0000000..3cc0203 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/packaging.doctree differ diff --git a/0.9.16/.doctrees/dev/python/prerequisites.doctree b/0.9.16/.doctrees/dev/python/prerequisites.doctree new file mode 100644 index 0000000..9fa9d3b Binary files /dev/null and b/0.9.16/.doctrees/dev/python/prerequisites.doctree differ diff --git a/0.9.16/.doctrees/dev/python/snippets.doctree b/0.9.16/.doctrees/dev/python/snippets.doctree new file mode 100644 index 0000000..d8af8a7 Binary files /dev/null and b/0.9.16/.doctrees/dev/python/snippets.doctree differ diff --git a/0.9.16/.doctrees/dev/python/testing.doctree b/0.9.16/.doctrees/dev/python/testing.doctree new file mode 100644 index 0000000..3acf15b Binary files /dev/null and b/0.9.16/.doctrees/dev/python/testing.doctree differ diff --git a/0.9.16/.doctrees/dev/python/transformers.doctree b/0.9.16/.doctrees/dev/python/transformers.doctree new file mode 100644 index 0000000..74b23bb Binary files /dev/null and b/0.9.16/.doctrees/dev/python/transformers.doctree differ diff --git a/0.9.16/.doctrees/dev/spec.doctree b/0.9.16/.doctrees/dev/spec.doctree new file mode 100644 index 0000000..fc3c071 Binary files /dev/null and b/0.9.16/.doctrees/dev/spec.doctree differ diff --git a/0.9.16/.doctrees/environment.pickle b/0.9.16/.doctrees/environment.pickle new file mode 100644 index 0000000..c6c2094 Binary files /dev/null and b/0.9.16/.doctrees/environment.pickle differ diff --git a/0.9.16/.doctrees/index.doctree b/0.9.16/.doctrees/index.doctree new file mode 100644 index 0000000..0ec7e0d Binary files /dev/null and b/0.9.16/.doctrees/index.doctree differ diff --git a/0.9.16/.nojekyll b/0.9.16/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/0.9.16/_images/1_debug_start_plugin_in_ide.png b/0.9.16/_images/1_debug_start_plugin_in_ide.png new file mode 100644 index 0000000..15ee2ec Binary files /dev/null and b/0.9.16/_images/1_debug_start_plugin_in_ide.png differ diff --git a/0.9.16/_images/2_debug_set_breakpoints.png b/0.9.16/_images/2_debug_set_breakpoints.png new file mode 100644 index 0000000..0b390ea Binary files /dev/null and b/0.9.16/_images/2_debug_set_breakpoints.png differ diff --git a/0.9.16/_images/3_debug_prepare_extraction.png b/0.9.16/_images/3_debug_prepare_extraction.png new file mode 100644 index 0000000..6d795bb Binary files /dev/null and b/0.9.16/_images/3_debug_prepare_extraction.png differ diff --git a/0.9.16/_images/4_debug_enable_debug_tool.png b/0.9.16/_images/4_debug_enable_debug_tool.png new file mode 100644 index 0000000..279e75a Binary files /dev/null and b/0.9.16/_images/4_debug_enable_debug_tool.png differ diff --git a/0.9.16/_images/cartoon.png b/0.9.16/_images/cartoon.png new file mode 100644 index 0000000..ceae6f5 Binary files /dev/null and b/0.9.16/_images/cartoon.png differ diff --git a/0.9.16/_images/datatransformations.png b/0.9.16/_images/datatransformations.png new file mode 100644 index 0000000..7acefa7 Binary files /dev/null and b/0.9.16/_images/datatransformations.png differ diff --git a/0.9.16/_images/download_template.png b/0.9.16/_images/download_template.png new file mode 100644 index 0000000..81e8adf Binary files /dev/null and b/0.9.16/_images/download_template.png differ diff --git a/0.9.16/_images/hanskenpy_gatekeeper_keystore.png b/0.9.16/_images/hanskenpy_gatekeeper_keystore.png new file mode 100644 index 0000000..849851f Binary files /dev/null and b/0.9.16/_images/hanskenpy_gatekeeper_keystore.png differ diff --git a/0.9.16/_images/hanskenpy_save_query.png b/0.9.16/_images/hanskenpy_save_query.png new file mode 100644 index 0000000..407245c Binary files /dev/null and b/0.9.16/_images/hanskenpy_save_query.png differ diff --git a/0.9.16/_images/pycharm_open_project.png b/0.9.16/_images/pycharm_open_project.png new file mode 100644 index 0000000..e112da2 Binary files /dev/null and b/0.9.16/_images/pycharm_open_project.png differ diff --git a/0.9.16/_images/pycharm_open_project_venv.png b/0.9.16/_images/pycharm_open_project_venv.png new file mode 100644 index 0000000..7a3b7a5 Binary files /dev/null and b/0.9.16/_images/pycharm_open_project_venv.png differ diff --git a/0.9.16/_images/pycharm_project_start_page.png b/0.9.16/_images/pycharm_project_start_page.png new file mode 100644 index 0000000..27fe8d1 Binary files /dev/null and b/0.9.16/_images/pycharm_project_start_page.png differ diff --git a/0.9.16/_images/toolrun_error.png b/0.9.16/_images/toolrun_error.png new file mode 100644 index 0000000..8f9d7df Binary files /dev/null and b/0.9.16/_images/toolrun_error.png differ diff --git a/0.9.16/_images/trace.svg b/0.9.16/_images/trace.svg new file mode 100644 index 0000000..89f4289 --- /dev/null +++ b/0.9.16/_images/trace.svg @@ -0,0 +1,40 @@ +TraceString idString nameString[] pathMap<Type, Properties> propertiesList<DataStream>List<Trace> childrenDataStreamString typeString lengthbyte[] dataString fileTypeProperties propertiesa trace could have child tracesa trace could have data streams \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/data_context.html b/0.9.16/_modules/hansken_extraction_plugin/api/data_context.html new file mode 100644 index 0000000..9d3e73f --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/data_context.html @@ -0,0 +1,129 @@ + + + + + + + + hansken_extraction_plugin.api.data_context — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.data_context

+"""This module contains the definition of the DataContext."""
+from dataclasses import dataclass
+
+
+
+[docs] +@dataclass(frozen=True) +class DataContext: + """This class contains the data context of a plugin that is processing a trace.""" + + data_type: str #: the named data type that is being processed + data_size: int #: the size / total length of the data stream that is being processed + + def __eq__(self, other): + # override the default equality check, a subclass is considered equal as long as it matches all the fields this + # type describes + return isinstance(other, DataContext) and (self.data_type, self.data_size) == (other.data_type, other.data_size)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/extraction_plugin.html b/0.9.16/_modules/hansken_extraction_plugin/api/extraction_plugin.html new file mode 100644 index 0000000..7625ff9 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/extraction_plugin.html @@ -0,0 +1,253 @@ + + + + + + + + hansken_extraction_plugin.api.extraction_plugin — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.extraction_plugin

+"""
+This module contains the different types of Extraction Plugins.
+
+The types of Extraction Plugins differ in their process functions.
+"""
+from abc import ABC, abstractmethod
+import inspect
+from typing import List
+
+from hansken_extraction_plugin.api.data_context import DataContext
+from hansken_extraction_plugin.api.extraction_trace import ExtractionTrace, MetaExtractionTrace
+from hansken_extraction_plugin.api.plugin_info import PluginInfo
+from hansken_extraction_plugin.api.trace_searcher import TraceSearcher
+from hansken_extraction_plugin.api.transformer import Transformer
+from hansken_extraction_plugin.decorators.transformer import transformer_registry
+
+
+
+[docs] +class BaseExtractionPlugin(ABC): + """All Extraction Plugins are derived from this class.""" + +
+[docs] + @abstractmethod + def plugin_info(self) -> PluginInfo: + """Return information about this extraction plugin."""
+ + + @property + def transformers(self) -> List[Transformer]: + """ + Dynamically retrieves the transformer methods that were decorated with @transform. + + Note: This method will retrieve transformers for superclasses as well. + """ + # Retrieve all super classes of a plugin so that we can also retrieve transformers of super classes. + # Note: This also contains the more specific instance this method might be called on as well. + base_classes = inspect.getmro(self.__class__) + + # Check for each (super) class of the plugin if transformers have been registered. + transformers = [ + transformer for cl in base_classes + if cl.__name__ in transformer_registry + for transformer in transformer_registry[cl.__name__] + ] + + return transformers
+ + + +
+[docs] +class ExtractionPlugin(BaseExtractionPlugin): + """Default extraction plugin, that processes a trace and one of its datastreams.""" + +
+[docs] + @abstractmethod + def process(self, trace: ExtractionTrace, data_context: DataContext): + """ + Process a given trace. + + This method is called for every trace that is processed by this tool. + + :param trace: Trace that is being processed + :param data_context: Data data_context describing the data stream that is being processed + """
+
+ + + +
+[docs] +class MetaExtractionPlugin(BaseExtractionPlugin): + """Extraction Plugin that processes a trace only with its metadata, without processing its data.""" + +
+[docs] + @abstractmethod + def process(self, trace: MetaExtractionTrace): + """ + Process a given trace. + + This method is called for every trace that is processed by this tool. + + :param trace: Trace that is being processed + """
+
+ + + +
+[docs] +class DeferredExtractionPlugin(BaseExtractionPlugin): + """ + Extraction Plugin that can be run at a different extraction stage. + + This type of plugin also allows accessing other traces using the searcher. + """ + +
+[docs] + @abstractmethod + def process(self, trace: ExtractionTrace, data_context: DataContext, searcher: TraceSearcher): + """ + Process a given trace. + + This method is called for every trace that is processed by this tool. + + :param trace: Trace that is being processed + :param data_context: Data data_context describing the data stream that is being processed + :param searcher: TraceSearcher that can be used to obtain more traces + """
+
+ + + +
+[docs] +class DeferredMetaExtractionPlugin(BaseExtractionPlugin): + """ + Extraction Plugin that can be postponed to a later extraction iteration. + + This type of plugin processes a trace only with its metadata, + without processing its data and accesses traces using the searcher. + """ + +
+[docs] + @abstractmethod + def process(self, trace: MetaExtractionTrace, searcher: TraceSearcher): + """ + Process a given trace. + + This method is called for every trace that is processed by this tool. + + :param trace: Trace that is being processed + :param searcher: TraceSearcher that can be used to obtain more traces + """
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/extraction_trace.html b/0.9.16/_modules/hansken_extraction_plugin/api/extraction_trace.html new file mode 100644 index 0000000..2a7f186 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/extraction_trace.html @@ -0,0 +1,394 @@ + + + + + + + + hansken_extraction_plugin.api.extraction_trace — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.extraction_trace

+"""
+This module contains the different Trace apis.
+
+Note that there are a couple of different traces:
+  * The ExtractionTrace and MetaExtractionTrace, which are offered to the process function.
+  * ExtractionTraceBuilder, which is a trace that can be built; it does not exist in hansken yet, but it is added after
+    building.
+  * SearchTrace, which represents an immutable trace which is returned after searching for traces.
+"""
+from abc import ABC, abstractmethod
+from io import BufferedReader, BufferedWriter, TextIOBase
+from typing import Any, Literal, Mapping, Optional, Union
+
+from hansken_extraction_plugin.api.tracelet import Tracelet
+from hansken_extraction_plugin.api.transformation import Transformation
+
+
+
+[docs] +class ExtractionTraceBuilder(ABC): + """ + ExtractionTrace that can be build. + + Represents child traces. + """ + +
+[docs] + @abstractmethod + def update(self, key_or_updates: Optional[Union[Mapping, str]] = None, value: Optional[Any] = None, + data: Optional[Mapping[str, bytes]] = None) -> 'ExtractionTraceBuilder': + """ + Update or add metadata properties for this `.ExtractionTraceBuilder`. + + Can be used to update the name of the Trace represented by this builder, + if not already set. + + :param key_or_updates: either a `str` (the metadata property to be + updated) or a mapping supplying both keys and values to be updated + :param value: the value to update metadata property *key* to (used + only when *key_or_updates* is a `str`, an exception will be thrown + if *key_or_updates* is a mapping) + :param data: a `dict` mapping data type / stream name to bytes to be + added to the trace + :return: this `.ExtractionTraceBuilder` + """
+ + +
+[docs] + @abstractmethod + def add_tracelet(self, + tracelet: Union[Tracelet, str], + value: Optional[Mapping[str, Any]] = None) -> 'ExtractionTraceBuilder': + """ + Add a `.Tracelet` to this `.ExtractionTraceBuilder`. + + :param tracelet: the Tracelet or tracelet type (supplied as a `str`) to add + :param value: the tracelet properties to add (only applicable when *tracelet* is a `str`) + :return: this `.ExtractionTraceBuilder` + """
+ + +
+[docs] + @abstractmethod + def add_transformation(self, data_type: str, transformation: Transformation) -> 'ExtractionTraceBuilder': + """ + Update or add transformations for this `.ExtractionTraceBuilder`. + + :param data_type: data type of the Transformation + :param transformation: the Transformation to add + :return: this `.ExtractionTraceBuilder` + """
+ + +
+[docs] + @abstractmethod + def child_builder(self, name: Optional[str] = None) -> 'ExtractionTraceBuilder': + """ + Create a new `.TraceBuilder` to build a child trace to the trace to be represented by this builder. + + .. note:: + Traces should be created and built in depth first order, + parent before child (pre-order). + + :return: a `.TraceBuilder` set up to save a new trace as the child + trace of this builder + """
+ + +
+[docs] + def add_data(self, stream: str, data: bytes) -> 'ExtractionTraceBuilder': + """ + Add data to this trace as a named stream. + + :param stream: name of the data stream to be added + :param data: data to be attached + :return: this `.ExtractionTraceBuilder` + """ + return self.update(data={stream: data})
+ + +
+[docs] + @abstractmethod + def open(self, data_type: Optional[str] = None, offset: int = 0, size: Optional[int] = None, + mode: Literal['rb', 'wb', 'w', 'wt'] = 'rb', encoding='utf-8', buffer_size: Optional[int] = None) \ + -> Union[BufferedReader, BufferedWriter, TextIOBase]: + """ + Open a data stream to read or write data from or to the `.ExtractionTrace`. + + :param data_type: the data type of the datastream, 'raw' by default + :param offset: byte offset to start the stream on when reading + :param size: the number of bytes to make available when reading + :param mode: 'rb' for reading, 'wb' for writing + :param encoding: encoding for writing text, used to convert `str` values to bytes, \ + only valid for modes 'w' and 'wt' + :param buffer_size: buffer size for reading (cache read back/ahead) or writing (cache for flush) data + :return: a file-like object to read or write bytes from the named stream + """
+ + +
+[docs] + @abstractmethod + def build(self) -> str: + """ + Save the trace being built by this builder to remote. + + .. note:: + Building more than once will result in an error being raised. + + :return: the new trace' id + """
+
+ + + +
+[docs] +class Trace(ABC): + """All trace classes should be able to return values.""" + +
+[docs] + @abstractmethod + def get(self, key: str, default: Optional[Any] = None) -> Any: + """ + Return metadata properties for this `.ExtractionTrace`. + + :param key: the metadata property to be retrieved + :param default: value returned if property is not set + :return: the value of the requested metadata property + """
+
+ + + +
+[docs] +class SearchTrace(Trace): + """SearchTraces represent traces returned when searching for traces.""" + +
+[docs] + @abstractmethod + def open(self, stream: str = 'raw', offset: int = 0, size: Optional[int] = None, + buffer_size: Optional[int] = None) -> BufferedReader: + """ + Open a data stream of the data that is being processed. + + :param stream: data stream of trace to open. defaults to raw. other examples are html, text, etc. + :param offset: byte offset to start the stream on + :param size: the number of bytes to make available + :param buffer_size: buffer size for reading data + :return: a file-like object to read bytes from the named stream + """
+
+ + + +
+[docs] +class MetaExtractionTrace(Trace): + """ + MetaExtractionTraces contain only metadata. + + This class represents traces during the extraction of an extraction plugin without a data stream. + """ + +
+[docs] + @abstractmethod + def update(self, key_or_updates: Optional[Union[Mapping, str]] = None, value: Optional[Any] = None, + data: Optional[Mapping[str, bytes]] = None) -> None: + """ + Update or add metadata properties for this `.ExtractionTrace`. + + :param key_or_updates: either a `str` (the metadata property to be + updated) or a mapping supplying both keys and values to be updated + :param value: the value to update metadata property *key* to (used + only when *key_or_updates* is a `str`, an exception will be thrown + if *key_or_updates* is a mapping) + :param data: a `dict` mapping data type / stream name to bytes to be + added to the trace + """
+ + +
+[docs] + @abstractmethod + def add_tracelet(self, + tracelet: Union[Tracelet, str], + value: Optional[Mapping[str, Any]] = None) -> None: + """ + Add a `.Tracelet` to this `.MetaExtractionTrace`. + + :param tracelet: the Tracelet or tracelet type to add + :param value: the tracelet properties to add (only applicable when *tracelet* is a tracelet type) + """
+ + +
+[docs] + @abstractmethod + def add_transformation(self, data_type: str, transformation: Transformation) -> None: + """ + Update or add transformations for this `.ExtractionTraceBuilder`. + + :param data_type: data type of the Transformation + :param transformation: the Transformation to add + """
+ + +
+[docs] + @abstractmethod + def child_builder(self, name: Optional[str] = None) -> ExtractionTraceBuilder: + """ + Create a `.TraceBuilder` to build a trace to be saved as a child of this `.Trace`. + + A new trace will only be added to the index once explicitly saved (e.g. + through `.TraceBuilder.build`). + + .. note:: + Traces should be created and built in depth first order, + parent before child (pre-order). + + :param name: the name for the trace being built + :return: a `.TraceBuilder` set up to create a child trace of this `.MetaExtractionTrace` + """
+
+ + + +
+[docs] +class ExtractionTrace(MetaExtractionTrace): + """Trace offered to be processed.""" + +
+[docs] + @abstractmethod + def open(self, data_type: Optional[str] = None, offset: int = 0, size: Optional[int] = None, + mode: Literal['rb', 'wb', 'w', 'wt'] = 'rb', encoding='utf-8', buffer_size: Optional[int] = None) \ + -> Union[BufferedReader, BufferedWriter, TextIOBase]: + """ + Open a data stream to read or write data from or to the `.ExtractionTrace`. + + :param data_type: the data type of the datastream, 'raw' by default + :param offset: byte offset to start the stream on when reading + :param size: the number of bytes to make available when reading + :param mode: 'rb' for reading, 'wb' for writing + :param encoding: encoding for writing text, used to convert `str` values to bytes, \ + only valid for modes 'w' and 'wt' + :param buffer_size: buffer size for reading (cache read back/ahead) or writing (cache for flush) data + :return: a file-like object to read or write bytes from the named stream + """
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/plugin_info.html b/0.9.16/_modules/hansken_extraction_plugin/api/plugin_info.html new file mode 100644 index 0000000..be5e3fe --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/plugin_info.html @@ -0,0 +1,271 @@ + + + + + + + + hansken_extraction_plugin.api.plugin_info — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.plugin_info

+"""This module contains all definitions to describe metadata of a plugin, a.k.a. PluginInfo."""
+from dataclasses import dataclass, field
+from enum import Enum
+from typing import Dict, List, Optional
+
+
+
+[docs] +@dataclass(frozen=True) +class Author: + """ + The author of an Extraction Plugin. + + This information can be retrieved by an end-user from Hansken. + """ + + name: str + email: str + organisation: str
+ + + +
+[docs] +class MaturityLevel(Enum): + """This class represents the maturity level of an extraction plugin.""" + + PROOF_OF_CONCEPT = 0 + READY_FOR_TEST = 1 + PRODUCTION_READY = 2
+ + + +
+[docs] +@dataclass(frozen=True) +class PluginId: + """Identifier of a plugin, consisting of domain, category and name. Needs to be unique among all tools/plugins.""" + + domain: str + category: str + name: str + + def __str__(self): + return f'{self.domain}/{self.category}/{self.name}'.lower()
+ + + +
+[docs] +@dataclass(frozen=True) +class PluginResources: + """PluginResources contains information about how many resources will be used for a plugin.""" + + maximum_cpu: Optional[float] = None + """ + CPU resources are measured in cpu units. One cpu is equivalent to 1 vCPU/Core for cloud providers and 1 hyperthread + on bare-metal Intel processors. Also, fractional requests are allowed. A plugin that asks 0.5 CPU uses half as + much CPU as one that asks for 1 CPU. + """ + maximum_memory: Optional[int] = None + """Max usable memory for a plugin, measured in megabytes.""" + maximum_workers: Optional[int] = None + """The number of concurrent workers(i.e. traces that can be processed).""" + + def __post_init__(self): + if self.maximum_cpu is not None and self.maximum_cpu < 0: + raise ValueError(f'maximum_cpu cannot be < 0: {self.maximum_cpu}') + if self.maximum_memory is not None and self.maximum_memory < 0: + raise ValueError(f'maximum_memory cannot be < 0: {self.maximum_memory}') + if self.maximum_workers is not None and self.maximum_workers < 0: + raise ValueError(f'maximum_workers cannot be < 0: {self.maximum_workers}')
+ + + +
+[docs] +@dataclass(frozen=True) +class TransformerLabel: + """ + TransformerLabel contains information about a transformer method that a plugin provides. + + It is mainly used for storing the properties (name, arguments, return type) of a transformer in PluginInfo objects. + Unlike the Transformer class it does not contain the actual function reference to the transformer itself. + """ + + """The method name of the transformer. For example: my_method""" + method_name: str + + """The parameters of the function where the key is the parameter name and the value is the type of the parameter.""" + parameters: Dict[str, str] + + """The return type of the parameter. See api.Transformer class for supported types.""" + return_type: str
+ + + +
+[docs] +@dataclass +class PluginInfo: + """ + This information is used by Hansken to identify and run the plugin. + + Note that the build_plugin.py build script is used to build a plugin docker image with PluginInfo docker labels. + """ + + id: PluginId #: a plugin's unique identifier, see PluginId + version: str #: version of the plugin + description: str #: short description of the functionality of the plugin + author: Author #: the plugin's author, see Author + maturity: MaturityLevel #: maturity level, see MaturityLevel + matcher: str #: this matcher selects the traces offered to the plugin + webpage_url: str #: plugin url + license: Optional[str] = None #: license of this plugin + deferred_iterations: int = 1 #: number of deferred iterations (1 to 20), nly for deferred plugins (optional) + resources: Optional[PluginResources] = None #: resources to be reserved for a plugin (optional) + bulk_mode: Optional[bool] = None #: this plugin should be run as a plugin with bulk mode enabled (optional) + + """Populated dynamically in pack.plugin_info by collecting all @transformer methods. Do not assign manually.""" + transformers: List[TransformerLabel] = field(default_factory=list) + + def __post_init__(self): + if not 1 <= self.deferred_iterations <= 20: + raise ValueError(f'Invalid value for deferred_iterations: {self.deferred_iterations}. ' + f'Valid values are 1 =< 20.') + +
+[docs] + @staticmethod + def from_dict(data: dict): + """Create a PluginInfo object from a dictionary.""" + return PluginInfo( + id=PluginId(domain=data['id']['domain'], category=data['id']['category'], name=data['id']['name']), + version=data['version'], + description=data['description'], + author=Author(name=data['author']['name'], + email=data['author']['email'], + organisation=data['author']['organisation']), + maturity=MaturityLevel[data['maturity'].split('.')[-1]], + matcher=data['matcher'], + webpage_url=data['webpage_url'], + license=data.get('license'), + deferred_iterations=data.get('deferred_iterations', 1), + resources=PluginResources( + maximum_cpu=data['resources'].get('maximum_cpu'), + maximum_memory=data['resources'].get('maximum_memory'), + maximum_workers=data['resources'].get('maximum_workers') + ) if 'resources' in data else None, + bulk_mode=data.get('bulk_mode', None), + transformers=[ + TransformerLabel( + method_name=transformer['method_name'], + parameters=transformer['parameters'], + return_type=transformer['return_type'] + ) for transformer in data.get('transformers', []) + ] + )
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/search_result.html b/0.9.16/_modules/hansken_extraction_plugin/api/search_result.html new file mode 100644 index 0000000..0b0f722 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/search_result.html @@ -0,0 +1,198 @@ + + + + + + + + hansken_extraction_plugin.api.search_result — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.search_result

+"""This module contains a representation of a search result."""
+from abc import ABC, abstractmethod
+from itertools import islice
+from typing import Iterable, List, Optional
+
+from hansken_extraction_plugin.api.extraction_trace import SearchTrace
+
+
+
+[docs] +class SearchResult(ABC, Iterable): + """ + Class representing a stream of traces, returned when performing a search request. + + This result can only be iterated once. Results can be retrieved in three ways: + + Treating the result as an iterable: + + .. code-block:: python + + for trace in result: + print(trace.name) + + Calling `.take` to process one or more batches of traces: + + .. code-block:: python + + first_100 = result.take(100) + process_batch(first_100) + + Calling `.takeone` to get a single trace: + + .. code-block:: python + + first = result.takeone() + second = result.takeone() + + print(first.name, second.name) + + """ + +
+[docs] + @abstractmethod + def total_results(self) -> int: + """ + Return the total number of hits. + + :return: Total number of hits + """ + pass
+ + +
+[docs] + def takeone(self) -> Optional[SearchTrace]: + """ + Return a single trace, if this stream is not exhausted. + + :return: A searchtrace, or None if no trace is available + """ + return next(self.__iter__(), None)
+ + +
+[docs] + def take(self, num: int) -> List[SearchTrace]: + """ + Return a list containing at most num number of traces, or less if they are not available. + + :param num: Number of traces to take + :return: List containing zero or more traces + """ + return list(islice(self.__iter__(), num))
+ + +
+[docs] + def close(self): + """ + Close this SearchResult if no more traces are to be retrieved. + + Required to keep compatibility with hansken.py. + """ + pass
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/search_sort_option.html b/0.9.16/_modules/hansken_extraction_plugin/api/search_sort_option.html new file mode 100644 index 0000000..089d124 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/search_sort_option.html @@ -0,0 +1,177 @@ + + + + + + + + hansken_extraction_plugin.api.search_sort_option — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.search_sort_option

+"""This module defines the sort options for a search within Hansken."""
+from enum import Enum
+
+
+
+[docs] +class Direction(Enum): + """ + Enumeration for sorting directions. + + Attributes: + ASCENDING: Sort in ascending order. + DESCENDING: Sort in descending order. + """ + + ASCENDING = 'ASCENDING' + DESCENDING = 'DESCENDING'
+ + + +
+[docs] +class SearchSortOption: + """ + Represents a search sort option consisting of a field and a direction. + + Attributes: + _field (str): The field to sort by. + _direction (Direction): The direction to sort in (ascending or descending). + """ + + def __init__(self, field: str = 'uid', direction: Direction = Direction.ASCENDING): + """ + Initialize a new SearchSortOption. + + Args: + field (str): The name of the field to sort on. + direction (Direction): The direction to sort (ascending or descending). + """ + self._field = field + self._direction = direction + +
+[docs] + def field(self): + """ + Get the field to sort on. + + Returns: + str: Returns the current field. + """ + return self._field
+ + +
+[docs] + def direction(self): + """ + Get the sorting direction. + + Returns: + Direction: Returns the current direction. + """ + return self._direction
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/trace_searcher.html b/0.9.16/_modules/hansken_extraction_plugin/api/trace_searcher.html new file mode 100644 index 0000000..d92527a --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/trace_searcher.html @@ -0,0 +1,154 @@ + + + + + + + + hansken_extraction_plugin.api.trace_searcher — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.trace_searcher

+"""This module contains the definition of a trace searcher."""
+from abc import abstractmethod
+from enum import Enum
+from typing import Optional, Union
+
+from hansken_extraction_plugin.api.search_result import SearchResult
+from hansken_extraction_plugin.api.search_sort_option import SearchSortOption
+
+
+
+[docs] +class SearchScope(str, Enum): + """Scope to describe the search context for TraceSearcher.search calls.""" + + image = 'image' + project = 'project'
+ + + +
+[docs] +class TraceSearcher: + """This class can be used to search for traces, using the search method.""" + +
+[docs] + @abstractmethod + def search(self, query: str, count: Optional[int] = None, scope: Union[str, SearchScope] = SearchScope.image, + start: int = 0, sort: list[SearchSortOption] = [SearchSortOption()]) -> SearchResult: + """ + Search for indexed traces in Hansken using provided query returning at most count results. + + :param query: HQL-query used for searching + :param start: Starting index of traces to return + :param count: Maximum number of traces to return + :param scope: Select search scope: 'image' to search only search for other traces within the image of the trace + that is being processed, or 'project' to search in the scope of the full project (either Scope- + enum value can be used, or the str-values directly). + :param sort: The fields and directions to sort on + :return: SearchResult containing found traces + """
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/tracelet.html b/0.9.16/_modules/hansken_extraction_plugin/api/tracelet.html new file mode 100644 index 0000000..ae367e5 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/tracelet.html @@ -0,0 +1,142 @@ + + + + + + + + hansken_extraction_plugin.api.tracelet — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.tracelet

+"""This module contains the definition of a Tracelet."""
+from typing import Any, Mapping
+
+
+
+[docs] +class Tracelet: + """ + A tracelet contains the values of a single fvt (Few Valued Type). + + A few valued type is a trace property type that is a collection of tracelets. A trace can contain multiple few + valued types containing one or more tracelets. For example, the `trace.identity`` type may look like this:: + + {emailAddress: 'interesting@notreally.com'}, + {firstName: 'piet'}, + {emailAddress: 'anotheremail@notreally.com'}, + + The trace.identity few valued types contains three different tracelets. + """ + + def __init__(self, name: str, value: Mapping[str, Any]): + """ + Initialize a tracelet. + + :param name: name or type of the tracelet. In the example this would be ``identity``. + :param value: Mapping of keys to properties of this tracelet. In the example this could be + ``{emailAddress: 'anotheremail@notreally.com'}``. + """ + self.name = name + self.value = value
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/transformation.html b/0.9.16/_modules/hansken_extraction_plugin/api/transformation.html new file mode 100644 index 0000000..b2fbdf6 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/transformation.html @@ -0,0 +1,193 @@ + + + + + + + + hansken_extraction_plugin.api.transformation — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.transformation

+"""This module contains the definition of a Transformation."""
+from abc import ABC
+from dataclasses import dataclass
+from typing import List
+
+
+
+[docs] +class Transformation(ABC): + """A super class for data transformations. Currently only :class:RangedTransformation is supported.""" + + pass
+ + + +
+[docs] +@dataclass(frozen=True) +class Range: + """A Range describes a range of bytes with a offset and length.""" + + offset: int #: the starting point of the data + length: int #: the size of the data
+ + + +
+[docs] +class RangedTransformation(Transformation): + """A :class:RangedTransformation describes a data transformation consisting of a list of :class:Range.""" + + def __init__(self, ranges: List[Range]): + """:type ranges: list of :class:Range.""" + self.ranges = ranges + +
+[docs] + @staticmethod + def builder(): + """:return a Builder.""" + return RangedTransformation.Builder()
+ + +
+[docs] + class Builder: + """Helper class that implements a transformation builder.""" + + def __init__(self) -> None: + """Initialize a Builder.""" + self._ranges: List[Range] = [] + +
+[docs] + def add_range(self, offset: int, length: int) -> 'RangedTransformation.Builder': + """ + Add a range to a ranged transformation by providing the range's offset and length. + + :param offset the offset of the data transformation + :param length the length of the data transformation + :return: this `.RangedTransformation.Builder` + """ + if offset is None: + raise ValueError('offset is required') + if length is None: + raise ValueError('length is required') + self._ranges.append(Range(offset=offset, length=length)) + return self
+ + +
+[docs] + def build(self) -> 'RangedTransformation': + """ + Return a RangedTransformation. + + :return: a :class:RangedTransformation + """ + return RangedTransformation(ranges=self._ranges)
+
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/hansken_extraction_plugin/api/transformer.html b/0.9.16/_modules/hansken_extraction_plugin/api/transformer.html new file mode 100644 index 0000000..eb934f6 --- /dev/null +++ b/0.9.16/_modules/hansken_extraction_plugin/api/transformer.html @@ -0,0 +1,243 @@ + + + + + + + + hansken_extraction_plugin.api.transformer — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for hansken_extraction_plugin.api.transformer

+"""
+This module contains the Transformer class that holds the function reference of the transformer.
+
+Instances of this class are constructed by BaseExtractionPlugin when retrieving transformers dynamically.
+It also validates whether the method to which @transformer is applied adheres to the requirements of a transformer.
+"""
+
+from datetime import datetime
+import inspect
+from typing import Mapping, Sequence
+
+from hansken.util import GeographicLocation, Vector
+
+from hansken_extraction_plugin.api.plugin_info import TransformerLabel
+from hansken_extraction_plugin.utility.type_conversion import get_type_name
+
+
+
+[docs] +class Transformer: + """ + A transformer is an exposed method of a plugin that can be executed remotely outside extraction-time. + + This allows for on-demand analysis during an investigation. + """ + + """ + This dictionary holds the supported types that transformer methods can as arguments and return types. + + The keys are the supported Python types and the values the generic type names as in the Hansken trace model. + Note that these types should also be defined in _primitive_matchers in runtime.pack for successful serialization. + In order to not create circular dependencies and separate the runtime module and the api module this is defined + separately here. + """ + supported_primitives = {bytes: 'binary', + bool: 'boolean', + int: 'integer', + float: 'real', + str: 'string', + datetime: 'date', + GeographicLocation: 'latLong', + Vector: 'vector', + Sequence: 'list', + Mapping: 'map'} + + def __init__(self, function): + """Create a transformer and validate whether the passed function meets the requirements.""" + self.function = function + + # Retrieve the signature so that we can validate whether it complies to the transformer requirements. + signature = inspect.signature(function) + + # Validate that @transformer was applied to a function/method and not any other type of object (i.e. a class) + if not function.__class__.__name__ == 'function': + raise Exception('@transformer was applied to something other than a function/method. ' + '@transformer may only be applied to methods of classes derived from BaseExtractionPlugin.') + + # Validate that @transformer was applied to a method instead of a function. + if '.' not in function.__qualname__: + raise Exception( + '@transformer was applied to a function instead of a method of a class derived from ' + 'BaseExtractionPlugin. ' + '@transformer may only be applied to methods of classes derived from BaseExtractionPlugin.') + + # Extract the method name for ease of use. + self.method_name = function.__qualname__.split('.')[1] + + # Validate if this function is not a static method. + # Note: This is not entirely foolproof since the self parameter may officially also be named differently or as + # a non-first argument. + if 'self' not in signature.parameters: + raise Exception('@transformer may not be applied to static methods.') + + # Validate all the parameters and store them. + self.parameters = {} + for parameter in signature.parameters.values(): + + # Other than validating the self property we don't include it in the parameters field because we do not + # want to expose it externally. + # Note: This check is not fool-proof since parameters called self can be defined as non-first parameters. + if parameter.name == 'self': + if parameter.annotation is not inspect.Parameter.empty: + raise Exception('@transformer methods should have a parameter self without a type annotation.') + else: + continue + + # Validate if annotations are present on each parameter. + if parameter.annotation is inspect.Parameter.empty: + raise Exception('The parameters of @transformer methods must have type hints.') + + # Validate that parameters do not have default values. + if parameter.default is not inspect.Parameter.empty: + raise Exception('@transformer methods are currently not allowed to have parameters with a ' + 'default value.') + + # Do not allow variable arguments or positional only arguments. + if parameter.kind in [parameter.POSITIONAL_ONLY, parameter.VAR_POSITIONAL, parameter.VAR_KEYWORD]: + raise Exception('@transformer methods are currently not allowed to have positional only parameters or ' + 'variable parameters (like *args and **kwargs).') + + # Validate if a parameter is one of the supported serializable types. + if parameter.annotation not in Transformer.supported_primitives.keys(): + raise Exception(f'The parameters of @transformer methods should be one of ' + f'{[get_type_name(x) for x in Transformer.supported_primitives]}') + + self.parameters[parameter.name] = parameter.annotation + + # Validate if the return annotation is present and one of the supported serializable types. + if signature.return_annotation not in Transformer.supported_primitives.keys(): + raise Exception(f'The return type of @transformer methods should be one of ' + f'{[get_type_name(x) for x in Transformer.supported_primitives.keys()]}') + + self.return_type = signature.return_annotation + +
+[docs] + def generate_label(self) -> TransformerLabel: + """ + Generate a TransformerLabel given the transformer method. TransformerLabels are used in PluginInfo objects. + + Unlike Transformers TransformerLabels can be serialized and sent to a client that wishes to call a transformer. + The specific Python types are converted to the generic types that are used in the Hansken trace model. + """ + # Convert the parameters to a generic Hansken parameter names. + # No checks are needed here because they are already performed upon initialization of a Transformer. + parameters = {name: self.supported_primitives[param_type] for name, param_type in self.parameters.items()} + return_type = self.supported_primitives[self.return_type] + return TransformerLabel(method_name=self.method_name, + parameters=parameters, + return_type=return_type)
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_modules/index.html b/0.9.16/_modules/index.html new file mode 100644 index 0000000..abd079e --- /dev/null +++ b/0.9.16/_modules/index.html @@ -0,0 +1,120 @@ + + + + + + + + Overview: module code — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/0.9.16/_sources/changes.rst.txt b/0.9.16/_sources/changes.rst.txt new file mode 100644 index 0000000..3277514 --- /dev/null +++ b/0.9.16/_sources/changes.rst.txt @@ -0,0 +1,15 @@ +.. _changelog: + +Changelog +========= + +The following page lists all (technical) changes in the extraction plugin SDK. + +Programming language specific API changes are described in more detail on API changelog pages. +These pages list new API functionalities, and describe how to update your plugins when API changes are in order. +For the API changelog pages see: + +* :doc:`dev/java/api_changelog` +* :doc:`dev/python/api_changelog` + +.. mdinclude:: ../CHANGES.md diff --git a/0.9.16/_sources/contact.md.txt b/0.9.16/_sources/contact.md.txt new file mode 100644 index 0000000..073d2ad --- /dev/null +++ b/0.9.16/_sources/contact.md.txt @@ -0,0 +1,16 @@ +# Contact + +Please get in touch with us: + +* if you have questions about the SDK, +* have found a bug, +* have a feature request, +* see other opportunity to improve, +* want to contribute, +* ... + +Chat with us on [Discord](https://www.discord.com). You can find members of the extraction plugin SDK development team +in the Hansken Community server, in the `extraction-plugins` channel. This is a Hansken community-private server. If you +don't have access to the Hansken Community server, please contact your Hansken business owner. He or she can invite you +to the Hansken Community server. If you don't know who to contact, feel free to fill in +the [contact form](https://www.hansken.nl/contact) for further questions/contact. diff --git a/0.9.16/_sources/dev/concepts.rst.txt b/0.9.16/_sources/dev/concepts.rst.txt new file mode 100644 index 0000000..7348949 --- /dev/null +++ b/0.9.16/_sources/dev/concepts.rst.txt @@ -0,0 +1,21 @@ +General concepts +================ + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + concepts/extraction_plugins + concepts/anatomy_of_a_plugin + concepts/plugin_types + concepts/plugin_naming_convention + concepts/traces + concepts/hql_lite + concepts/data_transformations + + concepts/test_framework + concepts/all_in_one_debugging + + concepts/isolation + concepts/kubernetes_autoscaling + diff --git a/0.9.16/_sources/dev/concepts/all_in_one_debugging.md.txt b/0.9.16/_sources/dev/concepts/all_in_one_debugging.md.txt new file mode 100644 index 0000000..18df95f --- /dev/null +++ b/0.9.16/_sources/dev/concepts/all_in_one_debugging.md.txt @@ -0,0 +1,33 @@ +# Debugging locally with Hansken All in One (AIO) + +.. note:: this feature is available from Hansken 46.4.0 + +.. warning:: `DeferredExtractionPlugin` are currently NOT supported + +It is also possible to debug an Extraction Plugin with a locally running Hansken AIO. This requires a few steps: + +1. Start your plugin in your IDE (default port 8999) + ![1_debug_start_plugin_in_ide.png](1_debug_start_plugin_in_ide.png) +2. Set some breakpoint(s) + ![2_debug_set_breakpoints.png](2_debug_set_breakpoints.png) +3. Prepare an extraction in the AIO **with advanced** options + ![3_debug_prepare_extraction.png](3_debug_prepare_extraction.png) +4. Enable the `DebugExtractionPluginTool` for this extraction + ![4_debug_enable_debug_tool.png](4_debug_enable_debug_tool.png) +5. Start extraction, and happy debugging! + +## Tips/notes + +- You can only debug 1 plugin at a time + - .. note:: If you are debugging `MyPlugin`, and it is also visible in the tools list, then you need to **disable** it, and **only enable** the `DebugExtractionPluginTool` +- Test your plugin with a small image. Otherwise, it might take long before you reach your breakpoint. +- Be careful when using this debugger with `APPEND` extractions: + - Similar to other tools/plugins, the `DebugExtractionPluginTool` will only run once per trace + - So if you need to re-run your debug session, then we advise you to re-extract `(INDEX)` your project instead +- Hansken runs multiple instances of every Tool, so the same breakpoint can be hit multiple times concurrently by + different instances + - limiting the number of plugin threads/workers can minimize this + - see [Specifying system resources (Python)](../python/snippets.md#Specifying system resources) +- Only restart your plugin before starting an extraction. Restarting your plugin **during** an extraction can + produce + **undefined behaviour**. diff --git a/0.9.16/_sources/dev/concepts/anatomy_of_a_plugin.md.txt b/0.9.16/_sources/dev/concepts/anatomy_of_a_plugin.md.txt new file mode 100644 index 0000000..c8c6ff4 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/anatomy_of_a_plugin.md.txt @@ -0,0 +1,72 @@ +# Anatomy of a plugin + +This page describes the general anatomy of a plugin, and its (simplified) execution in Hansken. + +## The plugin itself + +Each plugin must implement two methods: + +* `pluginInfo()`: This method returns information about the plugin. +* `process()`: This method performs the extraction task of the plugin. + +Let's dive a bit deeper into these methods in the next sections! + +### The method `pluginInfo()` + +The `pluginInfo()` method returns a `PluginInfo` object. Hansken needs this object to be able to know the capabilities +of the plugin, and to show the plugin in the list of tools. The most important fields that must be set on `PluginInfo` +are the following: + +| `id` | The identifier of the plugin. This will be used as a unique name for the plugin Hansken. | +| `description` | A description of the plugin that is shown in Hansken. | +| `author` | The author of the plugin that is shown in Hansken. | +| `license` | The type of license of the plugin that is shown in Hansken. | +| `matcher` | This matcher is used by Hansken to determine which Traces are sent to the Plugin during extraction. | + +### The method `process()` + +During extraction, Hansken calls the `process()` method for every matching trace. The `matcher` attribute of +the `PluginInfo` is very important as it determines which traces will be sent to the `process` method. + +Although the plugin developer is free to program whatever seems useful, the following tasks are typically performed +within the `process()` method: + +* Creating child-traces +* Reading trace properties +* Adding trace properties +* Reading the data that the Trace represents +* Writing data on a Trace + +Depending on the type of plugin that is implemented, different functionality is available in the `process()` method. +See [Plugin Types](plugin_types.md) for more details. + +## The execution in Hansken + +This describes the process of running a plugin from the perspective of Hansken. The perspective of the user is described +in [Hansken Extraction Plugins](extraction_plugins.md). + +### Plugin discovery + +Hansken manages a list of tools that can be used in extractions. The available plugins must be added to this list so +that the user can select them. To accomplish this, Hansken scans the Docker registry for docker images that are plugins. +Each image is started up, and a call is done to its `pluginInfo()` method. If the call resulted in a valid `PluginInfo` +object, the Extraction Plugin is added to the list of tools visible to users. After the `PluginInfo` is retrieved, the +docker image is shutdown again. + +### Starting an extraction + +Hansken checks if any plugins are selected by the user that started the extraction. For each selected plugin, at least +one docker image will be started. See [Kubernetes autoscaling](kubernetes_autoscaling.md) for more details on expanding +the number of instances for each plugin. + +### Extracting + +During an extraction, Hansken will iteratively loop through all selected tools, including Extraction Plugins. For each +trace that matches on a tool, Hansken will call its `process` method. For Extraction Plugins, this means that +the `process` method is called via the gRPC protocol. The trace to be processed is sent over gRPC to the plugin, and any +other communication between Hansken and the Extraction Plugin (like created properties and child traces, search requests +and written data) are done using gRPC. + +### Finishing an extraction + +At the end of an extraction, Hansken will stop all associated plugins. diff --git a/0.9.16/_sources/dev/concepts/data_transformations.md.txt b/0.9.16/_sources/dev/concepts/data_transformations.md.txt new file mode 100644 index 0000000..116c0a5 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/data_transformations.md.txt @@ -0,0 +1,24 @@ +# Data Transformations + +Extraction Plugins can create new :ref:`data-streams ` on a Trace through data transformations. Data +transformations describe how data can be obtained from a source. Data transformations are preferred over storing blobs +because they take less space. This is because they only describe the data instead of specifying the actual data. + +The following figure shows how Hansken visualizes data transformations: +![datatransformations.png](datatransformations.png) +Note that transformations can be applied on transformations. The SDK only supports range transformations at the moment, +while this image also shows some transformations that are currently available in Hansken but not in the SDK. + +An example case is an extraction plugin that processes an archive file. The plugin creates a child trace per entry in +the archive file. Each child trace will have a data stream that is a transformation that marks the start and length of +the entry in the original archive data. By just describing the data instead of specifying the actual data, a lot of +space is saved. + +Although Hansken supports various transformations, the Extraction Plugins SDK for now only supports ranged data +transformations. Ranged data transformations define data as a list of ranges, each range with an offset and length in a +bytearray. + +## See also + +* [Data Transformations in Java](../java/snippets.md#Data Transformations) +* [Data Transformations in Python](../python/snippets.md#Data Transformations) diff --git a/0.9.16/_sources/dev/concepts/extraction_plugins.md.txt b/0.9.16/_sources/dev/concepts/extraction_plugins.md.txt new file mode 100644 index 0000000..ced3be4 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/extraction_plugins.md.txt @@ -0,0 +1,59 @@ +# Hansken Extraction Plugins + +Hansken Extraction Plugins enable Hansken users to add their own extraction tools to Hansken. + +To use an Extraction Plugin in Hansken, the following steps have to be done: + +1. Build the plugin +2. Upload the plugin to Hansken +3. Refresh the Hansken tools list +4. Start an extraction with the plugin enabled + +## Building a plugin + +Hansken Extraction Plugins can be built in Java or Python by implementing an interface. Which interface you choose +depends on the type of plugin you choose to make, see [Plugin Types](plugin_types.md). For more information on coding +your own plugin, see the [Extraction Plugin Examples](https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples). + +The plugin can then be tested using the [Test Framework](test_framework.md). This way you make sure everything works as +expected before taking further steps. + +## Package the plugin + +To upload a plugin into Hansken, a docker image for this plugin must be uploaded to the docker registry. First, the +plugin container image must be packaged. +A plugin is packaged into an OCI image (also known as Docker image). + +* [Package a docker image for a Python plugin](../python/packaging.md) +* [Package a docker image for a Java plugin](../java/packaging.md) + +.. _upload_plugin: + +## Upload the plugin to Hansken + +Hansken finds the plugins by scanning a docker registry. It will try to load all docker images with a certain prefix as +Extraction Plugins. The settings for this are defined in Hansken properties: + +* `registry.extraction.plugins.registry.uri` defines the registry +* `registry.extraction.plugins.registry.prefix` defines the prefix plugins must have + +When the image is packaged locally, it needs to be pushed (uploaded) to the docker registry. These commands provide an +outline of how to do this: + +* `docker login ` (make sure you are logged in to the registry) +* `docker push ` (push the plugin docker image to the registry) + +.. note:: For more information about uploading plugins and running them in Hansken, see the 'Using extraction plugins in + Hansken' chapter of the *Hansken User Guide*. + +## Refresh the Hansken tools list + +Hansken checks which plugins are available at startup. The list of available plugins can also be refreshed by calling +the following endpoint: `/gatekeeper/tools?refresh=true` + +This can be invoked via an internet browser. + +## Start an extraction with the plugin enabled + +If everything went well, the list of available tools in Hansken should now feature your plugin. To run the plugin in an +extraction, be sure to select its checkbox in the extraction tools dialog. diff --git a/0.9.16/_sources/dev/concepts/hql_lite.md.txt b/0.9.16/_sources/dev/concepts/hql_lite.md.txt new file mode 100644 index 0000000..877576e --- /dev/null +++ b/0.9.16/_sources/dev/concepts/hql_lite.md.txt @@ -0,0 +1,375 @@ +# HQL-Lite + +## Overview + +HQL-Lite is a query language derived from Hanskens full HQL human. HQL stands for Hansken Query Language and can be +used to search or match traces. Since not all elements of full HQL can be used in the context of an extraction, +extraction plugins use HQL-Lite, a lightweight version of HQL. This document describes the usage of HQL-Lite in the +context of extraction plugins. + +.. _howdoeshanskenwork: + +## How does Hansken work? + +- Let's say we have a Hansken image `hansken_image1` with 10 pdf files, and 5 jpegs. +- And our Hansken contains 2 tools: + - PdfPlugin + - JpegTool + +.. note:: All plugins are Hansken tools, but not all Hansken tools are plugins. Some tools are included in Hansken core. + +Let's look at a (simplified) pseudocode example of the inner workings of Hansken: + +```python + for each trace in new_traces { + for each datastream in trace { + for each tool in hansken_tools { + if tool.can_this_tool_process_the_provided_trace(trace, datastream) { + tool.process_the_trace(trace, datastream) + } + } + } + } +``` + +So in this example we know the following: + +- `new_traces` has + - 10 pdf files + - 5 jpeg files +- `hansken_tools` contains: + - PdfPlugin + - JpegTool + +So the question here is, how do we prevent that traces are not processed by incompatible tools? + +The answer is the `tool.can_this_tool_process_the_provided_trace()` part of the pseudocode. + +### What does `can_this_tool_process_the_provided_trace()` do? + +Hansken actually contains many more tools/plugins than these 2, and instead of 15 files/traces, we usually deal with +millions. + +.. note:: If each trace has 1 extra second of overhead, 1 million traces would take 11.5 days of extra CPU time + +#### Matchers to the rescue + +To reduce the unnecessary overhead of processing all traces (even the ones the tool cannot actually process), Hansken +implements the concept of a `matcher` for each tool. This _matcher_ basically checks the _trace_ for _"matching +conditions"_, that would allow the tool to process it. + +Sometimes these _matching conditions_ can be as simple as a specific `filename` or `extension`, but are often more +elaborate in the sense that they check multiple factors that require some intimate knowledge of Hansken. + +## What is HQL-Lite? + +HQL-Lite is a language based on HQL (Hansken Query Language) that allows plugin developers to write _matchers_ for +Hansken Extraction Plugins. It could be said that HQL-Lite contains a subset of HQL features, plus some HQL-Lite unique +features that are only interesting for _matchers_. + +.. note:: + Please note that even though the HQL-Lite query is part of the plugin, it is compiled and stored in Hansken during + startup to achieve performance. + +### Why not just use HQL for plugins? + +HQL was designed to search for traces stored in the Elasticsearch database. As such, some of its features are tightly +coupled to the Elasticsearch implementation, making it difficult to re-implement them for plugins. + +Also, even though HQL is more complex than the requirements for _matching_ in plugins, a couple of minor features that +are absolutely necessary for _matching_ are not implemented in HQL, as they don't make much sense from a search point of +view. This is because HQL was designed to be used with _finished extractions_ with all the traces stored in the +database, while HQL-Lite was designed for _active extractions_. + +.. _hqllite syntax: + +### HQL-Lite syntax + +| Matcher | Syntax | remarks | +|----------|------------------------|--------------------------------------------------------------------------------------------------------| +| All | `""` | an empty string translates to match for __all__ traces | +| And | `foo:1 AND bar:2` | the case-sensitive `AND` operator behaves like a logical AND of 2 conditions | +| Not | `NOT foo` or `-foo` | the case-sensitive `NOT` or `-` negates the expression that follows | +| Range | `foo>1` or `1<=foo<10` | a numbered-range check with a min or/and max range(s) | +| Or | `foo:1 OR bar:2` | the case-sensitive `OR` operator behaves like a logical OR of 2 conditions | +| Data | `$data.foo:1` | see `$data` section below | +| DataType | `$data.type:raw` | this query matches against the type of the current datastream | +| Types | `type:email` | this query checks if the trace contains a certain trace type as defined in the Hansken trace model | + +There are also a couple of general guidelines that apply to all matchers: + +- Equals/not equals: + - `:` or `=` : The most basic of left equals right statements. note that `=` is also valid. + - `!=` : The opposite of equals, not equals. Note that `!:` is __NOT__ supported. +- Wildcards: + - `?` : Match against any single character. E.g. `foo:r?w` will match against `raw, row` but not against `rowing`. + - `*` : Match against any chars. E.g. `foo:r*` will match against `r, ra, raw, raaaaaw` but not against `aw`. +- Exact match: By surrounding a value with quotes, we tell the parser that it is a single value. This is especially + helpful for values that might contain separators. E.g. `foo:'hello hql-lite'`. +- CSV: Currently only the `type` query supports multiple values to check against. E.g. `type:email,chatMessage` will only + return `true` if both types exist for this trace. +- `()` grouping: You can group statements by putting brackets around them. E.g. `foo:1 AND (bar:2 OR bla:3)` which + translates to `foo:1` plus one of the statements in the brackets. +- Escaping `\"\\ .\t\r\n:=> this is the regex matcher, which is unsupported in HQL-lite + - `foo:c:\` -> should be `foo:c\:\\`, both the `colon` and the `slash` need to be escaped + - `foo:'c:\'` -> should be `foo:'c:\\'`, the `slash` still needs to be escaped + - .. note:: the backslash is the universal escape character, so it **always** needs to be escaped. + +#### $data matchers + +In Hansken, a trace can have multiple :ref:`datastreams `. The exact content of said datastreams is +discussed elsewhere, but the basic idea is that a trace can have multiple representations. For example, a trace might +have a `raw` datastream, but after we identify that the raw bytes contain a __text__ file, we might add a separate +datastream `text`. + +.. note:: + The `process()` method of each plugin is called for each datastream of each trace. This is explained + in :ref:`How does Hansken work? ` . Subsequently, you might have the same property for a + different datastream. For example: you might have a `data.raw.size` and a `data.text.size` property. The reason you + might have the same property multiple times, is because it could have a different meaning. + +For example: + +- data.raw.size: is the size in bytes +- data.text.size: is the number of bytes in the text representation of the raw stream + +If we want to check if either of these properties is not empty by using a `$data` matcher, we do: + +```text + $data.size>0 +``` + +##### When is it useful to use a $data matcher? + +For example, there is a simple plugin called `LetterCountPlugin`, that counts the letters in text based datastreams. + +So to match on these text based datastreams, we have 2 choices: + +- List all the possibilities + - Which is too tedious, and not very flexible when new types are supported +- Match on a common property + - More compact, but sometimes difficult to find a common property + +In this case we might match on mimeType, which we know is `text/plain` or `text/x-log` for 2 of types we want to match: + +```text + $data.mimeType=text\\/* +``` + +This will match the following: + +- `data.text.mimeType=text\\/plain` +- `data.text.mimeType=text\\/not\\ plain` +- `data.pdf.mimeType=text\\/encoded` +- `data.foo.mimeType=text\\/bar` + +But will __not__ match any of the following: + +- `data.text.mimeType=txt` +- `data.text.mimeType=pdf` +- `data.text.mime=text\\/plain` +- `data.foo.bar=text\\/plain` + +## How to write a matcher? + +The functional requirements for writing a matcher can be summarized in the following: + +1. What does my plugin expect as input? +2. How can I describe that input with the information Hansken provides? + +### PdfPlugin example + +Let's say we just finished writing a `PdfPlugin`. This is a simple plugin that checks if pdf files contain the +word `the`. + +So let's go over our checklist: + +#### _What does my plugin expect as input?_ + +PDF files. + +#### _How can I describe that input with the information Hansken provides?_ + +Hansken consumes and produces :ref:`Traces `. To that effect, we can only match on trace properties that are +available in Hansken. + +##### Match on extension + +The easiest way would be to only allow traces with the `.pdf` extension. Looking at the :ref:`Hansken trace model` (or a +Hansken extraction), we can see that there's a property `file` +which contains a property `extension`. + +So what would that look like in HQL-lite? Something like + +```text + file.extension=pdf +``` + +.. warning:: This of course **only** works if the file has the correct extension (note that matchers are case-sensitive). + +So what do we do, if we also want to match pdf files that are (un)intentionally misnamed? + +##### Match on mime-type + +Looking at Wikipedia, we see that `pdf` has a couple of mime-types. In return looking at our extraction and the +trace-model, we see both at `data.raw.mimeType`, with a further explanation in the :ref:`Hansken trace model` that +the `raw` portion of the property is the __data type__ of the datastream. + +If we don't know which datastream has the `mimeType` property beforehand, we could use the broad-scoped `$data.` matcher +to look at every datastream. + +So our matcher becomes: + +```text + file.extension=pdf OR + ( + $data.mimeType=application\\/pdf OR + $data.mimeType=application\\/x-pdf + ) +``` + +##### Match on data size + +Some pdf files can be huge, meaning that parsing them will need a lot of resources. Could we add a data size check to +the matcher? According to the :ref:`Hansken trace model` `data` has a property `size` (similar to `mimeType`) that we +could use for this. + +.. note:: This is also a good way to check if a file is empty or not. + +Let's say our cutoff limit is 1 MB, meaning our matcher becomes: + +```text + 0 < $data.size < 1000000 AND + ( + file.extension=pdf OR + ( + $data.mimeType=application\\/pdf OR + $data.mimeType=application\\/x-pdf + ) + ) +``` + +##### Match if 'property is set' + +It is not uncommon to have some overlap between tools/plugins. For example: + +- PdfPlugin: a plugin that only supports pdf documents +- DocumentPlugin: this plugin supports a lot of document types, including `pdf`. + +So how would we prevent our plugin from processing a trace that has already been processed by the `DocumentPlugin`? + +The easiest solution would be to check if a certain property has already been set. Meaning, that if both plugins set +the `foo.bar` property, we check if said property has already been set. + +So we __only__ process the trace if `foo.bar` is __empty__, meaning our matcher becomes: + +```text + foo.bar!=* AND + 0 < $data.size < 1000000 AND + ( + file.extension=pdf OR + ( + $data.mimeType=application\\/pdf OR + $data.mimeType=application\\/x-pdf + ) + ) +``` + +##### Match on excluding a certain path + +It is also not uncommon to exclude certain paths from your plugin. These paths might contain invalid or encrypted files, +for example. + +So let's say we want to exclude all files under in the `/tmp/virus` path. How do we go about it? + +Again, we check our extraction/:ref:`Hansken trace model`, and we see that `file.path` looks promising. + +So excluding `/tmp/virus` would look something like: + +```text + -file.path=/tmp/virus* AND + foo.bar!=* AND + 0 < $data.size < 1000000 AND + ( + file.extension=pdf OR + ( + $data.mimeType=application\\/pdf OR + $data.mimeType=application\\/x-pdf + ) + ) +``` + +.. _hql datastreams: + +##### Match on specific datastream type, an anti-pattern + +.. warning:: Matching on specific datastream types is an anti-pattern! It is not recommended to match on a datastream + type. Instead one should match on other datastream properties, such as `fileType`, `mimeType` or `mimeClass`. + The reason for this is explained in the paragraph below. + +Using a matcher that is too loose or too tight can yield unexpected results. Usually one will match on properties +of a datastream like `fileType`, `mimeType` or `mimeClass` as these are reliable properties that have been added by +Hansken tools. Matching on a specific datastream says nothing about the type of file. For example a PDF file may be +available in a `raw` as well as in a `decrypted` datastream. By matching on the datastream type one may exclude traces +that were not intended to be excluded. +Contrarily, note that matching on a datastream type may include *more* traces than you expected as well. For example, +someone may think "Plugin A puts data on the `plain` datastream, so I'll match on the `plain` datastream with Plugin B", +forgetting that `plain` may be used by other tools as well. In other words, there may be traces with that datastream +type that you did not know of, potentially crashing your plugin. See :ref:`datastreams` for more information. + +Now that you know why it is an anti-pattern, lets explain how it would be done (for those edge cases where it's needed): +Lets say we want our `PdfPlugin` to __ONLY__ process `raw` datastreams. +The best way to do this would be to match +on `$data.type:raw`. Note that `$data.type` matches against the type of the current datastream, so in this case it +matches only when the current datastream is of type `raw`. + +An __incorrect__ way to do it would be to replace `$data.` matcher(s) with `data.raw.`. This means the matcher +will match whenever a trace has this datastream type, even if the current datastream type is different. +Remember that the `process` method of an extraction plugin is always called once for each datastream on each trace. +For example, lets say a trace has two datastreams, `raw` and `text`. The matcher would match for both the datastreams +because the trace has a `raw` datastream (even though the current datastream type may be `text`). This results in the +`process` method being called twice (for `raw` and for `text`), which may lead to other bugs if the developer doesn't +know this. For example, the second time the plugin may be trying to overwrite data on a trace which is prohibited. + +So, using `$data.type`, our matcher would look like: + +```text + $data.type:raw AND + -file.path=/tmp/virus* AND + foo.bar!=* AND + 0 < $data.size < 1000000 AND + ( + file.extension=pdf OR + ( + $data.mimeType=application\\/pdf OR + $data.mimeType=application\\/x-pdf + ) + ) +``` + +## How precise should a matcher be? + +In practice, only you as the plugin dev can answer this question. + +Know that from the point of view of Hansken, we only care that the plugin: + +- __Should not crash__: If a matcher does not compile, then your plugin will not be available in Hansken. Tip: be sure + to test your plugin with the :ref:`test framework `. +- __Should not be slow__: Matching is designed to be extremely fast, but of course, if you make it too complex it can + take longer than we want. In the example above, we calculated that 1 second extra for 1 million traces is 11 days of + extra CPU time. Unlike processing, matching is done for __every trace__, in every extraction iteration, so be careful! +- __Should match on the bare minimum__: Don't go too far by matching 50 different criteria before allowing a trace to be + processed. Note that a lot of (if not all) of these criteria depend on properties set by other tools, and you don't + really have any control on how these tools work. diff --git a/0.9.16/_sources/dev/concepts/isolation.md.txt b/0.9.16/_sources/dev/concepts/isolation.md.txt new file mode 100644 index 0000000..8932753 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/isolation.md.txt @@ -0,0 +1,28 @@ +# Plugin isolation + +Extraction plugins allows arbitrary code to be executed during a Hansken extraction. This code is executed inside the +Hansken cluster. Extraction plugins are subjected +to [Hanskens design principles](https://www.sciencedirect.com/science/article/pii/S1742287615000857?via%3Dihub) +such as security, privacy and transparency. To ensure that plugins are compliant to these principles, each plugin will +be executed in isolation. This page describes the isolation measures that are in place. + +## User isolation + +The following user restrictions are implied on the plugin: + +* The plugin can not run as `root`. +* Instead, the plugin will run as user `1000` +* and with group `2000` +* and with fsgroup `3000` + +## System calls + +Plugins are only allowed to call a limited set of (Linux) system calls. This ensures that a plugin can be executed in a +secure manner within the Hansken platform. + +Hansken uses Kubernetes to run extraction plugins. The Kubernetes `RuntimeDefault` secure computing mode (`seccomp`) is +enabled to provide a sane default of available system calls. + +## Network isolation + +Plugins are not allowed to communicate over the network. diff --git a/0.9.16/_sources/dev/concepts/kubernetes_autoscaling.md.txt b/0.9.16/_sources/dev/concepts/kubernetes_autoscaling.md.txt new file mode 100644 index 0000000..6ffa7b4 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/kubernetes_autoscaling.md.txt @@ -0,0 +1,27 @@ +# Kubernetes, Autoscaling, Resourcemanagement + +Extraction Plugins can be run in a Kubernetes cluster. This can be the same cluster Hansken run on, or another external +cluster. For each plugin, a *pod* is created by Hansken. Each plugin will have 12 threads by default to process traces +separately within one pod. + +## Autoscaling + +Hansken will create a Horizontal Pod Autoscaler (*HPA*) for each pod. HPA's manage the number of replica's of a pod +based on metrics. The Extraction Plugins SDK provides two metrics to be set in the PluginInfo: + +* Observed CPU utilization +* Observed memory usage + +For more info on how to set these metrics follow these links: + +* [Specifying system resources (Java)](../java/snippets.md#Specifying system resources) +* [Specifying system resources (Python)](../python/snippets.md#Specifying system resources) + +If a pod reaches the CPU or memory usage provided with the PluginInfo, the HPA will increase the number of replicas for +that plugin. Scaling down is done automatically. The maximum number of replicas per pod is specified within Hansken +properties and can be adapted by an operator (needs restart). + +## Finding the right settings + +This depends on the kubernetes cluster settings, the nodes it runs on, and of course the plugin itself. Monitor the +number of replica's and resource metrics while an extraction is running and adapt accordingly. diff --git a/0.9.16/_sources/dev/concepts/plugin_naming_convention.md.txt b/0.9.16/_sources/dev/concepts/plugin_naming_convention.md.txt new file mode 100644 index 0000000..cd0e9ad --- /dev/null +++ b/0.9.16/_sources/dev/concepts/plugin_naming_convention.md.txt @@ -0,0 +1,44 @@ +# Plugin naming convention + +## Plugin identifier + +Each extraction plugin has a unique identifier. The identifier consists of three fields. These three fields combined +form the plugin name. + +The three fields of a plugin identifier are: *domain*, *category*, and *name*. The fields are described in more detail +below. + +**domain** +The domain name of the organisation where the plugin is created. If an organisation has multiple domain names, the +shortest name is preferred over the longer domain names. Examples: `nfi.nl`, `politie.nl`, `fiod.nl`, `hansken.org`. + +**category** +A type of action that the plugin performs. The category is a free text field, but the following table gives some +recommendations. + +| Category | Description | +|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| ``extract`` | The plugin parses a clear data structure | +| ``carve`` | The plugin parses data fragments to reassemble traces in the absence of filesystem metadata | +| ``classify`` | The plugin categorizes a plugin based on its content, e.g. detecting money on traces of type `picture` | +| ``digest`` | The plugin digests data to compute a hash | +| ``ocr`` | The plugin applies ocr (optical character recognition) to read text on `pictures` or scanned documents | +| ``match`` | The plugin matches a trace against a database, and reports whether there was hit or miss, e.g. matching a trace to a well known files database | + +**name** +The name of the plugin, or in the classic sense, a description detailing what the plugin processes. Note that the name +can contain (forward) slashes. + +## Examples + +The following table shows a list of plugin identifiers. The last column of the table shows the derived full plugin name. +The derived full plugin name will be shown in Hansken. + +| Domain | Category | Name | Derived plugin name | Explanation | +|-----------------|--------------|-----------------|------------------------------------|-------------------------------------------------------------------------------------------------------------| +| ``hansken.org`` | ``extract`` | ``archive`` | ``hansken.org/extract/archive`` | A plugin created by the Hansken development team that extracts traces from an arbitrary ``archive`` format | +| ``nfi.nl`` | ``extract`` | ``archive/zip`` | ``nfi.nl/extract/archive/zip`` | A plugin created by an NFI team that extracts traces from a specific ``archive`` format: ``zip`` | +| ``politie.nl`` | ``extract`` | ``archive/zip`` | ``politie.nl/extract/archive/zip`` | The same as the previous example, but now the plugin is created by a different organisation: ``politie.nl`` | +| ``hansken.org`` | ``carve`` | ``archive/zip`` | ``hansken.org/carve/archive/zip`` | A plugin that carves data to detect a specific ``archive`` format: ``zip`` | +| ``hansken.org`` | ``digest`` | ``sha256`` | ``hansken.org/digest/sha256`` | A plugin that digests data to compute a ``sha256`` hash | +| ``hansken.org`` | ``ocr`` | ``tesseract`` | ``hansken.org/ocr/tesseract`` | A plugin that performs ocr using ``tesseract`` | diff --git a/0.9.16/_sources/dev/concepts/plugin_types.md.txt b/0.9.16/_sources/dev/concepts/plugin_types.md.txt new file mode 100644 index 0000000..cb53fc9 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/plugin_types.md.txt @@ -0,0 +1,77 @@ +# Extraction plugin types + +Currently four types of Hansken Extraction Plugins are supported: + +* Standard Extraction Plugins +* Meta Extraction Plugins +* Deferred Extraction Plugins +* Deferred Meta Extraction Plugins (Python only) + +## Standard Extraction Plugins + +Standard Extraction Plugins provide enough functionality for most cases. This includes: + +* Processing traces +* Creating child-traces +* Reading trace properties +* Adding trace properties +* Reading data +* Writing data +* Writing [data transformations](data_transformations.md) + +## Meta Extraction Plugins + +Meta Extraction Plugins can only process and produce trace properties without the need (or possibility) for processing +actual trace data. This includes: + +* Processing traces +* Creating child-traces +* Reading trace properties +* Adding trace properties + +.. _deferred extraction plugins: + +## Deferred Extraction Plugins + +These plugins have two additional features that are not included with Standard Extraction Plugins: + +* a developer can choose to *defer* their execution +* information about other traces can be obtained while processing the current extraction trace. Code examples can be + found here: :ref:`Java `, :ref:`Python `. + +*Deferring execution* +A single Hansken image extraction consists of multiple *iterations*. Within every *iteration*, every Hansken tool and +plugin is executed on matching traces, which produces new traces or modifies existing traces. If a tool can be executed +another time because of these additions or modifications, another iteration is started. + +A regular plugin is executed in the same iteration a trace is matched. Deferred plugins are executed in a different +iteration; they are always deferred for at least one iteration. This is very useful when searching for traces, because +you are certain the deferred plugin is executed after all other tools performed their modifications. + +Sometimes, executing your plugin in the next iteration is not enough; it needs to be executed in a different iteration. +This is why the SDK allows setting a *deferredIterations* parameter in the plugin info. After the plugin matches with a +trace, it will be executed after *deferredIterations*. The execution can currently be deferred by a maximum of **20** +iterations and the default is **1**. + +*Searching for traces* +This type of plugin can perform a search to look for extracted traces in the current **image** (default) or +**project** (optional). This search is performed using a provided **HQL** query. +A maximum of **50** traces is returned for a given search request. + +.. warning:: Please note that HQL-Lite specific syntax such as the `Data` or `DataType` matchers is **NOT** supported. + +## Deferred Meta Extraction Plugins + +These plugins have two additional features that are not included with standard Extraction Plugins: + +* a developer can choose to *defer* their execution +* information about other traces can be obtained while processing the current extraction trace. Code example can be + found here: :ref:`Python `. + +Deferred Meta Extraction Plugins can only process and produce trace properties without the need (or possibility) for processing +actual trace data. This includes: + +* Processing traces +* Creating child-traces +* Reading trace properties +* Adding trace properties diff --git a/0.9.16/_sources/dev/concepts/test_framework.md.txt b/0.9.16/_sources/dev/concepts/test_framework.md.txt new file mode 100644 index 0000000..a937c31 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/test_framework.md.txt @@ -0,0 +1,276 @@ +# Test framework + +.. _test_framework: + +The SDK provides the _FLITS Test Framework_ for integration testing. This allows us to test/validate the plugin input +and output without having a running Hansken instance. + +To use the test framework, three components are required: + +1. A running server instance of an extraction plugin. See section :ref:`How to test your plugin `. +2. Input test data +3. Results (expected output) + +## Creating test data + +The test data is independent of which programming language is used for the plugin (Java or Python). This section +describes the setup of the test data, while the sections thereafter will link to the language specific documentation. + +.. _basictestdata: + +### Basic test data directory structure + +Example test data directory structure with an `inputs` and `results` directory: + +```text +tests/ +├── inputs +│  ├── example1.raw +│  ├── example1.text +│  ├── example1.trace +│  ├── example2.raw +│  └── example2.trace +└── results +   ├── example1.raw.PluginName.trace +   ├── example1.text.PluginName.trace +   └── example2.raw.PluginName.trace + ``` + +The `inputs` folder contains all traces that will be processed during the test. These 'input traces' are defined in +files with the '.trace' extension, using JSON. This JSON structure is explained in section +:ref:`Trace format`. Each trace may have various :ref:`data-streams`. The data for each trace +is put into separate files for each data-stream. The data-stream files need to have the same name as their corresponding +trace file but differ in extension. They can have any extension, for example 'raw', 'text' or 'jpeg'. __Note that one +input trace will always have one '.trace' file, and can have none, one or many data files.__ Also note that if the +plugin doesn't match on any of the input files and there are no result files yet, the test will succeed. + +.. note:: The test-framework uses the extension of the input test file(s) _(other than __.trace__)_ as type of the + current data-stream. + +The expected results (which are also traces) are stored in a separate `results` folder next to the `inputs` folder. The +file names in the `results` folder correspond to the file names in the `inputs` folder. Note that the name of the plugin +is added between the file basename and the file extension. This can be useful if one maintains a single test input and +output test datasets for multiple extraction plugins. + +.. note:: It is possible to let the test framework regenerate the results files automatically. See the + :ref:`Java` and :ref:`Python` sections on testing on how to do this. If no files are + being generated, check if the plugin matcher is actually matching the input files. + +The test runner will invoke the extraction plugin for each input trace. The test runner collects the plugin output and +compares it against the trace defined in the `results` folder. If there is a mismatch, the test runner will fail with an +exit code 1. If all tests pass the test runner will finish with exit code 0. + +Given the files in the example above, the test runner will invoke the extraction plugin three times: + +| Input | Result | +|--------------------------------------------------------------|------------------------------------------------| +| `example1.trace` with data `stream example1.raw` | `example1.raw.PluginName.trace` | +| `example1.trace` with data `stream example1.text` | `example1.text.PluginName.trace` | +| `example2.trace` with data `stream example2.text` | `example2.raw.PluginName.trace` | + +### Test data structure for deferred extraction plugins + +:ref:`Deferred extration plugins ` have the unique ability to search traces with a query. +The `input` test data should be extended to contain the results of searches done by deferred extraction plugins. These +_search traces_ are stored in separate folders that follow the naming format '{deferred trace name}/searchtraces/'. Below +is an example test data directory structure for a deferred extraction plugin that searches for +a `deferredExampleSearch.trace`: + +```text +tests/ +├── inputs +│  ├── deferredExample.trace +│  ├── deferredExample.raw +│  ├── deferredExample/ +│  │  ├── searchtraces/ +│  │  │  ├── deferredExampleSearch.trace +└── results +   └── deferredExample.raw.DeferredPluginName.trace +``` + +.. warning:: The plugin will try to match on all traces in the input folder, including traces used for search results ( + of deferred extraction plugins). This means that it is impossible to search on traces that match the same deferred + extraction plugin, as it would create an infinite loop. + +Given the files in the example above, the test runner will invoke the extraction plugin one time: + +| Input | Result | +|----------------------------------------------------------------|------------------------------------------------| +| `deferredExample.trace` with data stream `deferredExample.raw` | `deferredExample.raw.DeferredPluginName.trace` | + +.. warning:: The search query should be written in HQL, as that is how Hansken will interpret it. However, the test + framework interprets the query using its HQL-lite interpreter. Therefore, not all queries will be supported. + +.. _traceformat: + +### Trace format + +Input and result traces both stored in a JSON structure. There is however a slight difference between the two: The +result trace may store additional values that are purely there for testing purposes. The input format will first be +discussed, followed by the result format. + +#### Input trace JSON format + +Input traces start with a `trace` key, which contains a mapping of properties. The property names are split in a +dictionary structure. The example below shows a serialized trace with six properties: `data.raw.mimeClass` and the five +data types that are currently supported by the test-framework. + +The `data` key defines the :ref:`data-streams ` of the trace. When adding a data-stream make sure you also +add the corresponding input data file, as described :ref:`above`. + +```json +{ + "trace": { + "data": { + "raw": { + "mimeClass": "text" + } + }, + "supported data types": { + "Boolean": true, + "Integer": 1, + "Double": 0.1, + "String": "a string", + "StringList": [ + "a", + "b", + "c", + "d" + ] + } + } +} +``` + +.. warning:: The extraction plugin SDK and the test framework have no knowledge of the + :ref:`trace model `. This means that when properties are used that don't + comply with the trace model, this will not cause the test to fail, but it will fail when running your plugin in Hansken. + +#### Result trace JSON format + +The result traces have the same format as the input traces, namely a `trace` key which contains the full input trace +with all its properties. However, the result traces may have two additional keys `children` and `data` (which are +explained in-depth below). These are added for testing purposes. If the plugin adds :ref:`child traces ` +or writes [data transformations](data_transformations.md) to Hansken, this would normally not reflect on the JSON of the +trace. However, the test framework adds these to the result JSON structure to be able to test them. + +Consequently, result traces are stored in a JSON structure that may consist of up to three parts, namely the always +present `trace` and the occasional `children` and `data`: + +* `trace`: The key `trace` contains a mapping of its properties, in exactly the same way as is done for input traces. +* `children`: :ref:`Child traces ` that have been created by the plugin during the test are stored under a + reserved field `children`, which is a list of traces. The example trace below contains a child trace with a property + `name`. +* `data`: [Data transformations](data_transformations.md) that have been created by the plugin during the test are + stored under a reserved field `data`. For each data-stream type there is a `descriptor` field describing the data + transformation in a JSON format. The example trace has a ranged data transformation for the raw data-stream. Note that + this `data` is entirely different from the `data` key that may be present _inside_ the `trace`! + +```json +{ + "trace": { + "data": { + "raw": { + "mimeClass": "text" + } + }, + "supported data types": { + "Boolean": true, + "Integer": 1, + "Double": 0.1, + "String": "a string", + "List": [ + "a", + "b", + "c", + "d" + ] + } + }, + "children": [ + { + "trace": { + "name": "child trace 1" + } + } + ], + "data": { + "raw": { + "descriptor": "[{\"ranges\":[{\"length\":79,\"offset\":0}]}]" + } + } +} +``` + +### Testing exceptions + +Some scenarios may throw exceptions and this can be part of your tests too. For example, an input file that has the +wrong format can be part of your integration tests. When an exception occurs during the test, it will be written to the +result file. This can be deliberately used to test exceptions. However, it is often impractical to match against a full +exception. For example, the row numbers in the exception are very much prone to change due to circumstances irrelevant +to the case being tested. Therefore, the testframework provides some options to match only on those parts of result +files that are relevant to the test. + +The following sections will explain these partial result matchers using the following example exception: + +```json +{ + "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException", + "message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris faucibus varius sodales." +} +``` + +#### Leaving out the message + +It is possible to leave of the message of the exception, which will still result in a valid result: + +```json +{ + "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException" +} +``` + +#### The `startsWith` partial result matcher + +The `startsWith` partial result matcher requires a string as a parameter. The result will be valid if the actual result +starts with this string. + +```json +{ + "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException", + "message.startsWith": "Lorem ipsum dolor sit amet, " +} +``` + +#### The `containsInOrder` partial result matcher + +The `containsInOrder` partial result matcher requires a list of strings as a parameter. The result will be valid if +every string in the list can be found in that same order in the actual result. + +```json +{ + "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException", + "message.containsInOrder": [ + "Lorem ipsum dolor sit amet,", + "consectetur adipiscing elit.", + "Mauris faucibus varius sodales." + ] +} +``` + +.. _howtotestyourplugin: + +## How to test your plugin + +Running an integration test for an extraction plugin depends on the language in which the extraction plugin is built. + +### Java + +The Test Framework itself is built in Java. When building extraction plugins with Java, it can be incorporated in your +unit tests, as shown in [Using the Test Framework in Java](../java/testing.md). + +### Python + +The Python SDK also uses the Java based Test Framework. This is done by providing a wrapper to make calls to an included +Test Framework 'jar' file. See [Advanced use of the Test Framework in Python](../python/testing.md) for documentation +and examples on how to use FLITS for testing your Python plugin. diff --git a/0.9.16/_sources/dev/concepts/traces.md.txt b/0.9.16/_sources/dev/concepts/traces.md.txt new file mode 100644 index 0000000..17de4b0 --- /dev/null +++ b/0.9.16/_sources/dev/concepts/traces.md.txt @@ -0,0 +1,213 @@ +# Traces & Trace model + +.. _traces: + +## Traces + +Traces are structured data objects produced by tools/plugins during an extraction. A trace represents a piece of +information found in an evidence file. + +The following figure shows the main elements of a trace. Each element is described in more detail in the following +paragraphs. + +![trace.svg](trace.svg) + +.. The following diagram is used to produce the trace.png file + + @startuml + hide empty methods + + Interface Trace << (T,#FF7700 >> { + {static} String id + {static} String name + {static} String[] path + .. + Map properties + .. + List + List children + } + + Interface DataStream << (D,orchid>> { + {static} String type + {static} String length + {static} byte[] data + .. + String fileType + Properties properties + } + + Trace *-- Trace : a trace could have child traces + Trace *-- DataStream : a trace could have data streams + + @enduml + +### Types and Properties + +A trace has properties that describe the information of it by means of a property value. Trace properties are grouped by +a trace type. A trace can have multiple types. + +All types and properties that can be set are defined in the :ref:`Hansken trace model`. + +An example of a type is `document`, which could have the properties `application` and `createdOn`. The trace will have a +type `document`, and can the following properties with values: + + document.application: Libre Office + document.createdOn: 2021-09-18 20:00:00 + +### Intrinsic properties + +A trace has several *intrinsic* properties. These are properties that are not related to a trace type. The intrinsic +properties available to extraction plugins are: + +* `id`: a unique identifier of the trace, generated when a trace is created +* `name`: a name given to a trace when it is created +* `path`: a logical path of the trace, of which the elements are the names of traces from the root trace until this + trace + +.. _datastreams: + +### Data streams + +Typically, a trace represents a piece of data found in an evidence file. This data is part of the trace and available as +a data stream. A trace can have multiple data streams. Each data stream has a type. Data streams can also have +properties that apply to the data stream itself. The data stream properties are modeled as properties of the trace, in +the following pattern: +`data..propertyname` (where `` is substituted by the actual type of the data stream). + +The set of data stream types and data stream properties is fixed. All allowed types and properties are defined in the +:ref:`Hansken trace model` (see `data`). + +An important data stream property is the `fileType` property. This property contains a textual description of the +*detected* file type for the data stream. An example of a `fileType` is 'Adobe Pdf'. The `fileType` is a good candidate +to use in a extraction plugin 'matcher'. This `fileType` is detected by Hansken using file type heuristics, which are +primarily based on the data stream bytes itself, and secondarily on other metadata such as a file extension. +(N.B. The `fileType` is detected in Hansken by the extraction tool `FireFli`.) For more information on how datastream +properties can be used for matching, see :ref:`here`. + +Note that not all traces have data streams. In these cases it is a trace of meta-data derived from another trace. + +Usually, each trace with data has a data stream of type `raw`. This data stream contains the bytes of the traces as they +were found when the trace was created. In some occasions, the `raw` data can be represented in a different form before it +can be processed further, for example if the data can be decoded or decrypted. Hansken tools and plugins can decode +the `raw` data stream to a standard UTF-8 data stream, or can decrypt the data if a decryption key is present. Hansken +tools and extraction plugins can store the new data at the new trace in a new data stream. This new data stream has a +different type than the `raw` type. + +Examples in code can be found here: + +* Adding a Datastream :ref:`Java ` +* Adding a Datastream :ref:`Python ` + +.. TODO: Add a link to matcher in the paragraph above + +.. _child traces: + +### Child traces + +A trace can have child traces. For example, a trace of type `archive` can have children, where each child is a trace +that represents an entry in the archive. + +With an extraction plugin it is possible to create child traces for a trace that is being processed. New properties, +data streams, and other child traces can be set on the new child traces. When a child trace is created, the plugin +should provide a `name` for the child trace. The `id` of the child trace is generated, in the following +form: `parenttraceid-childnumber`. For example, if the parent has an id `0-0-0-0-0:0-9`, the first child gets the +id `0-0-0-0-0:0-9-1`, the second child gets the id `0-0-0-0-0:0-9-2`, and so on. + +Note that a trace does not have (direct) access to its parent trace. + +### Trace property types + +The SDK supports the following property types for traces: + +| | Java | Python | +|-------------|-----------------------|-----------------------| +| binary | `byte[]` | `bytes` / `bytearray` | +| boolean | `boolean` | `bool` | +| integer | `int` / `long` | `int` | +| real | `float` / `double` | `float` | +| string | `String` | `str` | +| date & time | `Date` | `datetime` | +| list | `List` | `list` / `tuple` | +| mapping | `Map` | `dict` | +| location | `LatLong` | `GeographicLocation` | +| vector | `Vector` | `Vector` | +| tracelet | *see Tracelets below* | *see Tracelets below* | + +Both location and vector types are available from the SDK, Java package `org.hansken.plugin.extraction.api` or Python module `hansken.util`. + +.. _vector: + +#### Vector + +A vector is a data type that can be used to store points in n-dimensional space as an array of floating point values. +Once indexed, the vectors can then be used in a gui or other client to search for traces that have a nearby vectors. +For example, it is possible to use a neural network that provides embeddings of human faces as vectors. Once indexed, +the vectors can then be used to find pictures with similar faces. To do this, the search rest api can be used to +sort by the euclidean- or manhattan distance, or cosine similarity to a given vector. + +.. _tracelets: + +#### Tracelets + +A Tracelet is a bundle of property values that belong to a single type. It is a property on a trace that can have +multiple properties itself, making it a list of key/value pairs. The API doesn't specify the cardinality, but the +implementation is limited to cardinality 'Few'. In Hansken these are called FVT's (Few Valued Types). + +.. note:: MVT's (Many Valued Types) are currently not supported in the SDK and will be added in a future release. + +An example of a tracelet is the `prediction` property, which describes a category or class a trace belongs to. It is +possible for a trace to have multiple predictions. Therefore `prediction` is a tracelet. Other examples of +tracelets are `identity` and `collection`. + +Examples in code can be found here: + +* Adding tracelets in :ref:`Java ` +* Adding tracelets in :ref:`Python ` + +.. _Hansken trace model: + +## Hansken trace model + +All traces in Hansken are based on a specific version of the trace model, and must comply to that version of the trace +model. This is a nested data structure composed of origins, categories, types and properties. + +All non-inrinsic trace properties are optional and are grouped by **type**. These types are defined under the trace +model section 'categories'. Every **category** has a list of allowed types. When a trace is identified as being a +document, it will get this set of predefined document properties. Trace types can have different **origins**. The +possible origins are defined in the trace model section 'origins'. An example of this is the processed types that are +always generated by the system during an extraction. + +The details of the current trace model can be retrieved using the `/tracemodel` +REST call on the Gatekeeper endpoint of Hansken, or check the Hansken Documentation on the trace model. + +.. TODO: nice screenshot on how to find the trace model in Hansken? + +.. _Trace model and the extraction plugin SDK: + +### Trace model and the extraction plugin SDK + +.. warning:: The extraction plugin SDK has no knowledge of the trace model + +The Extraction Plugins SDK has no knowledge of the trace model at this time. It is however possible to create new traces +with plugins. If any newly created Traces don't comply to the model, Hansken will not accept them and mark the plugin +execution as failed. The Extraction Plugins SDK and the provided [Test Framework](test_framework.md) don't check this. +Please make sure to use the right naming when creating new Traces, as provided by the trace model. + +If an erroneous trace property is set, Hansken will show an error. The error can be found in the Hansken Expert UI +interface by double-clicking on the trace. Then the trace details screen will be opened and the error will be displayed +as follows: + +.. image:: toolrun_error.png + +This error describes that a property does not exist in the trace model. To get more information about the error, the +extraction log can be viewed. In the extraction log you have to search +for `java.lang.IllegalArgumentException: no such type` to find out which property is not supported by the trace model. + +In the example extraction log below, the property `this_property_does_not_exist` could not be found 681 times. + + Cumulative warnings, based on the message without numbers, uuids and trace objects. Only showing full message for first warning of this type. + Count | Key | Message + 681 | org.hansken.ep.shade.io.grpc.StatusRuntimeException | CANCELLED: Cancelled by client with StreamObserver.onError(); org.hansken.ep.shade.io.grpc.StatusRuntimeException: ABORTED: java.lang.IllegalArgumentException: no such type: this_property_does_not_exist + 7 | java.lang.IllegalStateException | call was cancelled + 1 | org.hansken.ep.shade.io.grpc.StatusRuntimeException | UNAVAILABLE: HTTP/2 error code: NO_ERROR Received Rst Stream diff --git a/0.9.16/_sources/dev/examples.md.txt b/0.9.16/_sources/dev/examples.md.txt new file mode 100644 index 0000000..5be2f27 --- /dev/null +++ b/0.9.16/_sources/dev/examples.md.txt @@ -0,0 +1,5 @@ +# Examples + +Extraction Plugin Examples in both Java and Python can be found in the +[Hansken Extraction Plugin Examples Repository](https://github.com/NetherlandsForensicInstitute/hansken-extraction-plugin-sdk-examples) +hosted on Github. diff --git a/0.9.16/_sources/dev/faq.md.txt b/0.9.16/_sources/dev/faq.md.txt new file mode 100644 index 0000000..ee5a5f1 --- /dev/null +++ b/0.9.16/_sources/dev/faq.md.txt @@ -0,0 +1,64 @@ +# Frequently Asked Questions + +.. _communityaccess: + +## How can I access Hansken developer community + +You will first need git access to the Hansken developer community. Here you can find started guides and examples. If you +have no access yet, you can get access by following the next steps: + +1. Sign up at [git.eminjenv.nl](https://git.eminjenv.nl/) +2. After you have created your account, you should request access to the " + Hansken Community" group . Do this by contacting your organisations Hansken business owner. If you don't know who to + contact as your business owner, please read the :doc:`../contact` page. + +## Why use Extraction Plugins? + +Extraction plugins enable you to run your own extraction code in Hansken. + +* Your plugin runs during extraction +* Extraction plugins are faster than Hansken.py +* Multiple programming languages are supported +* Scalability: Extraction plugins can be scaled flexibly on a kubernetes cluster + +## What programming languages are supported? + +The SDK contains an API and tools to write a Hansken extraction plugin in Java or Python. The Java API can be used to +develop extraction plugins in JVM-compatible languages, such as Scala and Kotlin. + +## Will you support language *foobar*? + +Probably not. It takes time and effort to create a proper SDK. If you think there is a good use case to support +language *foobar*, and there is gRPC support, feel free to contact us. We can discuss the options to add support for +Hansken extraction plugins with *foobar*. + +Under the hood, extraction plugins use gRPC to communicate with Hansken. In theory, all programming languages that have +a gRPC implementation can be used to write Hansken extraction plugins. + +## Can I reuse or modify the Extraction Plugins SDK? + +The SDK is distributed under the Apache 2.0 License, see the LICENSE file in the SDK for more details. + +## Can I use a plugin that someone else wrote? + +Yes, at your own risk. The Hansken Team does not take responsibility for code written by third parties in the form of +Extraction Plugins. + +## What are the legal implications of creating your own Extraction Plugin(s)? + +All Extraction Plugins not written by the Hansken Team are considered **third party** Extraction Plugins. Please refer +to [Can I use a plugin that someone else wrote?](faq.md#can-i-use-a-plugin-that-someone-else-wrote?) + +## How safe are Extraction Plugins? + +We are doing everything to make sure Extraction Plugins are as safe as possible, however note that the Extraction Plugin +SDK is still in beta. Use it at your own risk. For more information on security see [Isolation](concepts/isolation.md). + +## Can my Extraction Plugin be embedded into Hansken for performance reasons? + +Embedding an Extraction Plugin into Hansken requires access to the Hansken source code. If you have access to the source +code then please `../contact` us for assistance. Please note that embedded Extraction Plugins are **not officially +supported**. + +If you do not have access to the Hansken source code, then please contact your own Business Owner, and ask them to +contact the Hansken Team. diff --git a/0.9.16/_sources/dev/introduction.md.txt b/0.9.16/_sources/dev/introduction.md.txt new file mode 100644 index 0000000..7f99bec --- /dev/null +++ b/0.9.16/_sources/dev/introduction.md.txt @@ -0,0 +1,50 @@ +# Introduction + +The Extraction Plugin Software Development Kit can be used to develop a [Hansken](https://www.hansken.nl/an-introduction-to-hansken) +extraction plugin. + +Hansken is designed to give access to and insight in digital data and traces originating from seized and demanded +digital material. One aspect of the Hansken platform is the extraction engine (extraction framework). The extraction +engine contains digital forensics knowledge, which is used to find traces in digital material. With extraction plugins +case investigators can add new digital forensics knowledge to the extraction framework. In this way, Hansken is enabled +to understand new digital formats, and thus is able to find new types of traces in the seized and demanded material. + +Examples of digital forensics knowledge that can be added to Hansken with extraction plugins: + +* new file formats (e.g. a new crypto currency wallet) +* combine traces to find new information (e.g. use a windows registry entry required to read a file from disk) +* apply algorithms on traces (e.g. speech to text from audio files) + +The primary goals of this SDK are: + +* to make it as easy as possible to add new digital forensics knowledge to Hansken. +* be able to share digital forensics knowledge with other Hansken community members + +## Software Development Kit (SDK) + +In order to create extraction plugins, the Hansken project maintains an Extraction Plugin Software Development Kit +(SDK). + +This SDK contains the following elements: + +* [Java API and tooling](java), to be able to write an extraction plugin with the [Java](https://www.java.com/) + programming language +* [Python API and tooling](python), to be able to write an extraction plugin with [Python](https://www.python.org/) + programming language +* [Test framework](concepts/test_framework.md), to be able to test extraction plugins before they are used production +* Documentation for plugin developers to help understand the SDK and all its facets (this documentation) +* :doc:`examples` + +## Development steps of a plugin + +To create a plugin, the plugin developer could follow the following steps. Detailed information per step will be added +later to the documentation. + +1. Create a new empty plugin +2. Implement the plugin logic +3. Verify the plugin using the [test framework](concepts/test_framework.md), using reference data (test data) and + expected output +4. Test the plugin in Hansken +5. Use the plugin in an actual case +6. Share the plugin with the Hansken community, so other case investigations can benefit from the plugin as well ( + optional, but encouraged) diff --git a/0.9.16/_sources/dev/java.rst.txt b/0.9.16/_sources/dev/java.rst.txt new file mode 100644 index 0000000..c6f37e9 --- /dev/null +++ b/0.9.16/_sources/dev/java.rst.txt @@ -0,0 +1,14 @@ +Java +==== + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + java/api_changelog + java/prerequisites + java/packaging + java/snippets + java/testing + java/debugging + java/javadoc diff --git a/0.9.16/_sources/dev/java/api_changelog.md.txt b/0.9.16/_sources/dev/java/api_changelog.md.txt new file mode 100644 index 0000000..fbca70d --- /dev/null +++ b/0.9.16/_sources/dev/java/api_changelog.md.txt @@ -0,0 +1,292 @@ +# Java API Changelog + +This document summarizes all important API changes in the Extraction Plugin API. This document only shows changes that +are important to plugin developers. For a full list of changes per version, please refer to the general +:ref:`changelog `. + +.. If present, remove `..` before `## |version|` if you create a new entry after a previous release. + +.. ## |version| + +## 0.9.13 + +* This release introduces a new parameter `bulkMode` to the `PluginInfo`. This can be used for + [lightweight plugins](snippets.md#bulk-mode) which have to process a lot of data (either a lot of traces or a small + number of traces with large data streams). These plugins will run inside the worker pod for streaming extractions, + and will therefore be able to process data more efficiently. + +## 0.9.11 + +* This release allows the user to search for more than 50 traces using the `TraceSearcher` in deferred extraction plugins. + +## 0.9.10 + +* This release introduces the deferred meta extraction plugin. This plugin type can *defer* their execution and + processes a trace only with its metadata, without processing its data and accesses traces using the searcher. + This makes it possible to use deferred plugins in combination with traces without data. + _Note:_ Hansken will support these types of plugins from v47.34.0. + +* This release introduces new parameters for the `TraceSearcher`, `start` and `sort`. + This allows the searcher can get a certain range of traces in a specific order. + _Note:_ Hansken will support these types of plugins from v47.34.0. + +## 0.9.5 + +* The internal (de)serialization of some types has changed. Please update the extraction plugin sdk to match the one used in Hansken. + +## 0.8.0 + +* The trace property `imageId` is renamed to `image`. This is to be in line with the Hansken REST API and Python API. + When updating your plugin, please update your calls `trace.get("imageId")` to `trace.get("image")`. + +* [#774](https://git.eminjenv.nl/hansken/hbacklog/-/issues/774) + By default, deferred extraction plugin searches are now scoped to the image + of the trace that is currently being processed. Optionally, a project-wide + search can be done by passing an optional scope argument. + + ```java + @Override + public void process(final Trace trace, final ExtractionContext context, final TraceSearcher searcher) { + // only search for traces inside the same image as the trace that is being processed + final SearchResult result = searcher.search("file.extension=asc", 10); + final SearchResult result = searcher.search("file.extension=asc", 10, TraceSearcher.SearchScope.IMAGE); + + // search for all traces inside the same project as the trace that is being processed + final SearchResult result = searcher.search("file.extension=asc", 10, TraceSearcher.SearchScope.PROJECT); + } + ``` + +* Support trace properties of type `List`, `List`, and `List`. + This enables you to write multiple offsets and confidence scores in tracelets of type prediction. + + For example: + + ```java + trace.addTracelet("prediction", tracelet -> { + tracelet.set("modelName", "my_cat_detector"); + tracelet.set("modelVersion", "0.0.BETA"); + tracelet.set("type", "classification"); + tracelet.set("label", "cat"); + + tracelet.set("offset", 3.0); + tracelet.set("confidence", 0.4); + + tracelet.set("offsets", List.of(0.0, 3.0, 6.0, 9.0)); + tracelet.set("confidences", List.of(0.1, 0.4, 0.03, 0.09)); + }) + ``` + +## 0.7.0 + +* Escaping the `/` character in matchers is optional. + This simplifies and aims for better HQL and HQL-Lite compatability. + See for more information and examples the :ref:`HQL-Lite syntax documentation`. + + Examples: + + * `file.path:\\/Users\\/*\\/AppData` -> `file.path:/Users/*/AppData` + * `registryEntry.key:\\/Software\\/Dropbox\\/ks*\\/Client-p` -> `registryEntry.key:/Software/Dropbox/ks*/Client-p` + +* Hansken returns `file.path` properties as a `String` property, instead of a `List`. + Example: `trace.get("file.path")` now returns `"/dev/null"`, this was `["dev", "null"]`. + +## 0.6.3 + +* A plugin can now write multiple data streams to a single trace concurrently, + e.g. write both `decrypted` and `ocr` at the same time. See the ":ref:`datastreams java`" code snippets for + general examples on adding data to a trace. + +## 0.6.1 + +* The JAVA SDK is now distributed through maven central instead of the Hansken community. + +## 0.6.0 + +.. warning:: It is highly recommended to upgrade your plugin to this new version. + See the migration steps below. + +* Extraction plugin container images are now labeled with PluginInfo. This + allows Hansken to efficiently load extraction plugins. + +* By default, extraction plugin version is managed in the plugin's `pom.xml`. + The `.pluginVersion(..)` can be removed from the PluginInfo builder. + +* **Migration steps from earlier versions** -- for plugins that use the Java + extraction plugin SuperPOM: + + 1. Update the SDK version in your `pom.xml` + 2. If you come from a version prior to `0.4.0`, or if you use a plugin name + instead of a plugin id in your `pluginInfo()`, switch to the plugin id style + (read instructions for version `0.4.0`) + 3. Set your plugin version in your project's `pom.xml`, and remove the + following from your `PluginInfo.Builder`: + + ```java + .pluginVersion(...) + ``` + + 4. Update your build scripts to build your plugin (Docker) container image. + You should build your plugin container image with the following command: + + ```bash + mvn package docker:build` + ``` + + This will generate a plugin image: + + * The extraction plugin is added to your local image registry + (`docker images`), + * The image name is `extraction-plugin/PLUGINID`, e.g. + `extraction-plugin/nfi.nl/extract/chat/whatsapp`, + * The image is tagged with two tags: `latest`, and your plugin version. + + Nb. If Docker is not available in your environment, `podman` can be used + as an alternative. See :ref:`packaging ` for more + details. + +## 0.5.0 + +* Add new tracelet api `Trace.addTracelet(type, consumer)`. + It can be used like this: + + ```java + trace.addTracelet("prediction", tracelet -> tracelet + .set("type", "classification") + .set("label", "label") + .set("confidence", 0.8f) + .set("embedding", Vector.of(1,2,3)) + .set("modelName", "yolo") + .set("modelVersion", "2.0")); + ``` + +* Deprecate Trace.addTracelet(Trace) +* Support vector data type in trace properties. + +## 0.4.13 + +* When writing input search traces for tests, it is no longer required to explicitly set an `id` property. + These are automatically generated when executing tests. + +## 0.4.7 + +* A new convenience method `id(String, String, String)` is added to the PluginInfo builder. This removes some + boilerplate code when setting the pluginId. More details on the plugin naming conventions can be found at the + :doc:`../concepts/plugin_naming_convention` section. + + ```java + PluginInfo.builderFor(this) + .id("nfi.nl", "extract", "TestPlugin") // new style + .id(new PluginId("nfi.nl", "extract", "TestPlugin")) // old style, but also works + ... + ``` + +## 0.4.6 + +* It is now possible to specify maximum system resources in the `PluginInfo`. To run a plugin with 0.5 cpu (= 0.5 + vCPU/Core/hyperthread) and 1 gb memory, for example, the following configuration can be added to `PluginInfo`: + + ```java + PluginInfo.builderFor(this) + ... + .pluginResources(PluginResources.builder() + .maximumCpu(0.5f) + .maximumMemory(1000) + .build()) + .build(); + ``` + +## 0.4.0 + +* Extraction Plugins are now identified with a `PluginInfo.PluginId` containing a domain, category and name. The + method `PluginInfo.name(pluginName)` has been replaced by `PluginInfo.id(new PluginId(domain, category, name)`. More + details on the plugin naming conventions can be found at the :doc:`../concepts/plugin_naming_convention` section. + +* `PluginInfo.name()` is now deprecated (but will still work for backwards compatibility). + +* A new license field `PluginInfo.license` has also been added in this release. + +* The following example creates a PluginInfo for a plugin with the name `TestPlugin`, licensed under + the `Apache License 2.0` license: + + ```java + PluginInfo.builderFor(this) + .id(new PluginId("nfi.nl", "extract", "TestPlugin")) // id.domain: nfi.nl, id.category: extract, id.name: TestPlugin + // .name("TestPlugin") // no longer supported + .pluginVersion("0.4.1") + .author(Author.builder()...build()) + .description("A plugin for testing.") + .maturityLevel(MaturityLevel.PROOF_OF_CONCEPT) + .hqlMatcher("*") + .webpageUrl("https://www.hansken.org") + .license("Apache License 2.0") + .build(); + ``` + +## 0.3.0 + +* Extraction Plugins can now create new datastreams on a Trace through data transformations. Data transformations + describe how data can be obtained from a source. + + An example case is an extraction plugin that processes an archive file. The plugin creates a child trace per entry in + the archive file. Each child trace will have a datastream that is a transformation that marks the start and length of + the entry in the original archive data. By just describing the data instead of specifying the actual data, a lot of + space is saved. + + Although Hansken supports various transformations, the Extraction Plugins SDK for now only supports ranged data + transformations. Ranged data transformations define data as a list of ranges, each range with an offset and length in + a bytearray. + + The following example sets a new datastream with dataType `html` on a trace, by setting a ranged data transformation: + + ```java + trace.setData("html", RangedDataTransformation.builder().addRange(offset, length).build()); + ``` + + The following example creates a child trace and sets a new datastream with dataType `raw` on it, by setting a ranged + data transformation with two ranges: + + ```java + trace.newChild(format("lineNumber %d", lineNumber), child -> { + child.setData("raw", RangedDataTransformation.builder() + .addRange(10, 20) + .addRange(50, 30) + .build()); + }); + ``` + + More detailed documentation will follow in an upcoming SDK release. + +## 0.2.0 + +.. warning:: This is an API breaking change. Plugins created with an earlier version of the extraction plugin SDK are + not compatible with Hansken that uses `0.2.0` or later. + +* Introduced a new extraction plugin type `DeferredExtractioPlugin`. Deferred Extraction plugins can be run at a + different extraction stage. This type of plugin also allows accessing other traces using the searcher. + +* The class `ExtractionContext` has been renamed to `DataContext`. The new name `DataContext` represents the class + contents better. Plugins have to update matching import statements and the type in `ExtractionPlugin.process()` + implementation in the same way. This change has no functional side effects. + + Old: + + ```java + import org.hansken.plugin.extraction.api.ExtractionContext; + + @Override + + public void process(final Trace trace, final ExtractionContext context) throws IOException { + + } + ``` + + New: + + ```java + import org.hansken.plugin.extraction.api.DataContext; + + @Override + public void process(final Trace trace, final DataContext dataContext) throws IOException { + + } + ``` diff --git a/0.9.16/_sources/dev/java/debugging.md.txt b/0.9.16/_sources/dev/java/debugging.md.txt new file mode 100644 index 0000000..2674eb4 --- /dev/null +++ b/0.9.16/_sources/dev/java/debugging.md.txt @@ -0,0 +1,134 @@ +# How to debug an Extraction Plugin + +Debugging is the art of removing bugs — hopefully quickly. + +## Locally + +To debug a plugin locally, it is recommended to start the plugin via the IDE by running the integration test. This has +the advantage that breakpoints can easily be put in the code instead of printing log statements, for example. + +### Logging + +The logging of the extraction plugin is displayed in the console. + +## Locally with Docker + +Debugging an extraction plugin via docker is a bit trickier. Java has the advantage that remote debugging is already +baked in. + +Using Java Remote Debug with Docker containers requires 3 distinct steps: + +1. Build a Docker image +2. Run the Docker image with specific Java tool options +3. Setting breakpoints in your code + +### Build a Docker image + +If the Docker image is not built, run the following command to build the Docker image: + +```bash +mvn package docker:build +``` + +### Run the Docker image with specific Java tool options + +In Java, the remote debug functionality is not enabled by default. To enable the remote debug functionality, the +following environments variable must be set in the Docker container: + +```bash +JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" + ``` + +This environment variable allows the debugger to connect to the debuggee (application being debugged). To start the +Docker image with the `JAVA_TOOL_OPTIONS` environment variable, the following command can be used: + +```bash +docker run -p 5005:5005 -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" your_extraction_plugin_name +``` + +The next step is to attach the debugger to the debuggee. +For Intellij, the instructions are clearly described on the following +page: [Tutorial: Remote debug](https://www.jetbrains.com/help/idea/tutorial-remote-debug.html#49be7f04) + +### Setting breakpoints in the code + +The last step is to add breakpoints in the code. + +### Logging in Docker + +The logging of the extraction plugin is displayed in the console after running the `docker run` command. In addition, +the logging is also displayed in the IntelliJ console while debugging. + +## Kubernetes + +In kubernetes it is currently _not_ possible to debug via Java Remote Debug because: + +* no debug ports are published; +* the container was not started with the environment variable `JAVA_TOOL_OPTIONS` so debugging is not enabled. + +### Logging in Kubernetes + +If there is authorization to the kubernetes cluster, the logging can be viewed with the following command: + +```bash +kubectl logs -f hansken-extraction-plugins/your_extraction_plugin_pod +``` + +## Debug HQL + +An HQL query can be debugged by overriding the `isVerboseLoggingEnabled()` method of the `ExtractionPluginFlits` class. +The example below shows an example of an embedded FLITS test with verbose logging enabled. + +```java +public class TestPluginFlitsIT extends EmbeddedExtractionPluginFlits { + + @Override + public Path testPath() { + return srcPath("integration/inputs/plugin"); + } + + @Override + public Path resultPath() { + return srcPath("integration/results/embedded/plugin"); + } + + @Override + protected ExtractionPlugin pluginToTest() { + return new TestPlugin(); + } + + @Override + public boolean regenerate() { + return true; + } + + @Override + protected boolean isVerboseLoggingEnabled() { + return true; + } +} +``` + +The following output will then be displayed in the console: + +```text +HQL match found for: +$data.type=jpg +With trace: +dataType=jpg +types={file, data} +properties={data.raw.mimeType=image/jpg, path=/test-input-trace, file.name=image.jpg, name=test-input-trace, id=0} +``` + +If the HQL query contains an error, it will be shown in the generated test results. An example of an invalid query +is ``$data.mimeType=image/jpg`` (slash not escaped). This query will produce an error like the one shown below. + +```json +{ + "class": "org.hansken.plugin.extraction.hql_lite.lang.ParseException", + "message": "HqlLiteHumanQueryParser: line 1:20 token recognition error at: '/jpg'" +} +``` + +.. note:: The error is only shown in the generated trace, so to find out the `ParseException` override + the `regenerate()` method from `Flits` and then let this method return `true`. diff --git a/0.9.16/_sources/dev/java/javadoc.md.txt b/0.9.16/_sources/dev/java/javadoc.md.txt new file mode 100644 index 0000000..fdca19d --- /dev/null +++ b/0.9.16/_sources/dev/java/javadoc.md.txt @@ -0,0 +1,3 @@ +# Javadoc + +Visit the `Javadoc of the Extraction Plugins SDK API <../../_static/javadoc/index.html>`_. diff --git a/0.9.16/_sources/dev/java/packaging.md.txt b/0.9.16/_sources/dev/java/packaging.md.txt new file mode 100644 index 0000000..0a51a06 --- /dev/null +++ b/0.9.16/_sources/dev/java/packaging.md.txt @@ -0,0 +1,42 @@ +# Packaging + +Extraction plugins are packaged as OCI images (also known as Docker images). +The OCI images are labeled with the PluginInfo. +To automate packaging of a Java plugin and labeling the OCI image, the Extraction Plugin SuperPom has been configured to automate this for you. + +If your project uses the Extraction Plugin SuperPom (see [Prerequisites](prerequisites.md)), Packaging an extraction plugin is handled by Maven. +To package your plugin into a container image, the following command can be used: + +```bash +mvn package docker:build +``` + +This will generate a plugin image: + +* The extraction plugin is added to your local image registry +(`docker images`), +* The image name is `extraction-plugin/PLUGINID`, e.g. +`extraction-plugin/nfi.nl/extract/chat/whatsapp`, +* The image is labeled with two tags: `latest`, and your plugin version. + +It is possible to apply extra arguments to the docker command [as described here](http://dmp.fabric8.io/#docker:build). +For example, to specify a proxy, use the following command: + +```bash +mvn package docker:build -Ddocker.buildArg.https_proxy=https://proxy:8001 +``` + +Once your plugin is packaged, it can be published or 'uploaded' to Hansken. +See ":ref:`upload_plugin`" for instructions. + +.. _java_superpom_podman: + +Note: if your build environment does not have Docker available, you can use +[podman](https://podman.io/) as an alternative. Install podman on your machine +or build agent, and run the following commands _before_ invoking the +`mvn package docker:build` command: + +```bash +podman system service --time=0 unix:/run/user/$(id -u)/podman/podman.sock & +export DOCKER_HOST="unix:/run/user/$(id -u)/podman/podman.sock" +``` diff --git a/0.9.16/_sources/dev/java/prerequisites.md.txt b/0.9.16/_sources/dev/java/prerequisites.md.txt new file mode 100644 index 0000000..9a4279b --- /dev/null +++ b/0.9.16/_sources/dev/java/prerequisites.md.txt @@ -0,0 +1,42 @@ +# Prerequisites + +Required software: + +* Java 11 or higher +* Docker for [packaging](packaging.md) and publishing plugins + (or use a Docker alternative such as `podman`) +* Maven (recommended, build automation tool) + +Required dependencies: +* All required project dependencies to build extraction plugins are published on the public Maven Central, under `org.hansken.plugin.extraction:plugin-super-pom`. + For maven based extraction plugins, the following `pom.xml` snippet can be used as basis of a plugin: + + ```xml + + + 4.0.0 + + + org.hansken.plugin.extraction + plugin-super-pom + SET_THE_SDK_VERSION_HERE + + + CHOOSE_YOUR_ARTIFACTID_HERE + SET_THE_PLUGIN_VERSION_HERE + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + SET_THE_PLUGIN_MAIN_CLASS_HERE + + + ``` diff --git a/0.9.16/_sources/dev/java/snippets.md.txt b/0.9.16/_sources/dev/java/snippets.md.txt new file mode 100644 index 0000000..6a5bfdd --- /dev/null +++ b/0.9.16/_sources/dev/java/snippets.md.txt @@ -0,0 +1,265 @@ +# Java code snippets + +This page contains Java code snippets for common patterns that will be used when writing a plugin. + +## RandomAccessData as InputStream + +In Java, `InputStream` is a common type to pass data to another class or method. The SDK provides a simple utility to +use a `RandomAccessData` as `InputStream`. + +Add the following import to your code: + +```java +import org.hansken.plugin.extraction.core.data.RandomAccessDatas; +``` + +Next we can create an `InputStream` from the `RandomAccessData` as shown in the following snippet. Note that the +`InputStream` is created using a `try-with-resources`-statement. This ensures that the `InputStream` is correctly closed +when the `InputStream` is no longer required. + +```java +RandomAccessData traceData=...; + try(InputStream asInputStream=RandomAccessDatas.asInputStream(traceData)){ + // use the InputStream here + } +``` + +Notes: + +* the created `InputStream` is *not* thread-safe, +* the created `InputStream` changes state in the provided `RandomAccessData` + (e.g. when data is read, the position updated in both the `InputStream` *and* + the `RandomAccessData` instances), +* for more details on the implementation of the `InputStream`, refer to the `RandomAccessDataInputStream` JavaDoc. + +.. _tracelets java: + +## Adding tracelets + +In the following Java example, a "classification" :ref:`tracelet` is added to a trace. The tracelet consists +of a list of four properties, namely "class", "confidence", "modelName" and "modelVersion". + +```java +trace.addTracelet("prediction", tracelet -> tracelet + .set("type", "classification") + .set("class", "telephone") + .set("label", "label") + .set("confidence", 0.8f) + .set("embedding", Vector.of(1,2,3)) + .set("modelName", "yolo") + .set("modelVersion", "2.0")); +``` + +or + +```java +trace.addTracelet(new Tracelet("prediction", List.of( + new TraceletProperty("prediction.type","classification"), + new TraceletProperty("prediction.class","telephone"), + new TraceletProperty("prediction.label","label"), + new TraceletProperty("prediction.confidence",0.8f))), + new TraceletProperty("prediction.embedding", Vector.of(1,2,3)), + new TraceletProperty("prediction.modelName","yolo"), + new TraceletProperty("prediction.modelVersion","2.0")); +``` + +.. _datastreams java: + +## Adding data to a trace + +Traces can have data attached to them. See :ref:`datastreams` for more information. +The following two snippets demonstrate how to add data to a trace. + +It is currently not possible to verify that a specific data stream is already set or not. + +### Data Transformations + +The most efficient way to add data to a trace is using data transformations. +See :doc:`../concepts/data_transformations` for more details. + +The following example sets a new data stream with dataType `html` on a trace, by setting a ranged data transformation: + +```java +trace.setData("html", RangedDataTransformation.builder().addRange(offset, length).build()); +``` + +The following example creates a child trace and sets a new datastream with dataType `raw` on it, by setting a ranged +data transformation with two ranges: + +```java +trace.newChild(format("lineNumber %d", lineNumber), child -> { + child.setData("raw", RangedDataTransformation.builder() + .addRange(10, 20) + .addRange(50, 30) + .build()); +}); +``` + +### Blobs + +It is not always possible to create a transormation for the data that has to be +added to a trace. For example the data is a result of a computation, and not +a direct subset of another data stream.. + +The following examples show how to creates a new data stream of dataType `raw` on a trace. + +In case all data is stored in a `byte[]`, we can add the byte array to the data stream with: + +```java +final byte[] rawBytes = {.....}; +trace.setData("raw", writer -> writer.write(rawBytes)); +``` + +Alternatively, if the data is available in an `InputStream` the data can be added with: + +```java +final InputStream inputStream = ...; +trace.setData("raw", inputStream); +``` + +## Specifying system resources + +In the `PluginInfo` you can specify **maximum** system resource metrics for a plugin. These are used for scaling the +number of pods as described [here](../concepts/kubernetes_autoscaling.md#Autoscaling). To run a plugin with 0.5 cpu (= +0.5 vCPU/Core/hyperthread), 1 gb memory and 10 (concurrent) cpu workers (threads), for example, the following configuration can be added to `PluginInfo`: + +```java +PluginInfo.builderFor(this) + ... + .pluginResources(PluginResources.builder() + .maximumCpu(0.5f) + .maximumMemory(1000) + .maximumWorkers(10) + .build()) + .build(); +``` + +.. _java_snippets_deferred: + +## Deferred Extraction Plugins + +Using a deferred plugin requires inheriting the `DeferredExtractionPlugin` base class. This allows access to +a ``TraceSearcher`` object in the process function to search for traces. + +```java +public class ExampleDeferred extends DeferredExtractionPlugin { + @Override + public PluginInfo pluginInfo(); + + @Override + public void process(final Trace trace, final ExtractionContext context, final TraceSearcher searcher) { + final SearchResult result = searcher.search("file.extension=asc", 10); + } +} +``` + +The ``search`` method accepts three arguments; +1. a HQL query (note: this is the traditional HQL query, and not the matchers HQL-lite variant), +2. the maximum number of traces the return (currently hard-limited to a maximum of 50 traces), +3. (optional) a scope, which can be either `TraceSearcher.SearchScope.IMAGE` (default), or `TraceSearcher.SearchScope.PROJECT`. + When set to `IMAGE`, the searcher will only search for traces within the same image as the trace that is being processed. + +The traces contained in the ``SearchResult`` are returned as a stream. + +```java +final Stream stream = result.getTraces(); +stream.limit(5); +``` + +## Bulk Mode + +The `PluginInfo` contains a parameter `bulkMode`. This can be used for lightweight plugins which have to process a lot +of data (either a lot of traces with data or a small number of traces with large data streams). For streaming +extractions, these plugins will run inside the worker pod, and will therefore be able to process data more efficiently. + +**WARNING**: The plugin should be lightweight. This means that it should not use a lot of resources like CPU or memory, +because this will limit the resources of the worker pod, and therefore Hansken will not be able to start enough workers +to do extractions. + +Creating a plugin with bulk mode enabled can be done by setting the parameter in `PluginInfo` as follows: + +```java +PluginInfo.builderFor(this) + ... + .bulkMode() + .build(); +``` + +## Logging + +The logging is provided by Log4j 2 with a SLF4J binding. The Log4j 2 SLF4J binding allows applications coded to the +SLF4J API to use Log4j 2 as the implementation. + +### Usage + +Here is an example illustrating how to log something with SLF4J. It begins by getting a logger with the name "LOG". This +logger is in turn used to log the message `I'm logging a variable 1234!`. + +```java +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Example { + private static final Logger LOG = LoggerFactory.getLogger(Example.class); + + public void example() { + final int aNumber = 1234; + // logs to console: I'm logging a variable 1234! + LOG.info("I'm logging a variable {}!", aNumber); + } +} +``` + +### Customize logging + +It's easy to change the logging format with a file called `log4j2.xml`. If desired, this file must be in the `resources` +folder, for example `src/main/resources/log4j2.xml` + +```xml + + + + + + + + + + + + + +``` + +.. warning:: Be careful with logging sensitive information. + +.. note:: More information about customizing the logging can be found `here `_. + +.. note:: The default logger is pre-configured to log `INFO` to `STDOUT` (see the configuration above) + +.. note:: Log4j 2 supports various logging formats, including xml, yaml, json, properties, etc. + Currently, only the xml format is supported. + +.. note:: Contact your Hansken administrator for more information on where to find logs for your Hansken environment. + +## [EXPERIMENTAL FEATURE] Adding previews to a trace + +.. warning:: This is an experimental feature, which might change or get removed in future releases. + +Example: + +```java +public class ExamplePlugin extends ExtractionPlugin { + @Override + public PluginInfo pluginInfo(); + + @Override + public void process(final Trace trace, final DataContext context) { + final byte[] previewData; + // set the preview data for the image/png MIME-type + trace.set("preview.image/png", previewData); + trace.set("preview.image/png", previewData); + } +} +``` diff --git a/0.9.16/_sources/dev/java/testing.md.txt b/0.9.16/_sources/dev/java/testing.md.txt new file mode 100644 index 0000000..aff916c --- /dev/null +++ b/0.9.16/_sources/dev/java/testing.md.txt @@ -0,0 +1,156 @@ +# Using the Test Framework in Java + +.. _java testing: + +This section assumes you use the same setup as is used in the +[Extraction Plugin Examples](https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples). + +## Prerequisites + +Java Plugins can use the `plugin-super-pom` as maven parent, which makes sure the +FLITS [Test Framework](../concepts/test_framework.md) is included in the build. + +```xml + + + org.hansken.plugin.extraction + plugin-super-pom + 0.4.3 + +``` + +## Embedded Testing versus Remote Testing + +There are ways of integration testing a plugin with the Test Framework: + +* **Embedded testing**: Here the plugin is run directly from a JUnit test without using the gRPC layer. +* **Remote testing**: Here the test will start an ExtractionPluginServer that will serve the plugin. All communication + is between server and plugin is done using gRPC. + +See below for an example of each way of testing. +The [Extraction Plugin Examples](https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples) contains many +more examples. + +### Embedded Testing example + +Embedded tests can be run as a unit test. + +```java +import static nl.minvenj.nfi.flits.util.FlitsUtil.srcPath; + +import java.nio.file.Path; + +import org.hansken.plugin.extraction.api.ExtractionPlugin; +import org.hansken.plugin.extraction.test.EmbeddedExtractionPluginFlits; + +/** + * An integration test for MyPlugin. + */ +class MyPluginIT extends EmbeddedExtractionPluginFlits { + + @Override + protected ExtractionPlugin pluginToTest() { + // MyPlugin is a class implementing the ExtractionPlugin interface, + // with pluginInfo() and process() methods. + return new MyPlugin(); + } + + @Override + public Path testPath() { + // Provide the folder containing input files. For examples, see + // https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples. + return srcPath("integration/inputs"); + } + + @Override + public Path resultPath() { + // Provide the folder containing result files. For examples, see + // https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples. + return srcPath("integration/results"); + } + + @Override + public boolean regenerate() { + // Returning false means the test will fail if the result files don't + // match the outcome of the=++ test. Returning true means the test create + // new result files . + return false; + } +} +``` + +### Remote Testing example + +Note that the following example serves the plugin by using `ExtractionServer`. + +```java +import static nl.minvenj.nfi.flits.util.FlitsUtil.srcPath; + +import java.nio.file.Path; + +import org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginClient; +import org.hansken.plugin.extraction.runtime.grpc.server.ExtractionPluginServer; +import org.hansken.plugin.extraction.test.plugins.DataTransformationsPlugin; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +public class RemoteTransformationPluginFlitsIT extends RemoteExtractionPluginFlits { + + private static ExtractionPluginServer _server; + private static ExtractionPluginClient _client; + + @BeforeAll + public static void init() throws Exception { + final int port = 8999; + + // Serve MyPlugin. + // MyPlugin is a class implementing the ExtractionPlugin interface, with PluginInfo and Process methods. + _server = ExtractionPluginServer.serve(port, MyPlugin::new); + + // Create an ExtractionPluginClient + _client = new ExtractionPluginClient("localhost", _server.getListeningPort()); + } + + @AfterAll + public static void destruct() { + // At the end of the test, make sure the server and client are closed. + if (_server != null) { + _server.close(); + } + if (_client != null) { + _client.close(); + } + } + + @Override + public Path testPath() { + // Provide the folder containing input files. For examples, see https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples. + return srcPath("integration/inputs"); + } + + @Override + public Path resultPath() { + // Provide the folder containing result files. For examples, see https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples. + return srcPath("integration/results"); + } + + @Override + protected ExtractionPluginClient pluginToTest() { + // For Remote testing, the test won't talk directly to the plugin, but to the client. + // The client will use gRPC to communicate with the served plugin. + return _client; + } + + @Override + public boolean regenerate() { + // Returning false means the test will fail if the result files don't match the outcome of the test. + // Returning true means the test create new result files. + return false; + } +} +``` + +.. note:: Note that with a `RemoteTransformationPluginFlitsIT` it is possible to start a docker image of a plugin and + run remote tests against it using your own testdata. To do this, simply remove all `_server` code and manually start + your plugin in a docker container. Then run the test against the docker container by setting the correct url and + port, presumably `new ExtractionPluginClient("localhost", 8999)`. diff --git a/0.9.16/_sources/dev/python.rst.txt b/0.9.16/_sources/dev/python.rst.txt new file mode 100644 index 0000000..ee03dfb --- /dev/null +++ b/0.9.16/_sources/dev/python.rst.txt @@ -0,0 +1,25 @@ +Python +====== + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + python/api_changelog + python/prerequisites + python/getting_started + python/packaging + python/snippets + python/transformers + python/testing + python/hanskenpy + python/debugging + +API Documentation +----------------- + +.. autosummary:: + :toctree: python/api + :recursive: + + hansken_extraction_plugin.api diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.data_context.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.data_context.rst.txt new file mode 100644 index 0000000..e49fcfd --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.data_context.rst.txt @@ -0,0 +1,29 @@ +hansken\_extraction\_plugin.api.data\_context +============================================= + +.. automodule:: hansken_extraction_plugin.api.data_context + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + DataContext + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.rst.txt new file mode 100644 index 0000000..1f25f80 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.rst.txt @@ -0,0 +1,33 @@ +hansken\_extraction\_plugin.api.extraction\_plugin +================================================== + +.. automodule:: hansken_extraction_plugin.api.extraction_plugin + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + BaseExtractionPlugin + DeferredExtractionPlugin + DeferredMetaExtractionPlugin + ExtractionPlugin + MetaExtractionPlugin + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.extraction_trace.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.extraction_trace.rst.txt new file mode 100644 index 0000000..01a389b --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.extraction_trace.rst.txt @@ -0,0 +1,33 @@ +hansken\_extraction\_plugin.api.extraction\_trace +================================================= + +.. automodule:: hansken_extraction_plugin.api.extraction_trace + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + ExtractionTrace + ExtractionTraceBuilder + MetaExtractionTrace + SearchTrace + Trace + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.plugin_info.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.plugin_info.rst.txt new file mode 100644 index 0000000..84db660 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.plugin_info.rst.txt @@ -0,0 +1,34 @@ +hansken\_extraction\_plugin.api.plugin\_info +============================================ + +.. automodule:: hansken_extraction_plugin.api.plugin_info + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + Author + MaturityLevel + PluginId + PluginInfo + PluginResources + TransformerLabel + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.rst.txt new file mode 100644 index 0000000..cdb9470 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.rst.txt @@ -0,0 +1,40 @@ +hansken\_extraction\_plugin.api +=============================== + +.. automodule:: hansken_extraction_plugin.api + + + + + + + + + + + + + + + + + + + +.. rubric:: Modules + +.. autosummary:: + :toctree: + :recursive: + + hansken_extraction_plugin.api.data_context + hansken_extraction_plugin.api.extraction_plugin + hansken_extraction_plugin.api.extraction_trace + hansken_extraction_plugin.api.plugin_info + hansken_extraction_plugin.api.search_result + hansken_extraction_plugin.api.search_sort_option + hansken_extraction_plugin.api.trace_searcher + hansken_extraction_plugin.api.tracelet + hansken_extraction_plugin.api.transformation + hansken_extraction_plugin.api.transformer + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.search_result.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.search_result.rst.txt new file mode 100644 index 0000000..28a93a8 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.search_result.rst.txt @@ -0,0 +1,29 @@ +hansken\_extraction\_plugin.api.search\_result +============================================== + +.. automodule:: hansken_extraction_plugin.api.search_result + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + SearchResult + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.search_sort_option.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.search_sort_option.rst.txt new file mode 100644 index 0000000..1918d88 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.search_sort_option.rst.txt @@ -0,0 +1,30 @@ +hansken\_extraction\_plugin.api.search\_sort\_option +==================================================== + +.. automodule:: hansken_extraction_plugin.api.search_sort_option + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + Direction + SearchSortOption + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.trace_searcher.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.trace_searcher.rst.txt new file mode 100644 index 0000000..91a0322 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.trace_searcher.rst.txt @@ -0,0 +1,30 @@ +hansken\_extraction\_plugin.api.trace\_searcher +=============================================== + +.. automodule:: hansken_extraction_plugin.api.trace_searcher + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + SearchScope + TraceSearcher + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.tracelet.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.tracelet.rst.txt new file mode 100644 index 0000000..c502877 --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.tracelet.rst.txt @@ -0,0 +1,29 @@ +hansken\_extraction\_plugin.api.tracelet +======================================== + +.. automodule:: hansken_extraction_plugin.api.tracelet + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + Tracelet + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.transformation.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.transformation.rst.txt new file mode 100644 index 0000000..3d80bab --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.transformation.rst.txt @@ -0,0 +1,31 @@ +hansken\_extraction\_plugin.api.transformation +============================================== + +.. automodule:: hansken_extraction_plugin.api.transformation + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + Range + RangedTransformation + Transformation + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.transformer.rst.txt b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.transformer.rst.txt new file mode 100644 index 0000000..688f4fb --- /dev/null +++ b/0.9.16/_sources/dev/python/api/hansken_extraction_plugin.api.transformer.rst.txt @@ -0,0 +1,29 @@ +hansken\_extraction\_plugin.api.transformer +=========================================== + +.. automodule:: hansken_extraction_plugin.api.transformer + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + Transformer + + + + + + + + + diff --git a/0.9.16/_sources/dev/python/api_changelog.md.txt b/0.9.16/_sources/dev/python/api_changelog.md.txt new file mode 100644 index 0000000..5c7c991 --- /dev/null +++ b/0.9.16/_sources/dev/python/api_changelog.md.txt @@ -0,0 +1,536 @@ +# Python API Changelog + +This document summarizes all important API changes in the Extraction Plugin API. This document only shows changes that +are important to plugin developers. For a full list of changes per version, please refer to the general +:ref:`changelog `. + +.. If present, remove `..` before `## |version|` if you create a new entry after a previous release. + +.. ## |version| + +## 0.9.13 + +* This release introduces a new parameter `bulk_mode` to the `PluginInfo`. This can be used for + [lightweight plugins](snippets.md#bulk-mode) which have to process a lot of data (either a lot of traces or a small + number of traces with large data streams). These plugins will run inside the worker pod for streaming extractions, + and will therefore be able to process data more efficiently. + +## 0.9.10 + +* This release introduces new parameters for the `trace_searcher`, `start` and `sort`. + This allows the searcher can get a certain range of traces in a specific order. + _Note:_ Hansken will support these types of plugins from v47.34.0. + +* This release allows the user to search for more than 50 traces using the `GrpcTraceSearcher`. By specifying a count + greater than 50, results will be retrieved in batches of 50 (or less) until the desired count is achieved. + Setting the count to `None` (or omitting it) allows the `GrpcTraceSearcher` to retrieve all available traces. + This functionality is implemented in a buffered manner and is defined within `BatchedSearchResult`, + which replaces the now-removed `GrpcTraceResult`. _Note_: the search results are still limited by Elasticsearch + so no more than 100.000 results can be obtained. + +## 0.9.9 + +* This release introduces the deferred meta extraction plugin. This plugin type can *defer* their execution and + processes a trace only with its metadata, without processing its data and accesses traces using the searcher. + This makes it possible to use deferred plugins in combination with traces without data. + _Note:_ Hansken will support these types of plugins from v47.34.0. + +## 0.9.5 + +* The internal (de)serialization of some types has changed. Please update the extraction plugin sdk to match the one used in Hansken. + +## 0.9.4 + +* This release supports providing all types of transformer arguments when using the `execute_transformer` script. + +## 0.9.2 + +* This release introduces a simple flow-control mechanism that fixes `connection RST` errors that can occur when a + plugin produces traces too fast. Plugins built with this version are **not backwards compatible**. + +* Python plugins now support transformers, remote methods which can be executed using the Hansken REST API. More information can be found in [the docs](transformers.md). + +* The `build_plugin` and `label_plugin` utilities prematurely shut down containers if the building and labeling process takes too long causing the process for slow containers to fail. If your plugin takes a long time to start, you may want to increase the timeout before the script stops trying to connect and aborts the process of building the plugin. This can be done using the new optional `--timeout` argument. The default is set to 30 seconds. + +* The optional image name argument of `build_plugin` is changed to a flag. Build scripts can be updated using `--target-name DOCKER_IMAGE_NAME`. + +## 0.8.3 + +* This release addresses important load balancing issues. Please use release `0.8.3` as a drop-in-replacement for releases `0.8.2` and `0.8.1`. + +## 0.8.2 + +* ⚠️ This release is deprecated, please upgrade to `0.8.3` + +* The `build_plugin` utility has been updated and the deprecation status has been removed. + As with `label_plugin`, `build_plugin` now no longer requires a full (virtual) environment + with all plugin dependencies and resources. This will greatly reduce build times for plugins with + big dependencies and/or large models. + + The first argument of the command (a pointer to your `plugin.py` file) has been removed. + Please do not forget to remove the first argument of `build_plugin` in your `tox.ini` or other build tooling. + + For usage read further in [packaging](packaging.md). + +* The default read-buffer of `trace.open('rb')` as been changed from 1 Megabyte to 6 Megabyte to reduce overhead while data reading. + +* The data stream writer of `trace.open('wb')` is now buffered as well. This means that multiple small writes will be flushed after every 6 Megabytes of data has been written (or when the writer is closed). + +* The read-buffer or write-buffer size can be overridden by the user, by passing the `buffer_size=` argument to `trace.open()`: + + ```python + with trace.open('rb', buffer_size=1024*1024): # set a 1 Megabyte buffer size + pass + + with trace.open('wb', buffer_size=1024*1024*12): # set a 12 Megabyte buffer size + pass + + with trace.open('wb', buffer_size=1): # a buffer_size of 1 effectively disables the buffer: + pass # each write will be flushed to Hansken directly + ``` + +* It is now possible to write `str` values to `trace.open(..)`. To do so, pass `mode='w'` as additional argument. + By default, it is assumed that the written text is 'utf-8' encoded. The default can be overwritten by using the `'encoding='` argument. + + In a future Hansken update, Hansken will set the correct data-stream properties for your text stream (`mimeType`, `mimeClass`, and `fileType`). + + Example use cases are: + + * write picture-to-text (OCR) data to a trace + * write translations to a trace + * write audio-to-text (audio transcriptions) to a trace + * write the results of a JSON dump, e.g.: `json.dump(['your', 'data'], text_writer)` + + Examples in code: + + ```python + with trace.open(data_type='raw', mode='w', encoding='utf-8') as text_writer: + text_writer.write('hello.world') # write strings directly to it + json.dump({'hello': 'world'}, text_writer) # or pass the writer to json.dump + ``` + + See also :ref:`the python code snippet`. + +## 0.8.1 + +* ⚠️ This release is deprecated, please upgrade to `0.8.3` + +## 0.8.0 + +* The trace property `imageId` is renamed to `image`. This is to be in line with the Hansken REST API and Python API. + When updating your plugin, please update your calls `trace.get('imageId')` to `trace.get('image')`. + +* [#774](https://git.eminjenv.nl/hansken/hbacklog/-/issues/774) + By default, deferred extraction plugin searches are now scoped to the image + of the trace that is currently being processed. Optionally, a project-wide + search can be done by passing an optional scope argument. + + ```python + def process(trace, data_context, searcher): + # only search for traces inside the same image as the trace that is being processed + searcher.search('*') + searcher.search('*', scope='image') # explicit alternative, using a str + searcher.search('*', scope=SearchScope.image) # explicit alternative, using the SearchScope enum + + # only search for traces inside the same image as the trace that is being processed + searcher.search('*', scope='project') + searcher.search('*', scope=SearchScope.project) + ``` + +* Support trace properties of type `list[float]`. This enables you to write + multiple offsets and confidence scores in tracelets of type prediction. + + For example: + + ```python + trace.add_tracelet('prediction', { + 'modelName': 'my_cat_detector', + 'modelVersion': '0.0.BETA', + 'type': 'classification', + 'label': 'cat', + + # the best score + 'offset': 3.0, + 'confidence': 0.4, + + # all scores + 'offsets': [0.0, 3.0, 6.0, 9.0], + 'confidences': [0.1, 0.4, 0.03, 0.09], + }) + ``` + +## 0.7.3 + +* This version introduces a new docker image build utility `label_plugin`. + This utility will eventually replace `build_plugin`. `build_plugin` is now deprecated. + + `label_plugin` is a utility to add labels to an extraction plugin image. Labeling a plugin is required for + Hansken to detect extraction plugins in a plugin image registry. + + To label a plugin, first build the plugin image with [docker build](https://docs.docker.com/reference/cli/docker/image/build/); + for example by using one of the following commands: + + ```shell + docker build . -t my_plugin + docker build . -t my_plugin --build-arg https_proxy=http://your_proxy:8080 + ``` + + Next, run the `label_plugin` utility to label the build plugin container: + + ```shell + label_plugin my_plugin + ``` + + The result of `label_plugin` is a plugin image that can be :ref:`uploaded to Hansken`. + + `label_plugin` is preferred over `build_plugin`, as it does not require a full (virtual) environment + with all plugin dependencies and resources. This is especially preferred when the plugin uses (big) + data models or (external) dependencies. + + For usage read further in [packaging](packaging.md). + +## 0.7.0 + +* Escaping the `/` character in matchers is optional. + This simplifies and aims for better HQL and HQL-Lite compatability. + See for more information and examples the :ref:`HQL-Lite syntax documentation`. + + Examples: + + * Old: `file.path:\/Users\/*\/AppData` -> new: `file.path:/Users/*/AppData` + * Old: `file.path:\\/Users\\/*\\/AppData` -> new: `file.path:/Users/*/AppData` + * Old: `registryEntry.key:\/Software\/Dropbox\/ks*\/Client-p` -> new: `registryEntry.key:/Software/Dropbox/ks*/Client-p` + +* Hansken returns `file.path` properties (outside the scope of matchers) as a `String` property, + instead of a list of strings. + Example: `trace.get('file.path')` now returns `'/dev/null'`, this was `['dev', 'null']`. + +* Improved plugin loading when using `serve_plugin` and `build_plugin`: + `import` statements now work for modules (python files) that are located the same directory structure of a plugin. + +* A plugin can now stream data to a trace using `trace.open(mode='wb')`. + This removes the limit on the size of data that could be written. + See also :ref:`the python code snippet`. + + Example: + + ```python + with trace.open(mode='wb') as writer: + writer.write(b'a string') + writer.write(bytes(another_string, 'utf-8')) + ``` + + _note_: this does not work when using `run_with_hanskenpy`. + +## 0.6.1 + +* The docker image build script `build_plugin` has been updated to allow for extension of the docker command. + This can be especially handy for specifying a proxy. You should build your plugin container image with the following + command: + + ```bash + build_plugin PLUGIN_FILE DOCKER_FILE_DIRECTORY [DOCKER_IMAGE_NAME] [DOCKER_ARGS] + ``` + + .. warning:: Note that the `DOCKER_IMAGE_NAME` argument no longer requires a `-n` parameter to be specified. + + For usage read further in [packaging](packaging.md). + +## 0.6.0 + +.. warning:: This is an API breaking change. + Upgrading your plugin to this version will require code changes. + Plugins built with previous versions of the SDK from `0.3.0` will still work with Hansken. + +.. warning:: It is strongly recommended to upgrade your plugins to this new version because it significantly improves + the start-up time of Hansken. See the migration steps below. + +This release contains both build pipeline changes and API changes. +Please read all changes carefully. + +### Build pipeline change + +* Extraction plugin container images are now labeled with PluginInfo. This + allows Hansken to efficiently load extraction plugins. + Migration steps from earlier versions: + + 1. Update the SDK version in your `setup.py` / `requirements.txt` + 2. If you come from a version prior to `0.4.0`, or if you use a plugin name + instead of a plugin id in your `pluginInfo()`, switch to the plugin id style + (read instructions for version `0.4.0`) + 3. Update your build scripts to build your plugin (Docker) container image. + Be sure to [have the Extraction Plugins SDK installed](getting_started.md#Installation). + Then, you should build your plugin container image with the following command: + + ```bash + build_plugin PLUGIN_FILE DOCKER_FILE_DIRECTORY -n [DOCKER_IMAGE_NAME] + ``` + + For example: + + ```bash + build_plugin plugin/chatplugin.py . -n extraction-plugins/chatplugin + ``` + + This will generate a plugin image: + + * The extraction plugin is added to your local image registry (`docker images`), + * Note that DOCKER\_IMAGE\_NAME is optional and will default to `extraction-plugin/PLUGINID`, e.g. + `extraction-plugin/nfi.nl/extract/chat/whatsapp`, + * The image is tagged with two tags: `latest`, and your plugin version. + +### API changes + +* The field `plugin` has been removed from `PluginInfo`. +* The field `pluginId` should now be the first argument of PluginInfo (when using unnamed arguments). + + Old (unnamed arguments): + + ```python + def plugin_info(self): + return PluginInfo(self, '1.0.0', 'description', author, + MaturityLevel.PROOF_OF_CONCEPT, '*, 'https://hansken.org', + PluginId(...), 'Apache License 2.0') + ``` + + New (removed `self`, and moved `PluginId(...)` to first argument position): + + ```python + def plugin_info(self): + return PluginInfo(PluginId(...), '1.0.0', 'description', + author, MaturityLevel.PROOF_OF_CONCEPT, + '*', 'https://hansken.org', 'Apache License 2.0') + ``` + + Old (named arguments): + + ```python + def plugin_info(self): + return PluginInfo(plugin=self, + version='1.0.0', + ...) + ``` + + New (removed `plugin=self`): + + ```python + def plugin_info(self): + return PluginInfo(version='1.0.0', + ...) + ``` + +* Plugin `data_context.data_size` is now a variable instead of a method: + + Old: + + ```python + def process(self, trace: ExtractionTrace, data_context: DataContext): + size = data_context.data_size() + ``` + + New: + + ```python + def process(self, trace: ExtractionTrace, data_context: DataContext): + size = data_context.data_size + ``` + +* Simplify declaring required runtime resources in a plugin's info. + + Extraction plugin resources don't use the builder pattern anymore. + + Old: + + ```python + return PluginInfo( + ..., + resources=PluginResources.builder().maximum_cpu(0.5).maximum_memory(1000).build()) + ) + ``` + + New: + + ```python + # no need for a builder, declare resources by direct instantiation + return PluginInfo( + ..., + resources=PluginResources(maximum_cpu=2.0, maximum_memory=2048) + ) + # or, as before, specify just on resource + return PluginInfo( + ..., + resources=PluginResources(maximum_memory=4096) + ) + ``` + +## 0.5.1 + +* Simplify tracelet properties by making the tracelet type prefix optional. + + ```python + # using a Tracelet object + trace.add_tracelet(Tracelet("prediction", { + "type": "example", + "confidence": 0.8 + })) + # or without a Tracelet object + trace.add_tracelet("identity", {"name": "John Doe", "status": "online"}) + ``` + +* Enabled _manual_ plugin testing, as described on :ref:`advanced use of the test framework in Python`. + +## 0.5.0 + +* Support vector data type in trace properties. + + ```python + embedding = Vector.from_sequence((width, height)) + tracelet = Tracelet("prediction", { + "prediction.type": "example-vector", + "prediction.embedding": embedding + }) + trace.add_tracelet(tracelet) + ``` + +## 0.4.13 + +* When writing input search traces for tests, it is no longer required to explicitly set an `id` property. + These are automatically generated when executing tests. + +## 0.4.7 + +* More `$data` matchers are supported in Hansken.py plugin runner. Before this improvement it was only possible to match + on `$data.type`. Now it is also possible to match for example on `$data.mimeType` and `$data.mimeClass`. The `$data` + matcher should still be at the end of the query as before. + +## 0.4.6 + +* It is now possible to specify maximum system resources in the `PluginInfo`. To run a plugin with 0.5 cpu (= 0.5 + vCPU/Core/hyperthread) and 1 gb memory, for example, the following configuration can be added to `PluginInfo`: + + ```python + plugin_info = PluginInfo(..., + resources=PluginResources.builder().maximum_cpu(0.5).maximum_memory(1000).build()) + ``` + +## 0.4.0 + +* Extraction Plugins are now identified with a `PluginInfo.PluginId` containing a domain, category and name. The + method `PluginInfo.name(pluginName)` has been replaced by `PluginInfo.id(new PluginId(domain, category, name)`. More + details on the plugin naming conventions can be found at the :doc:`../concepts/plugin_naming_convention` section. + +* `PluginInfo.name()` is now deprecated (but will still work for backwards compatibility). + +* A new license field `PluginInfo.license` has also been added in this release. + +* The following example creates a PluginInfo for a plugin with the name `TestPlugin`, licensed under + the `Apache License 2.0` license: + + ```python + class TestPlugin(ExtractionPlugin): + def plugin_info(self) -> PluginInfo: + return PluginInfo(self, + version='1.0.0', + description='A plugin for testing.', + author=Author('The Externals', 'tester@holmes.nl', 'NFI'), + maturity=MaturityLevel.PROOF_OF_CONCEPT, + webpage_url='https://hansken.org', + matcher='file.extension=txt', + id=PluginId(domain='nfi.nl', category='test', name='TestPlugin'), + license='Apache License 2.0' + ) + ``` + +## 0.3.0 + +* Extraction Plugins can now create new datastreams on a Trace through data transformations. Data transformations + describe how data can be obtained from a source. + + An example case is an extraction plugin that processes an archive file. The plugin creates a child trace per entry in + the archive file. Each child trace will have a datastream that is a transformation that marks the start and length of + the entry in the original archive data. By just describing the data instead of specifying the actual data, a lot of + space is saved. + + Although Hansken supports various transformations, the Extraction Plugins SDK for now only supports ranged data + transformations. Ranged data transformations define data as a list of ranges, each range with an offset and length in + a bytearray. + + The following example sets a new datastream with dataType `html` on a trace, by setting a ranged data transformation: + + ```python + trace.add_transformation('html', RangedTransformation(Range(offset, length))) + ``` + + The following example creates a child trace and sets a new datastream with dataType `raw` on it, by setting a ranged + data transformation with two ranges: + + ```python + child = trace.child_builder('new trace') + child.add_transformation('raw', RangedTransformation.builder() + .add_range(10, 20) + .add_range(50, 30) + .build()) + }); + ``` + + More detailed documentation will follow in an upcoming SDK release. + +## 0.2.0 + +.. warning:: This is an API breaking change. + Plugins created with an earlier version of the extraction plugin + SDK are not compatible with Hansken that uses `0.2.0` or later. + +* Introduced a new extraction plugin type `api.extraction_plugin.DeferredExtractioPlugin`. + Deferred Extraction plugins can be run at a different extraction stage. + This type of plugin also allows accessing other traces using the searcher. + +* The class `api.extraction_context.ExtractionContext` has been renamed to `api.data_context.DataContext`. + The new name `DataContext` represents the class contents better. + Plugins have to update matching import statements accordingly. + Plugins should also update the named argument `context` to `data_context` of the plugin `process()` method. + This change has no functional changes. + + Old: + + ```python + from hansken_extraction_plugin.api.extraction_context import ExtractionContext + + def process(self, trace, context): + pass + + ``` + + New: + + ```python + from hansken_extraction_plugin.api.data_context import DataContext + + def process(self, trace, data_context): + pass + ``` + +* Moved `api.author.Author` to `api.plugin_info.Author`, and moved `api.maturity_level.MaturityLevel` + to `api.plugin_info.MaturityLevel` + This is a more *pythonic* way of grouping of classes into modules. This change has no functional side effects. + + Plugins have to update matching import statements accordingly. + + Old: + + ```python + from hansken_extraction_plugin.api.author import Author + from hansken_extraction_plugin.api.maturity_level import MaturityLevel + from hansken_extraction_plugin.api.plugin_info import PluginInfo + ``` + + New: + + ```python + from hansken_extraction_plugin.api.plugin_info import Author, MaturityLevel, PluginInfo + ``` + +* Removed `DataContext.get_first_bytes()` from the public API. + +* Removed `api.extraction_trace.validate_update_arguments(..)` from the public API. This method is still invoked + implicitly when setting trace properties. diff --git a/0.9.16/_sources/dev/python/debugging.md.txt b/0.9.16/_sources/dev/python/debugging.md.txt new file mode 100644 index 0000000..b4bdf6d --- /dev/null +++ b/0.9.16/_sources/dev/python/debugging.md.txt @@ -0,0 +1,161 @@ +# How to debug an Extraction Plugin + +Debugging is the art of removing bugs — hopefully quickly. + +## Locally + +To debug a plugin locally, it is recommended to start the plugin via the IDE. This has the advantage that breakpoints +can easily be put in the code instead of printing log statements, for example. To start a plugin locally, a piece of +code must be added, see [Testing](testing.md) for more information. + +### Logging + +The logging of the extraction plugin is displayed in the console. + +## Locally with Docker + +Debugging an extraction plugin via docker is a bit trickier. In order to debug in Python, a debugger must be added to +the extraction plugin. There are several debug modules for Python available, but one debug module that works well with +Visual Studio Code is [debugpy](https://github.com/microsoft/debugpy). This package is developed by Microsoft +specifically for use in Visual Studio Code with Python. + +.. note:: `debugpy` implements the Debug Adapter Protocol (DAP), which is a standardised way for development tools to + communicate with debuggers. + +Using `debugpy` with Docker containers requires 4 distinct steps: + +1. Install `debugpy` +2. Configuring `debugpy` in Python +3. Build a docker image +4. Configuring the connection to the Docker container +5. Setting breakpoints in your code + +### Install `debugpy` + +First, add `debugpy` to your `setup.py`. + +```python +from setuptools import setup + +setup( + # ... + install_requires=[ + "hansken-extraction-plugin==0.4.7", # the plugin SDK + "debugpy==1.5.1" + ] +) +``` + +### Configuring `debugpy` in Python + +At the beginning of your script, import `debugpy`, and call `debugpy.listen()` to start the debug adapter, passing +a `(host, port)` tuple as the first argument. Use the `debugpy.wait_for_client()` function to block program execution +until the client is attached. + +```python +import debugpy + +debugpy.listen(("0.0.0.0", 5678)) +debugpy.wait_for_client() # blocks execution until client is attached + +# your extraction plugin code +``` + +### Build a Docker image + +If the Docker image is not built, first build the image as described +[here](getting_started.md#Building a docker image for a Python plugin). + +### Configuring the connection to the Docker container + +`debugpy` is now set up to accept connections inside a Docker container. To connect to `debugpy` in the docker +container, port 5678 must be published. To make a port available to services outside of Docker, use the --publish or -p +flag. This creates a firewall rule which maps a container port to a port on the Docker host to the outside world. + +To run the extraction plugin with the published port the following command can be used: + +```bash +docker run -p 5678:5678 your_extraction_plugin_name +``` + +The next step is to configure Visual Studio Code. A `launch.json` file must be created in order for Visual Studio Code +to connect to the extraction plugin in Docker. This minimal `launch.json` example below tells the debugger to attach +to `localhost` on port `5678`. + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Remote Attach", + "type": "python", + "request": "attach", + "connect": { + "host": "localhost", + "port": 5678 + }, + "pathMappings": [ + { + "localRoot": "${workspaceFolder}", + "remoteRoot": "." + } + ] + } + ] +} +``` + +### Setting breakpoints in the code + +The last step is to add breakpoints in the code. + +### Logging in Docker + +The logging of the extraction plugin is displayed in the console after running the `docker run` command. In addition, +the logging is also displayed in the Visual Studio Code console while debugging. + +## Kubernetes + +In kubernetes it is currently _not_ possible to debug via `debugpy` because no debug ports are published. + +### Logging in Kubernetes + +If there is authorization to the kubernetes cluster, the logging can be viewed with the following command: + +```bash +kubectl logs -f hansken-extraction-plugins/your_extraction_plugin_pod +``` + +## Debug HQL + +An HQL query can be debugged by running the test framework with the `--verbose` option enabled. The found HQL matches +will then be displayed in the console. To test a plugin in python with the `--verbose` option enabled use the following +command: + +```bash +test_plugin --standalone plugin/your_plugin.py --regenerate --verbose +``` + +The following output will then be displayed in the console: + +```text +HQL match found for: +$data.type=jpg +With trace: +dataType=jpg +types={file, data} +properties={data.raw.mimeType=image/jpg, path=/test-input-trace, file.name=image.jpg, name=test-input-trace, id=0} +``` + +If the HQL query contains an error, it will be shown in the generated test results. An example of an invalid query +is ``$data.mimeType=image/jpg`` (slash not escaped). This query will produce an error like the one shown below. + +```json +{ + "class": "org.hansken.plugin.extraction.hql_lite.lang.ParseException", + "message": "HqlLiteHumanQueryParser: line 1:20 token recognition error at: '/jpg'" +} +``` + +.. note:: The error is only shown in the generated trace, so to find out the `ParseException` run the ``test_plugin`` + command with the ``--regenerate`` option enabled. diff --git a/0.9.16/_sources/dev/python/getting_started.md.txt b/0.9.16/_sources/dev/python/getting_started.md.txt new file mode 100644 index 0000000..be01bf3 --- /dev/null +++ b/0.9.16/_sources/dev/python/getting_started.md.txt @@ -0,0 +1,193 @@ +# Getting started + +Set up a development environment: step by step. + +The following section describes how to set up a fully working development environment for extraction plugins with Python. +This is written for those who are not comfortable setting up a working build environment. +This is **optional**; advanced users may choose a different development environment setup, and can skip this section completely. + +If you fail to set up a development environment, feel free to ask for help at our Discord channel. + +## Install required software on Ubuntu + +In order to be able to develop Hansken Extraction Plugins in Python on Ubuntu, the following build tools need be installed on your system: python, pip, tox, Java, Docker. + +* **Python, pip, tox, Java** + To install, run the following commands in your terminal: + + ```bash + sudo apt update + sudo apt install python3.10 python3-pip tox default-jdk + ``` + + You can check whether all versions are installed correctly by running the following commands (and validate the output): + + ```bash + python --version + # should return version 3.10.15 or higher + + pip3 --version + # should return version 20.0.2 or higher + + tox --version + # should return version 3.11.2 or higher + + java -version + # should return version 11.0.4 or higher + ``` + +If the above software is installed, you can continue with "Install Docker", +or if you don't want to install Docker, continue with "Install your IDE: Pycharm". + +## Install required software on Windows + +In order to be able to develop Hansken Extraction Plugins in Python on Windows, follow the next steps: + +* For verification of the installation of each program we will use commands on the command prompt. + This can be opened by clicking the Windows Start button and typing: + + ```bash + cmd + ``` + + Then hit Enter . This will open the command prompt where you can enter the commands given in the following steps. + +* **Python 3.10 or higher & pip** + Download the installer from [python.org/Downloads](https://www.python.org/downloads/) (click the yellow "Download Python" button) + and run it to install Python and pip. + Pip is the standard package manager for Python. + It allows you to install and manage additional packages that are not part of the Python standard library, like the Extraction Plugins SDK. + + Be sure to select the option "Add python to PATH". + + When the installation is complete, verify the installation by checking the Python and pip versions: + + ```bash + python --version + # should return your downloaded Python version (>3.10.4) + + pip3 --version + # should return 20.2.3 or higher + ``` + +* **tox** + Tox is used to automate and standardize testing in Python. Use Pip to install Tox with this command: + + ```bash + pip install tox + ``` + + Verify that Tox is installed by running: + + ```bash + tox --version + # should return 3.23.0 or higher + ``` + +* **Java JDK 11.0.4 (or higher)** + Java JDK 11.0.4 or higher is needed to run the test framework of the Extraction Plugins SDK. + This enables you to test without actually deploying the plugin in Hansken. + Installing Java on Windows can be done in many different way, but for now we can not recommend one method. + Please have a look at [Install the Microsoft Build of OpenJDK](https://docs.microsoft.com/en-us/java/openjdk/install) for more details. + + ```bash + java -version + # should return 11.0.4 or higher + ``` + + N.b. Make sure to set the environment variable in case the installed JDK is not detected by the system. + You can follow the below-mentioned steps to set the environment variable: + + 1. Click the Windows start button + 2. Type "advanced system settings" + 3. Hit enter + 4. Now click on Environment Variables, select Path under System Variables section and click on Edit. We need to add the path of installed JDK to system Path. + 5. Click on New Button and add the path to installed JDK bin which is C:\java\java-11\jdk-11.0.4\bin in our case. + 6. Press OK Button 3 times to close all the windows. This sets the JDK 11 on system environment variables to access the same from the console. + +If the above software is installed, you can continue with "Install Docker", +or if you don't want to install Docker, continue with "Install your IDE: Pycharm". + +## Install Docker (Ubuntu, Windows) + +Installing Docker is a bit more complicated. The Docker website describes the installation instructions in detail. +Please follow the instructions on [docs.docker.gom/get-docker/](https://docs.docker.com/get-docker/) to install docker. + +* To check you have Docker installed correctly, run + + ```bash + docker --version + # should return version 20.10.17 or higher + ``` + +Note: if you run Docker inside a managed network, you might also need to configure proxies and/or certificates. +Please contact your system administrator if you need help with this. + +## Set up your IDE: PyCharm + +We recommend that you use an IDE to aid you in your development of Extraction Plugins. PyCharm is a good choice. + +* JetBrains has an excellent installation guide on their webpage: [Click here to go to the Pycharm Installation Guide](https://www.jetbrains.com/help/pycharm/installation-guide.html) + +## Download an extraction plugin template (empty plugin) + +You can download an extraction plugin template. +This is an empty plugin, from which you can rapidly start your plugin development. + +* The template is hosted on GitHub [here](https://github.com/NetherlandsForensicInstitute/hansken-extraction-plugin-template-python). + You can download a zip with the template from here. The below screenshot shows where the download button is located: + + ![](getting_started/download_template.png) + +## Import the Extraction Plugins Skeleton in PyCharm + +* First unzip the skeleton plugin downloaded from the previous step. +* Next, start PyCharm. +* When PyCharm starts, choose "Open" and select the folder where you placed the Extraction Plugin Skeleton. +![](getting_started/pycharm_open_project.png) + +* The following popup will appear, click OK . +![](getting_started/pycharm_open_project_venv.png) + +* The Extraction Plugins Skeleton is now loaded in PyCharm, which should look as follows: +![](getting_started/pycharm_project_start_page.png) + +* Be sure to give the `README.md` a read when you are done with the Prerequisites. + +## Verify full setup + +To verify that your system has been setup correctly, you can run the test suite in the Extraction Plugin Skeleton: + +* First, press `alt-F12` at the same time to open a terminal in PyCharm in the project root folder. +* To run the tests of the Skeleton, run this command in the terminal from the root folder: + + ```bash + tox + ``` + + The first time running tox may take a few minutes! Please be patient 😊 + + Tox will install all required plugin dependencies, and start your tests. + N.b. The plugin template demonstrates how to build a plugin with tox. + Some plugin developers choose a different tool than tox. + +* If your system has been set up correctly, the output should end with a summary like this: + + ```bash + py38: commands succeeded + congratulations :) + ``` + + This means the setup is finished. You now have everything installed to start coding your own plugin! + +## Next steps + +Now that you have a working environment, you can start doing cool stuff. +Please have a look at the following pages for more information: + +* [Packaging](packaging.md): how to package your plugin and use it in Hansken +* [Run plugins with Hansken.py](hanskenpy.md): run your plugin on a case without uploading the plugin to Hansken, useful for quick prototyping +* [Transformers for on-demand execution](transformers.md): how to write a transformer to execute code on-demand outside extraction time. +* [Testing](testing.md): how to write tests for your plugin +* [Debugging](debugging.md): if your plugin isn't working as expected, you can debug it +* [Snippets](snippets.md): code snippets to demonstrate common plugin usage patterns diff --git a/0.9.16/_sources/dev/python/hanskenpy.md.txt b/0.9.16/_sources/dev/python/hanskenpy.md.txt new file mode 100644 index 0000000..32d3022 --- /dev/null +++ b/0.9.16/_sources/dev/python/hanskenpy.md.txt @@ -0,0 +1,91 @@ +# Run plugins with Hansken.py + +Hansken.py is a Python client to Hansken's REST API, developed and maintained by the Netherlands Forensic Institute. + +With Hansken.py, you can run your Python plugin on a project on your Hansken installation that has already been +extracted. This way of running your plugin is useful during your plugin development. It is not required to upload your +plugin to Hansken and start an extraction, making the development cycle faster. However, please note that this is only +useful during the development stage of your plugin, as the execution of your plugin will be much slower compared to +running the plugin during a Hansken extraction. + +.. note:: The execution of your plugin will be much slower in Hansken.py compared to running the plugin during a Hansken + extraction. + +## How to run python extraction plugins standalone with Hansken.py + +Running python extraction plugins standalone with Hansken.py is easy. It is just one command. This section explains how +to setup this command for your specific environment. + +### Create a runner file + +Create a file `run_with_hansken.py` in the root folder of your plugin. This will aid you in running the plugin with +hansken.py. + +```python +from hansken_extraction_plugin.runtime.extraction_plugin_runner import run_with_hanskenpy + +from plugin.my_plugin import MyPlugin + +if __name__ == '__main__': + run_with_hanskenpy(MyPlugin) +``` + +### Preparing for the command + +Before you can enter the command that runs your extraction plugin with Hansken.py, you need to find three values: + +* `HANSKEN_PROJECT_ID` project id on which you want to run your plugin +* `YOUR_GATEKEEPER_URL` the URL to the Hansken gatekeeper +* `YOUR_KEYSTORE_URL` the URL to your keystore + +The correct values of these variables can be found in the Expert UI. Go to the search-page of your project in the +ExpertUI. Next to the search-bar hit the button "Save query". + +![hanskenpy_save_query.png](hanskenpy_save_query.png) + +A new dialog shows up. At the bottom of this dialog, you will find your gatekeeper and keystore urls as well as the +project id. + +![hanskenpy_gatekeeper_keystore.png](hanskenpy_gatekeeper_keystore.png) + +### Running your plugin with Hansken.py + +Next, open a terminal in the project root folder of your plugin and enter the following command. It will run your +extraction plugin with Hansken.py in Hansken. Replace the three variables with their respective values. + +```bash +python3 ./run_with_hanskenpy.py -v -l - HANSKEN_PROJECT_ID --endpoint YOUR_GATEKEEPER_URL --keystore YOUR_KEYSTORE_URL +``` + +If your command runs well, you might be prompted for your username and password. There will be some output (note that +the output may vary depending on your system setup and project content): + +```text +[2021-03-16 12:59:45.344248+0000] INFO: hansken.auth: selected IDP ID (...) with SOAP endpoint (...) +[2021-03-16 12:59:45.344450+0000] WARNING: hansken.auth: IDP url known, user+pass auth required but no username supplied +username []: testaccount +[2021-03-16 12:59:48.423245+0000] INFO: hansken.auth: user acknowledged environment username or supplied custom username: testaccount +password for user testaccount: +[2021-03-16 12:59:53.799668+0000] INFO: hansken.auth: identity provider url and user+pass provided or known, using Keycloak SAML with Basic auth +[2021-03-16 12:59:53.805538+0000] INFO: hansken_extraction_plugin.runtime.extraction_plugin_runner: PluginRunner is running plugin class Plugin +[2021-03-16 12:59:53.859299+0000] INFO: hansken.auth: posting SAML request with authorization for user testaccount to IDP endpoint (...) +[2021-03-16 12:59:54.240290+0000] INFO: plugin.extraction_plugin: processing trace 54197e67-8135-40c3-93f1-3d73a5552693 +[2021-03-16 12:59:54.240753+0000] INFO: plugin.extraction_plugin: processing trace OCRimage +[2021-03-16 12:59:54.240753+0000] INFO: plugin.extraction_plugin: processing trace (...) +``` + +Note that the arguments `-v` and `-l -` are passed to enable logging. To find out what other options can be passed to +this command, please have a look at the hansken.py documentation, or simply run the following command: + +```bash +python3 ./run_with_hanskenpy.py --help +``` + +## Compatibility + +At this moment, running Extraction Plugins with Hansken.py has a few limitations. These are: + +* When writing an Extraction Plugin for use with Hansken.py, the matcher must contain exactly one "$data.property = + value" expression. +* [Data transformations](../concepts/data_transformations.md) are currently not supported by Hansken.py. +* :ref:`Tracelets` are not yet supported by the SDK in use with Hansken.py. diff --git a/0.9.16/_sources/dev/python/packaging.md.txt b/0.9.16/_sources/dev/python/packaging.md.txt new file mode 100644 index 0000000..a6096a9 --- /dev/null +++ b/0.9.16/_sources/dev/python/packaging.md.txt @@ -0,0 +1,136 @@ +# Packaging + +Extraction plugins are packaged as OCI images (also known as Docker images). +The OCI images are _labeled_ with the PluginInfo. +To automate packaging of a Python plugin and labeling the OCI image, +the Extraction Plugin SDK comes with three utility applications: `label_plugin`, `build_plugin` and `build_plugin_ci`. + +To package a plugin, make sure that the Extraction Plugins SDK is [installed](getting_started.md#Installation), as well as Docker. +Next build and label your plugin as described in the following sections. + +To verify that the image has been built, use the following command to view all local images: + +```bash +docker images +``` + +Once your plugin is packaged and labelled, it can be published or 'uploaded' to Hansken. +See ":ref:`upload_plugin`" for instructions. + +## `label_plugin` + +`label_plugin` is a utility to add labels to an extraction plugin image. +To label a plugin, first build the plugin image with [docker build](https://docs.docker.com/reference/cli/docker/image/build/); +for example by using one of the following commands: + +```shell +docker build . -t my_plugin +docker build . -t my_plugin --build-arg https_proxy=http://your_proxy:8080 +``` + +Next, run the `label_plugin` utility to label the build plugin container: + +```shell +label_plugin my_plugin +``` + +This utility will briefly start your plugin using Docker, and requests the PluginInfo from the plugin. +The information from the PluginInfo will be added as [labels](https://docs.docker.com/config/labels-custom-metadata/) to the plugin image. +The result of `label_plugin` is a plugin image that can be published to a docker/OCI image registry. + +## `build_plugin` + +The `build_plugin` extends `label_plugin` by also taking care of the docker build command. +Use this as an one-liner to both build and label your plugin image. + +To build your plugin container image you can use the following command: + +```bash +build_plugin DOCKER_FILE_DIRECTORY [DOCKER_IMAGE_NAME] [DOCKER_ARGS] +``` + +For example: + +```bash +build_plugin . +``` + +and to pass proxy configurations to Docker: + +```bash +build_plugin . --build-arg http_proxy="$http_proxy" --build-arg https_proxy="$https_proxy" +``` + +This will generate a plugin image: +* The extraction plugin is added to your local image registry (`docker images`), +* Note that the variables `$http_proxy` and `$https_proxy` are put in quotes, this is needed in case they contain + spaces, +* The image is tagged with two tags: `latest`, and your plugin version. + +Arguments: +* `DOCKER_FILE_DIRECTORY`: Path to the directory containing the Dockerfile of the plugin. +* (Optional) `DOCKER\_IMAGE\_NAME`: Name of the docker image without tag. Note that docker image names cannot start with + a period or dash. If it starts with a dash, it will be interpreted as an additional docker argument (see + DOCKER\_ARGS). If no name is given the name defaults to `extraction-plugin/PLUGINID`, e.g. + `extraction-plugin/nfi.nl/extract/chat/whatsapp`. +* (Optional) `DOCKER\_ARGS`: Additional arguments for the docker command, which can be as many arguments as you like. + +## `build_plugin_ci` + +The `build_plugin_ci` performs the same tasks as `build_plugin` except that it uses a different approach for labeling +the plugin. Not all CI/CD pipelines allow docker containers to be started and connected to, something which +`build_plugin` relies on to label the plugin correctly using the plugin info specified in the plugin. `build_plugin_ci` +uses another approach which exports the image and then parses the plugin info from this image. This way a container +does not have to be started. Therefore the advantage of `build_plugin_ci` is that it can more reliably build plugins on +CI systems. The downside of this approach is that it is slower than `build_plugin` utility. It is therefore adviced to +use `build_plugin` when developing locally to speed up the development process and to use `build_plugin_ci` when +building plugins in CI/CD pipelines. + +### Requirements + +To build your plugin container image using `build_plugin_ci` you have to add the following line to your Containerfile +after you have copied your plugin to the image. `build_plugin_ci` requires this to find the plugin information. + + +``` +RUN plugin_info "/app/plugin.py" +``` + +### Command usage + +`build_plugin_ci` can be invoked as follows: + +```bash +build_plugin DOCKER_FILE_DIRECTORY [--target_name DOCKER_IMAGE_NAME] [--build_agent BUILD_AGENT] [BUILD_AGENT_ARGS] +``` + +Other than the options provided by `build_plugin` `build_plugin_ci` also provides a `--build_agent` flag which allows a +user to choose between different build agents to build and label their plugin. Currently only docker, podman and +buildah are supported. For example: + +```bash +build_plugin . --target_name my-image:1.3.5 --build_agent "podman" +``` + +A proxy configurations can be configured as follows: + +```bash +build_plugin . --build-arg http_proxy="$http_proxy" --build-arg https_proxy="$https_proxy" +``` + +This will generate a plugin image: +* The extraction plugin is added to your local image registry (`docker images`), +* Note that the variables `$http_proxy` and `$https_proxy` are put in quotes, this is needed in case they contain + spaces, +* The image is tagged with two tags: `latest`, and your plugin version. + +Arguments: +* `DOCKER_FILE_DIRECTORY`: Path to the directory containing the Dockerfile of the plugin. +* (Optional) `DOCKER\_IMAGE\_NAME`: Name of the docker image without tag. Note that docker image names cannot start with + a period or dash. If it starts with a dash, it will be interpreted as an additional docker argument (see + DOCKER\_ARGS). If no name is given the name defaults to `extraction-plugin/PLUGINID`, e.g. + `extraction-plugin/nfi.nl/extract/chat/whatsapp`. +* (Optional) `BUILD\_AGENT`: The build agent that should be used to build the plugin. Either docker, podman or buildah. + Docker is the default. +* (Optional) `BUILD\_AGENT\_ARGS`: Additional arguments for the buildagent command, which can be as many arguments as + you like. diff --git a/0.9.16/_sources/dev/python/prerequisites.md.txt b/0.9.16/_sources/dev/python/prerequisites.md.txt new file mode 100644 index 0000000..5a0cfd3 --- /dev/null +++ b/0.9.16/_sources/dev/python/prerequisites.md.txt @@ -0,0 +1,9 @@ +# Prerequisites + +All required project dependencies to build extraction plugins are published on the public [PyPI](https://pypi.org/project/hansken-extraction-plugin/). + +Required: + +* Python 3.10 or higher +* Java 11 (for running the test-framework, which is implemented in Java) +* Docker (for packaging and deploying extraction plugins in containers, can be omitted if you have an external build pipeline that provides Docker) diff --git a/0.9.16/_sources/dev/python/snippets.md.txt b/0.9.16/_sources/dev/python/snippets.md.txt new file mode 100644 index 0000000..1df84d4 --- /dev/null +++ b/0.9.16/_sources/dev/python/snippets.md.txt @@ -0,0 +1,286 @@ +# Python code snippets + +## Adding properties to a trace + +Use :py:meth:`update ` +to add trace types and their properties to an +:py:class:`ExtractionTrace `. +Example: + +```python +def process(self, trace, data_context): + # get the name of the file + file_name = trace.get('file.name') + # set the chat application property on the trace + trace.update('chatConversation.application', f'DemoApp {file_name}') +``` + +All types and properties that can be set are defined in the :ref:`Hansken trace model`. + +### Date properties + +When adding a property which holds a value of data-type Date, always define timezone as being UTC. Example: + +```python +def process(self, trace, data_context): + trace.update('file.modifiedOn', + datetime.fromtimestamp(1630510809, tz=timezone.utc)) +``` + +### Category for extra properties + +If the information, which must be added as a property, does not match any of the existing properties of Hansken trace +model, use the category "misc" (miscellaneous). When part of the category "misc", any name can be given to a property. +The values of miscellaneous properties are expected to be of data-type string. Example: + +```python +def process(self, trace, data_context): + trace.update({ + 'file.misc.notes': 'Some additional notes about the file trace.', + 'file.misc.anyName': 'Even more notes.' + }) +``` + +.. _tracelets python: + +### Adding tracelets + +In the following Python example, a "prediction" :ref:`tracelet` is added to a trace. The tracelet consists +of a list of four properties, namely "class", "confidence", "modelName" and "modelVersion". + +```python +trace.add_tracelet(Tracelet('prediction', {'class': 'telephone', + 'confidence': 0.8, + 'modelName': 'yolo', + 'modelVersion': '2.0'})) +``` + +## Adding child traces to a trace + +Adding child traces to the trace can be done by creating a builder with +:py:meth:`child_builder `. +Example: + +```python +def process(self, trace, data_context): + child_builder = trace.child_builder('childTrace-1') + child_builder.update({ + 'chatMessage.application': 'DemoApp', + 'chatMessage.from': 'Ann', + 'chatMessage.to': ['Mark'], + # list, because there can be multiple receivers + 'chatMessage.message': 'Hello, are you there?', + }).build() + grandchild_builder = child_builder.child_builder('grandchild') + grandchild_builder.update(data={'byte': b'some bytes'}) + grandchild_builder.build() +``` + +This adds a single child trace with name `childTrace-1` with four properties and a grandchild trace with name +`grandchild` and a byte data stream. + +.. _datastreams python: + +## Adding data to a trace + +Traces can have data attached to them. See :ref:`datastreams` for more information. +The following two snippets demonstrate how to add data to a trace. + +It is currently not possible to verify that a specific data stream is already set or not. + +### Data Transformations + +The most efficient way to add data to a trace is using data transformations. +See :doc:`../concepts/data_transformations` for more details. + +The following example sets a new datastream with dataType `html` on a trace, by setting a ranged data transformation: + +```python +trace.add_transformation('html', RangedTransformation(Range(offset, length))) +``` + +The following example creates a child trace and sets a new datastream with dataType `raw` on it, by setting a ranged +data transformation with two ranges: + +```python +child = trace.child_builder('new trace') +child.add_transformation('raw', RangedTransformation.builder() + .add_range(10, 20) + .add_range(50, 30) + .build()) +}); +``` + +### Blobs + +It is not always possible to create a transformation for the data that has to be +added to a trace. For example, if the data is a result of a computation, and not +a direct subset of another data stream.. + +The following snippet shows how to create a new data stream of dataType `raw` on a trace from a blob stored in `bytes`: + +```python +data = {'raw': b'...'} +trace.update(data=data); +``` + +.. _python_snippets_data_streaming: + +#### Streaming data + +.. warning:: Streaming data does not work with the Hansken.py runner because Hansken.py does not support it. It does + work when running your plugin in Hansken and in the test framework. + +When dealing with large quantities of data, it is possible to keep the memory usage +of the plugin within manageable limits by streaming the data from the plugin to Hansken in smaller chunks. +To do this, use the `with trace.open(data_type=..., mode='wb')` syntax. Here are some examples: + +Stream strings to `raw` (default) datastream: + +```python +with trace.open(mode='wb') as writer: + writer.write(b'a string') + writer.write(bytes(another_string, 'utf-8')) +``` + +Stream a BufferedReader object to a `text` datastream: + +```python +with trace.open(data_type='text', mode='wb') as output, open('input.text', 'rb') as in_file: + output.write(in_file) +``` + +#### Streaming text + +To write `str` values directly, use mode `w` (or `wt`). +By default, it is assumed that the written text is 'utf-8' encoded. The default encoding can be overwritten by using the `'encoding='` argument. + +(In a future Hansken update) Hansken will set the correct data-stream properties for your text stream (`mimeType`, `mimeClass`, and `fileType`). + +```python +with trace.open(data_type='raw', mode='w', encoding='utf-8') as text_writer: + text_writer.write('hello.world') # write strings directly to the writer + json.dump({'hello': 'world'}, text_writer) # or pass the writer to json.dump +``` + +It is recommended to pass `utf-8` explictly as encoding. + +## Specifying system resources + +It is possible to specify system resources hints in the `PluginInfo`. To run a plugin with at least 0.5 cpu (= 0.5 +vCPU/Core/hyperthread), 1 gb memory and 10 (concurrent) cpu workers (threads), for example, the following configuration can be added to `PluginInfo`: + +```python +plugin_info = PluginInfo(..., + resources=PluginResources(maximum_cpu=0.5, maximum_memory=1000, maximum_workers=10)) +``` + +.. _python_snippets_deferred: + +## Deferred Plugins + +Implementing a deferred extraction plugin requires inheriting the +:py:class:`DeferredExtractionPlugin ` +base class. + +```python +class DeferredPlugin(DeferredExtractionPlugin): + def process(self, trace, context, searcher): +``` + +This allows accessing a third :py:class:`TraceSearcher ` +parameter in the process function. This can be used to search for traces: + +```python +with searcher.search('file.extension:html', 10, scope='image') as searchresult: + for trace in searchresult: + log.debug(f'extension {trace.get("file.extension")}') +``` + +The ``search`` method accepts three arguments; +1. a HQL query (note: this is the traditional HQL query, and not the matchers HQL-lite variant), +2. (optional) the maximum number of traces to return (currently hard-limited to a maximum of 50 traces), +3. (optional) a scope, which can be either `image`, or `project`. When set to `image`, the searcher will only search for traces + within the same image as the trace that is being processed. + +The returned :py:class:`SearchResult ` +should be closed, for example by using `with`. The resulting search result is an iterable, which will be exhausted when +no more traces are available. The search result allows taking one or more traces by calling :py: +meth:`take ` or +:py:meth:`takeone `. + +.. note:: The command `trace.open(datastream_type)` will fail on search result traces that do not originate from the + same image (evidence item) as the trace that is being processed. + +## Deferred Meta Extraction Plugins + +Implementing a deferred meta extraction plugin requires inheriting the +:py:class:`DeferredMetaExtractionPlugin ` +base class. This plugin is not able to call the trace.open() method since the actual trace data is not available to this plugin. +Also matching on data type will not work for this plugin since this plugin only works for meta traces + +```python +class DeferredMetaPlugin(DeferredMetaExtractionPlugin): + def plugin_info(self): + ... + + def process(self, trace, searcher): + ... +``` + +## Bulk Mode + +The `PluginInfo` contains a parameter `bulk_mode`. This can be used for lightweight plugins which have to process a lot +of data (either a lot of traces with data or a small number of traces with large data streams). For streaming +extractions, these plugins will run inside the worker pod, and will therefore be able to process data more efficiently. + +**WARNING**: The plugin should be lightweight. This means that it should not use a lot of resources like CPU or memory, +because this will limit the resources of the worker pod, and therefore Hansken will not be able to start enough workers +to do extractions. + +Creating a plugin with bulk mode enabled can be done by setting the parameter to `True` in the `PluginInfo` as follows: + +```python +plugin_info = PluginInfo(..., + bulk_mode=True) +``` + +## Logging + +We use Logbook to log messages in Python. Logbook is a logging system for Python that replaces the standard library’s +logging module. + +To enable logging in your plugin, add the following to the top of your plugin code: + +```python +from logbook import Logger + +log = Logger(__name__) +``` + +From there on the logging is pretty straight forward: + +```python +log.info(f'Logging a variable: {my_variable}') +``` + +The default log level is `WARNING`. There are two ways to set the logging level. You can use the `-v` (or `-vv` or `-vvv`) option of `serve_plugin.py` to increase the log level. This is typically done in the plugin `Dockerfile`. Another option is to use an environment variable, `LOG_LEVEL`. Available levels are `WARNING`, `NOTICE`, `INFO` and `DEBUG`. The environment variable overrides the option. + +.. warning:: Be careful with logging sensitive information. + +.. note:: Contact your Hansken administrator for more information on where to find logs for your Hansken environment. + +## [EXPERIMENTAL FEATURE] Adding previews to a trace + +.. warning:: This is an experimental feature, which might change or get removed in future releases. + +Use :py:meth:`update ` +to add previews to an +:py:class:`ExtractionTrace `. +Example: + +```python +def process(self, trace, data_context): + # set the preview data for the image/png MIME-type + trace.update('preview.image/png', b'\x00\xff') +``` diff --git a/0.9.16/_sources/dev/python/testing.md.txt b/0.9.16/_sources/dev/python/testing.md.txt new file mode 100644 index 0000000..a198ffd --- /dev/null +++ b/0.9.16/_sources/dev/python/testing.md.txt @@ -0,0 +1,134 @@ +# Advanced use of the Test Framework in Python + +.. _python testing: + +This section assumes you use the same setup as is used in +the [Extraction Plugin Examples](https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples). + +By default, the build scripts as described in the [Getting Started](getting_started.md) section will automatically run +tests. The appropriate commands have been added to the tox.ini directly. This section gives a little more detail on the +test commands and options. + +One can simply create unit tests for a plugin directly. However, we also provide a test-framework for testing them over +gRPC. The test-framework serves a running instance of a Python plugin, and feeds it input files and compares the results +against an expected result set. + +Note that the test-framework is implemented in Java, hence the Java 11 requirement. A jar file is included in the Python +SDK which is called from a Python wrapper. + +## Regenerate expected test results + +The build and test scripts run some integration tests. To update the expected test outcome, the following command can be +used: + +```bash +tox -e regenerate +``` + +## Standalone testing + +The test runner is a script called `test_plugin` which is available in the SDK. + +To get started, `cd` into the directory of the plugin you want to test and run: + +```bash +test_plugin --standalone plugin/chat_plugin.py +``` + +Note that the argument provided to the option `--standalone` in this example is the relative path to the plugin `py` +file which is to be tested. This test accepts input files from the directory `testdata/input` and compares the results +to the result files in found in `testdata/results`. Use the optional argument `--regenerate` to regenerate the expected +results for the test when needed. + +This standalone test is also used by the `tox.ini` file to validate the plugin. Simply calling `tox` should be enough to +install all dependencies and run the test. + +In case the plugin was defined in a module that is to be imported by the interpreter, it's also possible to run this +command by referencing either the module that defines the plugin or the plugin directly: + +```bash +test_plugin --standalone plugin_module +# or, assuming the plugin class is called ChatPlugin +test_plugin --standalone plugin_module:ChatPlugin +``` + +## Testing with a Docker image + +If there is a docker image available for the plugin you can also test it by executing: + +```bash +test_plugin --docker extraction-plugin-examples-my-plugin +``` + +Replace the 'extraction-plugin-examples-chat' with the docker image you want to test. Run the following command to see +which docker images are available: + +```bash +docker images +``` + +## Manual testing + +The third option for testing is a manually started plugin. Start the plugin service in a terminal by executing: + +```bash +serve_plugin -vvv plugin/my_plugin.py +``` + +This will spin up the chat plugin at port 8999. In this example the argument is also a path to the plugin's `.py` file. +The same alternative reference to the plugin shown with `test_plugin` above applies here. + +In another terminal window, run the test with: + +```bash +test_plugin --manual localhost 8999 +``` + +## Tip: Start tests in your IDE + +To start the extraction plugin from code, create a `__main__` method which calls the `_test_validate_standalone` +method of the test framework (see the example below). This method causes the extraction plugin to be started and +supplied with data by the FLITS test framework. In this way the test can be started from the IDE, which has the +advantage that it is easier to debug. + +```python +from hansken_extraction_plugin.test_framework.test_plugin import _test_validate_standalone +from hansken_extraction_plugin.api.extraction_plugin import ExtractionPlugin + + +class PluginToTest(ExtractionPlugin): + + def plugin_info(self): + # return plugin info + pass + + def process(self, trace, data_context): + # process the data/trace here + pass + + +if __name__ == '__main__': + _test_validate_standalone(PluginToTest, 'testdata/input', 'testdata/result', False) +``` + +## Help + +Run the following for an overview of all the available options in the test script: + +```bash +test_plugin --help +``` + +## Testing transformers + +The sdk includes a script to test transformer functions. This script will start an extraction plugin, executes a single transformer function with the provided arguments and stops the plugin. Try it with: + +```bash +execute_transformer docker_image method_name arguments +``` + +The arguments are provided in named argument pairs, so calling a method called `translate` with two parameters `language` and `input` might look like this: + +```bash +execute_transformer translator_plugin translate language nl_NL input "example input" +``` diff --git a/0.9.16/_sources/dev/python/transformers.md.txt b/0.9.16/_sources/dev/python/transformers.md.txt new file mode 100644 index 0000000..c0f6bfe --- /dev/null +++ b/0.9.16/_sources/dev/python/transformers.md.txt @@ -0,0 +1,100 @@ +# Using Transformers for on-demand execution + +## What are Transformers? + +Transformers are methods inside a plugin that can be called remotely at any moment. +This allows for live plugin execution independent of extraction. +Examples on how transformers could be used: +- For searching images using text (i.e. a purple car). +- For translating text in traces so that an investigator can read the text in their preferred language in a UI. +- For converting speech to text. + +## How do Transformers work in Hansken? + +Transformers can be implemented in extraction plugins. Using the Hansken REST API, calls can be made to a +specific plugin's transformer by specifying the transformer one wishes to call as well as its arguments. +Hansken can automatically discover transformers before plugins are actually started. +Once it has received a request for invoking a transformer it can choose to start the plugin's Docker container if it +is not already started and send the request once it is up and running. + +## Developing Transformers + +This section assumes you use the same setup as is used in the [Extraction Plugin Examples](https://github.com/NetherlandsForensicInstitute/hansken-extraction-plugin-template-python/). + +A transformer can be easily defined by using the transformer decorator. By creating a method inside your plugin and +decorating it with the transformer decorator it will automatically be made available to be remotely called. + +```python +from hansken_extraction_plugin.api.extraction_plugin import ExtractionPlugin +from hansken_extraction_plugin.decorators.transformer import transformer +class Plugin(ExtractionPlugin): + + def plugin_info(self): + ... + + def process(self, trace, data_context): + ... + + @transformer + def translate_text(self, text: str, language: str) -> str: + # To implement: Translate the text here. + return "Translated text" + +``` + +## Limitations on Transformers + +However, there are some limitations on which methods can be turned into a decorator method: + +- Transformers may only be defined on methods of a class that derives (indirectly) from BaseExtractionPlugin. + - Note: ExtractionPlugin derives from BaseExtractionPlugin and is therefore allowed. +- Transformer may not be static methods. +- All parameters and the return type must be annotated with type hints (except the `self` parameter). +- Parameters may not be positional-only or contain variable parameters like `*args` or `**kwarg`. +- Parameters and return types may only be of the following (returning None is not supported): + - bool + - int + - float + - str + - bytes + - bytearray + - datetime.datetime (The datetime will be converted to unix time and then converted to datetime with the zone "UTC". So the zone id is always("UTC")) + - hansken.util.GeographicLocation + - hansken.util.Vector + - typing.Sequence + - typing.Mapping + +Upon starting a plugin every method decorated with the transformer decorator will be automatically validated to see if they adhere to these requirements. An exception will be thrown when a method does not adhere to all of these requirements. + +## Error handling in Transformers + +If at some point a transformer wishes to signal to the caller of the transformer that something has gone wrong +it can simply throw a suitable exception. Any exceptions being thrown will automatically be propagated to the client +calling the transformer by wrapping the exception in a gRPC exception. The stack trace will be provided as well for +debugging purposes. + +## Testing transformers + +For more information on testing transformers, see the 'Testing Transformers' section on the [page on testing plugins](testing.md). + +## Calling transformer with /tools/transformers + +This REST Call calls a specified transformer method on a given tool/plugin with supplied arguments. +This endpoint allows a transformer to be executed on demand, outside an extraction. The transformer call can be used to transform user input to an output. A tool/plugin can have multiple transformer methods. +To use /tools/transformers REST CALL you need to know the following (see extractions tool or use the rest call/tools to get the information below): +- The name of the plugin/tool +- The transformer name +- The names of the parameters (arguments) + +Example JSON request body for the transformer above: + +```JSON +{ + "arguments": { + "text": "value1", + "language": "value2" + }, + "tool": "ExampleTool", + "transformer": "translate_text" +} +``` diff --git a/0.9.16/_sources/dev/spec.md.txt b/0.9.16/_sources/dev/spec.md.txt new file mode 100644 index 0000000..2c23ddb --- /dev/null +++ b/0.9.16/_sources/dev/spec.md.txt @@ -0,0 +1,67 @@ +# Extraction Plugin specifications + +.. note:: If you use the Java or Python extraction plugin SDK, you don't have + to worry about these specifications. The Java and Python SDKs makes + sure your plugin is compiled and packaged conform to the extraction + plugin specifications. + +This page describes the specifications that define an extraction plugin. +The spec contains two major parts: a plugin protocol, and the plugin packaging +method. + +This specification applies to plugins that are not embedded within Hansken, +but to plugins that developed and distributed outside the scope of the Hansken +platform development. + +## Plugin protocol + +An extraction plugin is a process that implements a [GRPC](https://grpc.io/) +service `ExtractionPluginService`. The service defines a protocol that is +used to allow communication between Hansken and an extraction plugin. The +GRPC and protocol definitions can be found in the extraction plugin source +code, under the folder `grpc`. + +.. note:: The source code of the Extraction Plugin is currently not available + outside the scope of the Hansken core development teams. If you are + interested in the GRPC definitions, please :doc:`../contact` the + Hansken development team. + +## Packaging + +An extraction plugin is packaged as a container image -- conform the open +container initiative [image spec](https://github.com/opencontainers/image-spec). +An extraction plugin can be + +The `ENTRYPOINT` of the container image should be a process that starts a GRPC +server that implements the plugin protocol. The GRPC protocol should run on port +`8999` by default. The plugin should always observe the `PLUGIN_PORT` environment +variable, and run on that port if set. + +The container image should be labeled with the plugin info. +The plugin info returned by the plugin plugin-info call and container labels +are required to match. If not, Hansken will not accept your plugin during +extractions - as it is unsure if the intended plugin is processing traces. + +The labels that are expected are: + +* `org.hansken.plugin-info.id` (conform :doc:`concepts/plugin_naming_convention`) +* `org.hansken.plugin-info.version` +* `org.hansken.plugin-info.api-version` +* `org.hansken.plugin-info.description` +* `org.hansken.plugin-info.webpage` +* `org.hansken.plugin-info.deferred-iterations` (optional, only has a meaning for deferred extraction plugins) +* `org.hansken.plugin-info.matcher` (see :doc:`concepts/hql_lite`) +* `org.hansken.plugin-info.license` +* `org.hansken.plugin-info.author-name` +* `org.hansken.plugin-info.author-organisation` +* `org.hansken.plugin-info.author-email` +* `org.hansken.plugin-info.resource-max_cpu` (in millicpu, optional) +* `org.hansken.plugin-info.resource-max_mem` (in mbs, optional) +* `org.hansken.plugin-info.bulk-mode` (optional, false by default) +* `org.hansken.plugin-info.transformers` (the signatures of the transformer methods as JSON). The transformers field contains a JSON array and is structured as follows: + + ```json + [ + {"method_name": "test_func", "parameters": {"arg_1": "str", "arg_2": "str"}, "return_type": "vector"} + ] + ``` diff --git a/0.9.16/_sources/index.md.txt b/0.9.16/_sources/index.md.txt new file mode 100644 index 0000000..102cfd7 --- /dev/null +++ b/0.9.16/_sources/index.md.txt @@ -0,0 +1,52 @@ +# Hansken extraction plugin SDK documentation for plugin developers + +.. image:: cartoon.png + :width: 500 + +## Quick links + +* [Latest version of this documentation](https://netherlandsforensicinstitute.github.io/hansken-extraction-plugin-sdk-documentation/latest) + +* Python: + [API Changelog](dev/python/api_changelog.md) | + [Code snippets](dev/python/snippets.md) | + [Python Examples](https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples/-/tree/master/python) + +* Java: + [API Changelog](dev/java/api_changelog.md) | + [Code snippets](dev/java/snippets.md) | + [Java Examples](https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples/-/tree/master/java) + +* [Extraction Plugins created by other community members](https://git.eminjenv.nl/hanskaton/extraction-plugins) +* Chat with us on [Discord](https://discord.com/channels/785509947416772649/796720708096360478) + +N.B. For access to any of the above external resources, please see ":ref:`communityaccess`" the in the [FAQ](dev/faq.md). + +## Welcome + +Welcome to the Hansken extraction plugin SDK documentation for plugin developers. +This documentation describes the Hansken extraction plugin Software Development Kit (SDK). +If you are new here, you can start by reading the [introduction](dev/introduction). + +.. ATTENTION:: + Hansken extraction plugins is a technology preview. + Please don't consider the SDK and integration in Hansken to be fully stable. + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + dev/introduction + dev/concepts + dev/spec + dev/java + dev/python + dev/examples + dev/faq + contact + changes + + + +Cartoon by @jorgb, all rights reserved + diff --git a/0.9.16/_static/_sphinx_javascript_frameworks_compat.js b/0.9.16/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 0000000..8141580 --- /dev/null +++ b/0.9.16/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/0.9.16/_static/basic.css b/0.9.16/_static/basic.css new file mode 100644 index 0000000..f316efc --- /dev/null +++ b/0.9.16/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/0.9.16/_static/css/badge_only.css b/0.9.16/_static/css/badge_only.css new file mode 100644 index 0000000..88ba55b --- /dev/null +++ b/0.9.16/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px} \ No newline at end of file diff --git a/0.9.16/_static/css/fonts/Roboto-Slab-Bold.woff b/0.9.16/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 0000000..6cb6000 Binary files /dev/null and b/0.9.16/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/0.9.16/_static/css/fonts/Roboto-Slab-Bold.woff2 b/0.9.16/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 0000000..7059e23 Binary files /dev/null and b/0.9.16/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/0.9.16/_static/css/fonts/Roboto-Slab-Regular.woff b/0.9.16/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 0000000..f815f63 Binary files /dev/null and b/0.9.16/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/0.9.16/_static/css/fonts/Roboto-Slab-Regular.woff2 b/0.9.16/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 0000000..f2c76e5 Binary files /dev/null and b/0.9.16/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/0.9.16/_static/css/fonts/fontawesome-webfont.eot b/0.9.16/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/0.9.16/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/0.9.16/_static/css/fonts/fontawesome-webfont.svg b/0.9.16/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/0.9.16/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/0.9.16/_static/css/fonts/fontawesome-webfont.ttf b/0.9.16/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/0.9.16/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/0.9.16/_static/css/fonts/fontawesome-webfont.woff b/0.9.16/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/0.9.16/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/0.9.16/_static/css/fonts/fontawesome-webfont.woff2 b/0.9.16/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/0.9.16/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/0.9.16/_static/css/fonts/lato-bold-italic.woff b/0.9.16/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 0000000..88ad05b Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-bold-italic.woff differ diff --git a/0.9.16/_static/css/fonts/lato-bold-italic.woff2 b/0.9.16/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 0000000..c4e3d80 Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/0.9.16/_static/css/fonts/lato-bold.woff b/0.9.16/_static/css/fonts/lato-bold.woff new file mode 100644 index 0000000..c6dff51 Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-bold.woff differ diff --git a/0.9.16/_static/css/fonts/lato-bold.woff2 b/0.9.16/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 0000000..bb19504 Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-bold.woff2 differ diff --git a/0.9.16/_static/css/fonts/lato-normal-italic.woff b/0.9.16/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 0000000..76114bc Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-normal-italic.woff differ diff --git a/0.9.16/_static/css/fonts/lato-normal-italic.woff2 b/0.9.16/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 0000000..3404f37 Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/0.9.16/_static/css/fonts/lato-normal.woff b/0.9.16/_static/css/fonts/lato-normal.woff new file mode 100644 index 0000000..ae1307f Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-normal.woff differ diff --git a/0.9.16/_static/css/fonts/lato-normal.woff2 b/0.9.16/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 0000000..3bf9843 Binary files /dev/null and b/0.9.16/_static/css/fonts/lato-normal.woff2 differ diff --git a/0.9.16/_static/css/theme.css b/0.9.16/_static/css/theme.css new file mode 100644 index 0000000..0f14f10 --- /dev/null +++ b/0.9.16/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search .wy-dropdown>aactive,.wy-side-nav-search .wy-dropdown>afocus,.wy-side-nav-search>a:hover,.wy-side-nav-search>aactive,.wy-side-nav-search>afocus{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon,.wy-side-nav-search>a.icon{display:block}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.switch-menus{position:relative;display:block;margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-side-nav-search>div.switch-menus>div.language-switch,.wy-side-nav-search>div.switch-menus>div.version-switch{display:inline-block;padding:.2em}.wy-side-nav-search>div.switch-menus>div.language-switch select,.wy-side-nav-search>div.switch-menus>div.version-switch select{display:inline-block;margin-right:-2rem;padding-right:2rem;max-width:240px;text-align-last:center;background:none;border:none;border-radius:0;box-shadow:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-size:1em;font-weight:400;color:hsla(0,0%,100%,.3);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none}.wy-side-nav-search>div.switch-menus>div.language-switch select:active,.wy-side-nav-search>div.switch-menus>div.language-switch select:focus,.wy-side-nav-search>div.switch-menus>div.language-switch select:hover,.wy-side-nav-search>div.switch-menus>div.version-switch select:active,.wy-side-nav-search>div.switch-menus>div.version-switch select:focus,.wy-side-nav-search>div.switch-menus>div.version-switch select:hover{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.wy-side-nav-search>div.switch-menus>div.language-switch select option,.wy-side-nav-search>div.switch-menus>div.version-switch select option{color:#000}.wy-side-nav-search>div.switch-menus>div.language-switch:has(>select):after,.wy-side-nav-search>div.switch-menus>div.version-switch:has(>select):after{display:inline-block;width:1.5em;height:100%;padding:.1em;content:"\f0d7";font-size:1em;line-height:1.2em;font-family:FontAwesome;text-align:center;pointer-events:none;box-sizing:border-box}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/0.9.16/_static/doctools.js b/0.9.16/_static/doctools.js new file mode 100644 index 0000000..4d67807 --- /dev/null +++ b/0.9.16/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/0.9.16/_static/documentation_options.js b/0.9.16/_static/documentation_options.js new file mode 100644 index 0000000..c83c919 --- /dev/null +++ b/0.9.16/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '0.9.16', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/0.9.16/_static/file.png b/0.9.16/_static/file.png new file mode 100644 index 0000000..a858a41 Binary files /dev/null and b/0.9.16/_static/file.png differ diff --git a/0.9.16/_static/fonts/Lato/lato-bold.eot b/0.9.16/_static/fonts/Lato/lato-bold.eot new file mode 100644 index 0000000..3361183 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bold.eot differ diff --git a/0.9.16/_static/fonts/Lato/lato-bold.ttf b/0.9.16/_static/fonts/Lato/lato-bold.ttf new file mode 100644 index 0000000..29f691d Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bold.ttf differ diff --git a/0.9.16/_static/fonts/Lato/lato-bold.woff b/0.9.16/_static/fonts/Lato/lato-bold.woff new file mode 100644 index 0000000..c6dff51 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bold.woff differ diff --git a/0.9.16/_static/fonts/Lato/lato-bold.woff2 b/0.9.16/_static/fonts/Lato/lato-bold.woff2 new file mode 100644 index 0000000..bb19504 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bold.woff2 differ diff --git a/0.9.16/_static/fonts/Lato/lato-bolditalic.eot b/0.9.16/_static/fonts/Lato/lato-bolditalic.eot new file mode 100644 index 0000000..3d41549 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bolditalic.eot differ diff --git a/0.9.16/_static/fonts/Lato/lato-bolditalic.ttf b/0.9.16/_static/fonts/Lato/lato-bolditalic.ttf new file mode 100644 index 0000000..f402040 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bolditalic.ttf differ diff --git a/0.9.16/_static/fonts/Lato/lato-bolditalic.woff b/0.9.16/_static/fonts/Lato/lato-bolditalic.woff new file mode 100644 index 0000000..88ad05b Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bolditalic.woff differ diff --git a/0.9.16/_static/fonts/Lato/lato-bolditalic.woff2 b/0.9.16/_static/fonts/Lato/lato-bolditalic.woff2 new file mode 100644 index 0000000..c4e3d80 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-bolditalic.woff2 differ diff --git a/0.9.16/_static/fonts/Lato/lato-italic.eot b/0.9.16/_static/fonts/Lato/lato-italic.eot new file mode 100644 index 0000000..3f82642 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-italic.eot differ diff --git a/0.9.16/_static/fonts/Lato/lato-italic.ttf b/0.9.16/_static/fonts/Lato/lato-italic.ttf new file mode 100644 index 0000000..b4bfc9b Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-italic.ttf differ diff --git a/0.9.16/_static/fonts/Lato/lato-italic.woff b/0.9.16/_static/fonts/Lato/lato-italic.woff new file mode 100644 index 0000000..76114bc Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-italic.woff differ diff --git a/0.9.16/_static/fonts/Lato/lato-italic.woff2 b/0.9.16/_static/fonts/Lato/lato-italic.woff2 new file mode 100644 index 0000000..3404f37 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-italic.woff2 differ diff --git a/0.9.16/_static/fonts/Lato/lato-regular.eot b/0.9.16/_static/fonts/Lato/lato-regular.eot new file mode 100644 index 0000000..11e3f2a Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-regular.eot differ diff --git a/0.9.16/_static/fonts/Lato/lato-regular.ttf b/0.9.16/_static/fonts/Lato/lato-regular.ttf new file mode 100644 index 0000000..74decd9 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-regular.ttf differ diff --git a/0.9.16/_static/fonts/Lato/lato-regular.woff b/0.9.16/_static/fonts/Lato/lato-regular.woff new file mode 100644 index 0000000..ae1307f Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-regular.woff differ diff --git a/0.9.16/_static/fonts/Lato/lato-regular.woff2 b/0.9.16/_static/fonts/Lato/lato-regular.woff2 new file mode 100644 index 0000000..3bf9843 Binary files /dev/null and b/0.9.16/_static/fonts/Lato/lato-regular.woff2 differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot new file mode 100644 index 0000000..79dc8ef Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf new file mode 100644 index 0000000..df5d1df Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff new file mode 100644 index 0000000..6cb6000 Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 new file mode 100644 index 0000000..7059e23 Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot new file mode 100644 index 0000000..2f7ca78 Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf new file mode 100644 index 0000000..eb52a79 Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff new file mode 100644 index 0000000..f815f63 Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ diff --git a/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 new file mode 100644 index 0000000..f2c76e5 Binary files /dev/null and b/0.9.16/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ diff --git a/0.9.16/_static/javadoc/allclasses-index.html b/0.9.16/_static/javadoc/allclasses-index.html new file mode 100644 index 0000000..1e3e682 --- /dev/null +++ b/0.9.16/_static/javadoc/allclasses-index.html @@ -0,0 +1,243 @@ + + + + +All Classes and Interfaces (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

All Classes and Interfaces

+
+
+
+
+
+
Class
+
Description
+ +
+
A collection of methods for defensively checking arguments passed to methods.
+
+ +
+
An author of a certain extraction plugin.
+
+ +
+
A builder for an author.
+
+ +
+
This the base class for types of Extraction Plugins, and cannot be used solely as a superclass for a plugin.
+
+ +
+
A BatchSearchResult is a SearchResult implementation that stores all found traces using a single + BatchSearchResult.setTraces(SearchTrace[]) call.
+
+ +
+
The data context contains information about a data stream of a trace that is currently being + processed by an ExtractionPlugin or DeferredExtractionPlugin.
+
+ +
+
A DataRange describes a range of bytes with an offset and length.
+
+ +
+
A data transformation that the Extraction Plugin can write to a Trace using + Trace.setData(String, DataTransformation...).
+
+ +
+
Writes data to an OutputStream.
+
+ +
+
Deferred extraction plugins can be used by Hansken to process traces during the extraction process.
+
+ +
+
Deferred meta extraction plugins can be used by Hansken to process traces during the extraction process.
+
+ +
+
Extraction plugins can be used by Hansken to process traces during the extraction process.
+
+ +
+
A trace contains information about processed data.
+
+ +
+
A geographical location consisting of a latitude and a longitude.
+
+ +
+
Indicates what stage of maturity a certain extraction plugin is in.
+
+ +
+
Meta extraction plugins can be used by Hansken to process traces during the extraction process.
+
+ +
+
Identifier of a plugin, consisting of domain, category and name.
+
+ +
+
Information about an extraction plugin, such as the author or + a human-readable description.
+
+ +
+
A builder for plugin information.
+
+ +
+
PluginResources contains information about how many resources will be used for a plugin.
+
+ +
+
Builder for PluginResources.
+
+ +
+
The type of plugin, which describes its function.
+
+ +
+
A random access readable byte sequence.
+
+ +
+
A RangedDataTransformation describes a data transformation consisting of a list of DataRanges.
+
+ +
+
Builder for creating RangedDataTransformation using a syntax that is sometimes shorter than using + constructors.
+
+ +
+
Represents search options including the search scope, the start offset of the results, and sorting preferences.
+
+ +
+
Builder for creating SearchOptions instances.
+
+ +
+
A SearchResult represents the result of a TraceSearcher.search(String, int).
+
+ +
+
Scope options for scoping a search to an image or project level.
+
+ +
+
Represents a sort option used in searches, including the field to sort by and the direction.
+
+ +
+
Builder for creating SearchSortOption instances.
+
+ +
+
The sort direction.
+
+ +
+
A trace contains information about processed data.
+
+ +
+
Represents an operation that accepts a single input argument and returns no result.
+
+ +
+
A trace contains information about processed data.
+
+ +
+
a Tracelet represents tracedata that can be present multiple times within a trace.
+
+ +
 
+ +
+
a TraceletProperty is a property of a Tracelet.
+
+ +
+
Allows searching for traces within the scope of the process function.
+
+ +
+
An argument or return value that can be passed to or returned from a Transformer.
+
+ +
+
Description of a transform method of a plugin.
+
+ +
+
An opaque vector of floating point values.
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/allpackages-index.html b/0.9.16/_static/javadoc/allpackages-index.html new file mode 100644 index 0000000..00b1d7e --- /dev/null +++ b/0.9.16/_static/javadoc/allpackages-index.html @@ -0,0 +1,80 @@ + + + + +All Packages (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

All Packages

+
+
Package Summary
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+ +
+
This package contains the Data Transformations.
+
+ +
+
This package provides util classes for the Extraction Plugin SDK API.
+
+
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/constant-values.html b/0.9.16/_static/javadoc/constant-values.html new file mode 100644 index 0000000..fa28beb --- /dev/null +++ b/0.9.16/_static/javadoc/constant-values.html @@ -0,0 +1,85 @@ + + + + +Constant Field Values (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Constant Field Values

+
+
+

Contents

+ +
+
+

org.hansken.*

+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/copy.svg b/0.9.16/_static/javadoc/copy.svg new file mode 100644 index 0000000..7c46ab1 --- /dev/null +++ b/0.9.16/_static/javadoc/copy.svg @@ -0,0 +1,33 @@ + + + + + + + + diff --git a/0.9.16/_static/javadoc/deprecated-list.html b/0.9.16/_static/javadoc/deprecated-list.html new file mode 100644 index 0000000..c0a3355 --- /dev/null +++ b/0.9.16/_static/javadoc/deprecated-list.html @@ -0,0 +1,104 @@ + + + + +Deprecated List (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Deprecated API

+
+

Contents

+ + + +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/element-list b/0.9.16/_static/javadoc/element-list new file mode 100644 index 0000000..ef008a6 --- /dev/null +++ b/0.9.16/_static/javadoc/element-list @@ -0,0 +1,3 @@ +org.hansken.plugin.extraction.api +org.hansken.plugin.extraction.api.transformations +org.hansken.plugin.extraction.util diff --git a/0.9.16/_static/javadoc/help-doc.html b/0.9.16/_static/javadoc/help-doc.html new file mode 100644 index 0000000..bc1fcf9 --- /dev/null +++ b/0.9.16/_static/javadoc/help-doc.html @@ -0,0 +1,204 @@ + + + + +API Help (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+

JavaDoc Help

+ +
+
+

Navigation

+Starting from the Overview page, you can browse the documentation using the links in each page, and in the navigation bar at the top of each page. The Index and Search box allow you to navigate to specific declarations and summary pages, including: All Packages, All Classes and Interfaces + +
+
+
+

Kinds of Pages

+The following sections describe the different kinds of pages in this collection. +
+

Overview

+

The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.

+
+
+

Package

+

Each package has a page that contains a list of its classes and interfaces, with a summary for each. These pages may contain the following categories:

+
    +
  • Interfaces
  • +
  • Classes
  • +
  • Enum Classes
  • +
  • Exception Classes
  • +
  • Annotation Interfaces
  • +
+
+
+

Class or Interface

+

Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a declaration and description, member summary tables, and detailed member descriptions. Entries in each of these sections are omitted if they are empty or not applicable.

+
    +
  • Class Inheritance Diagram
  • +
  • Direct Subclasses
  • +
  • All Known Subinterfaces
  • +
  • All Known Implementing Classes
  • +
  • Class or Interface Declaration
  • +
  • Class or Interface Description
  • +
+
+
    +
  • Nested Class Summary
  • +
  • Enum Constant Summary
  • +
  • Field Summary
  • +
  • Property Summary
  • +
  • Constructor Summary
  • +
  • Method Summary
  • +
  • Required Element Summary
  • +
  • Optional Element Summary
  • +
+
+
    +
  • Enum Constant Details
  • +
  • Field Details
  • +
  • Property Details
  • +
  • Constructor Details
  • +
  • Method Details
  • +
  • Element Details
  • +
+

Note: Annotation interfaces have required and optional elements, but not methods. Only enum classes have enum constants. The components of a record class are displayed as part of the declaration of the record class. Properties are a feature of JavaFX.

+

The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

+
+
+

Other Files

+

Packages and modules may contain pages with additional information related to the declarations nearby.

+
+
+

Use

+

Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the USE link in the navigation bar.

+
+
+

Tree (Class Hierarchy)

+

There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. Classes are organized by inheritance structure starting with java.lang.Object. Interfaces do not inherit from java.lang.Object.

+
    +
  • When viewing the Overview page, clicking on TREE displays the hierarchy for all packages.
  • +
  • When viewing a particular package, class or interface page, clicking on TREE displays the hierarchy for only that package.
  • +
+
+
+

Deprecated API

+

The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to shortcomings, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

+
+
+

Constant Field Values

+

The Constant Field Values page lists the static final fields and their values.

+
+
+

All Packages

+

The All Packages page contains an alphabetic index of all packages contained in the documentation.

+
+
+

All Classes and Interfaces

+

The All Classes and Interfaces page contains an alphabetic index of all classes and interfaces contained in the documentation, including annotation interfaces, enum classes, and record classes.

+
+
+

Index

+

The Index contains an alphabetic index of all classes, interfaces, constructors, methods, and fields in the documentation, as well as summary pages such as All Packages, All Classes and Interfaces.

+
+
+
+This help file applies to API documentation generated by the standard doclet.
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/index-all.html b/0.9.16/_static/javadoc/index-all.html new file mode 100644 index 0000000..214c23d --- /dev/null +++ b/0.9.16/_static/javadoc/index-all.html @@ -0,0 +1,1050 @@ + + + + +Index (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Index

+
+A B C D E F G H I L M N O P R S T V W 
All Classes and Interfaces|All Packages|Constant Field Values +

A

+
+
accept(T) - Method in interface org.hansken.plugin.extraction.util.ThrowingConsumer
+
+
Performs this operation on the given argument.
+
+
add(List<DataRange>) - Method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder
+
 
+
add(DataRange...) - Method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder
+
 
+
addRange(long, long) - Method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder
+
 
+
addTracelet(String, Consumer<Trace.TraceletBuilder>) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Add a tracelet to the trace.
+
+
addTracelet(Trace.Tracelet) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Deprecated. +
use addTracelet(type, callback)
+
+
+
addType(String) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Add a type to this trace (for example: "file").
+
+
addValue(String, T) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Adds a value to a property that's a List.
+
+
ALL_SEARCH_RESULTS - Static variable in interface org.hansken.plugin.extraction.api.TraceSearcher
+
 
+
ArgChecks - Class in org.hansken.plugin.extraction.util
+
+
A collection of methods for defensively checking arguments passed to methods.
+
+
argNotAllNull(String, Object...) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that not all values with given name are null, otherwise throw an exception.
+
+
argNotEmpty(String, String) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the string with given name is not null or empty, otherwise throw an exception.
+
+
argNotEmpty(String, Collection<T>) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the collection value with given name is not empty, otherwise throw an exception.
+
+
argNotEmpty(String, T[]) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the array value with given name is not empty, otherwise throw an exception.
+
+
argNotNegative(String, float) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the float with given name is not negative, otherwise throw an exception.
+
+
argNotNegative(String, int) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the int with given name is not negative, otherwise throw an exception.
+
+
argNotNegative(String, long) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the long with given name is not negative, otherwise throw an exception.
+
+
argNotNull(String, T) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the value with given name is not null, otherwise throw an exception.
+
+
argsIsType(String, List<T>, Class<?>) - Static method in class org.hansken.plugin.extraction.util.ArgChecks
+
+
Check that the value with given name is of type type, otherwise throw an exception.
+
+
asBinary() - Method in class org.hansken.plugin.extraction.api.Vector
+
+
Returns the binary representation of the Vector.
+
+
ASCENDING - Enum constant in enum class org.hansken.plugin.extraction.api.SearchSortOption.Direction
+
+
Sort results in ascending order.
+
+
asVector(byte[]) - Static method in class org.hansken.plugin.extraction.api.Vector
+
+
Creates a vector from a binary representation.
+
+
author() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the author of this plugin.
+
+
author(Author) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the author.
+
+
Author - Class in org.hansken.plugin.extraction.api
+
+
An author of a certain extraction plugin.
+
+
Author.Builder - Class in org.hansken.plugin.extraction.api
+
+
A builder for an author.
+
+
+

B

+
+
BaseExtractionPlugin - Interface in org.hansken.plugin.extraction.api
+
+
This the base class for types of Extraction Plugins, and cannot be used solely as a superclass for a plugin.
+
+
BatchSearchResult - Class in org.hansken.plugin.extraction.api
+
+
A BatchSearchResult is a SearchResult implementation that stores all found traces using a single + BatchSearchResult.setTraces(SearchTrace[]) call.
+
+
BatchSearchResult(long) - Constructor for class org.hansken.plugin.extraction.api.BatchSearchResult
+
 
+
build() - Method in class org.hansken.plugin.extraction.api.Author.Builder
+
+
Create the author from the properties set on this builder.
+
+
build() - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Create the plugin information from the properties set on this builder.
+
+
build() - Method in class org.hansken.plugin.extraction.api.PluginResources.Builder
+
 
+
build() - Method in class org.hansken.plugin.extraction.api.SearchOptions.Builder
+
+
Builds a new SearchOptions instance with the configured values.
+
+
build() - Method in class org.hansken.plugin.extraction.api.SearchSortOption.Builder
+
+
Builds a new SearchSortOption instance with the configured values.
+
+
build() - Method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder
+
 
+
builder() - Static method in class org.hansken.plugin.extraction.api.Author
+
+
Start creating a new author.
+
+
builder() - Static method in class org.hansken.plugin.extraction.api.PluginResources
+
 
+
builder() - Static method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Creates a new SearchOptions.Builder instance for constructing a SearchOptions object.
+
+
builder() - Static method in record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Creates a new SearchSortOption.Builder instance for constructing a SearchSortOption.
+
+
builder() - Static method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation
+
+ +
+
Builder() - Constructor for class org.hansken.plugin.extraction.api.Author.Builder
+
 
+
Builder() - Constructor for class org.hansken.plugin.extraction.api.SearchOptions.Builder
+
 
+
Builder() - Constructor for class org.hansken.plugin.extraction.api.SearchSortOption.Builder
+
 
+
Builder() - Constructor for class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder
+
 
+
builderFor(BaseExtractionPlugin) - Static method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Start creating new plugin information for the given plugin.
+
+
builderFor(PluginType) - Static method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Start creating new plugin information for a plugin of given type.
+
+
+

C

+
+
category() - Method in class org.hansken.plugin.extraction.api.PluginId
+
 
+
+

D

+
+
data() - Method in interface org.hansken.plugin.extraction.api.DataContext
+
+
A data sequence belonging to the trace currently being extracted.
+
+
DataContext - Interface in org.hansken.plugin.extraction.api
+
+
The data context contains information about a data stream of a trace that is currently being + processed by an ExtractionPlugin or DeferredExtractionPlugin.
+
+
DataRange - Class in org.hansken.plugin.extraction.api.transformations
+
+
A DataRange describes a range of bytes with an offset and length.
+
+
DataRange(long, long) - Constructor for class org.hansken.plugin.extraction.api.transformations.DataRange
+
+
Creates a DataRange which describes a range of bytes.
+
+
DataTransformation - Interface in org.hansken.plugin.extraction.api.transformations
+
+
A data transformation that the Extraction Plugin can write to a Trace using + Trace.setData(String, DataTransformation...).
+
+
dataType() - Method in interface org.hansken.plugin.extraction.api.DataContext
+
+
The type of data (see DataContext.data()) that is being processed.
+
+
DataWriter - Interface in org.hansken.plugin.extraction.api
+
+
Writes data to an OutputStream.
+
+
DEFAULT - Static variable in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
A default SearchOptions instance with.
+
+
DEFERRED_EXTRACTION_PLUGIN - Enum constant in enum class org.hansken.plugin.extraction.api.PluginType
+
+ +
+
DEFERRED_META_EXTRACTION_PLUGIN - Enum constant in enum class org.hansken.plugin.extraction.api.PluginType
+
+ +
+
DeferredExtractionPlugin - Interface in org.hansken.plugin.extraction.api
+
+
Deferred extraction plugins can be used by Hansken to process traces during the extraction process.
+
+
deferredIterations() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the number of extraction iterations before the deferred plugin can be applied on traces.
+
+
deferredIterations(int) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the number of extraction iterations needed for this deferred plugin.
+
+
DeferredMetaExtractionPlugin - Class in org.hansken.plugin.extraction.api
+
+
Deferred meta extraction plugins can be used by Hansken to process traces during the extraction process.
+
+
DeferredMetaExtractionPlugin() - Constructor for class org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin
+
 
+
DESCENDING - Enum constant in enum class org.hansken.plugin.extraction.api.SearchSortOption.Direction
+
+
Sort results in descending order.
+
+
description() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get a human readable description of this plugin.
+
+
description(String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the description.
+
+
direction() - Method in record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Returns the value of the direction record component.
+
+
direction(SearchSortOption.Direction) - Method in class org.hansken.plugin.extraction.api.SearchSortOption.Builder
+
+
Sets the sort direction.
+
+
domain() - Method in class org.hansken.plugin.extraction.api.PluginId
+
 
+
+

E

+
+
email() - Method in class org.hansken.plugin.extraction.api.Author
+
+
Get the email address of the author.
+
+
email(String) - Method in class org.hansken.plugin.extraction.api.Author.Builder
+
+
Set the email.
+
+
enableBulkMode() - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set bulk mode (optional).
+
+
equals(Object) - Method in class org.hansken.plugin.extraction.api.LatLong
+
 
+
equals(Object) - Method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Indicates whether some other object is "equal to" this one.
+
+
equals(Object) - Method in record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Indicates whether some other object is "equal to" this one.
+
+
equals(Object) - Method in class org.hansken.plugin.extraction.api.Vector
+
 
+
EXTRACTION_PLUGIN - Enum constant in enum class org.hansken.plugin.extraction.api.PluginType
+
+ +
+
ExtractionPlugin - Interface in org.hansken.plugin.extraction.api
+
+
Extraction plugins can be used by Hansken to process traces during the extraction process.
+
+
+

F

+
+
field() - Method in record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Returns the value of the field record component.
+
+
field(String) - Method in class org.hansken.plugin.extraction.api.SearchSortOption.Builder
+
+
Sets the field to sort by.
+
+
fullName() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the full name of this plugin, based on the id.
+
+
+

G

+
+
get(String) - Method in interface org.hansken.plugin.extraction.api.ImmutableTrace
+
+
Get the value of the property with given name on this trace.
+
+
get(String) - Method in interface org.hansken.plugin.extraction.api.Trace.TraceletBuilder
+
+
Returns the currently set value (if any) for the requested property.
+
+
getArgument() - Method in class org.hansken.plugin.extraction.api.TransformerArgument
+
+
Retrieves the Transformer argument as an Object.
+
+
getData(String) - Method in interface org.hansken.plugin.extraction.api.SearchTrace
+
+
Returns a RandomAccessData for a specific trace data type.
+
+
getDataTypes() - Method in interface org.hansken.plugin.extraction.api.SearchTrace
+
+
Returns all available data types for this search trace.
+
+
getLength() - Method in class org.hansken.plugin.extraction.api.transformations.DataRange
+
 
+
getMethodName() - Method in class org.hansken.plugin.extraction.api.TransformerLabel
+
+
Retrieves the method name of the transformer.
+
+
getName() - Method in class org.hansken.plugin.extraction.api.Trace.Tracelet
+
 
+
getName() - Method in class org.hansken.plugin.extraction.api.Trace.TraceletProperty
+
 
+
getNewTracelets() - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Retrieve the tracelets that were added by the plugin.
+
+
getOffset() - Method in class org.hansken.plugin.extraction.api.transformations.DataRange
+
 
+
getParameters() - Method in class org.hansken.plugin.extraction.api.TransformerLabel
+
+
Retrieves the parameters of the transformer method as a name, type mapping.
+
+
getRanges() - Method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation
+
 
+
getReturnType() - Method in class org.hansken.plugin.extraction.api.TransformerLabel
+
+
Retrieves the return type of the transformer method.
+
+
getTotalHits() - Method in class org.hansken.plugin.extraction.api.BatchSearchResult
+
 
+
getTotalHits() - Method in interface org.hansken.plugin.extraction.api.SearchResult
+
+
Returns the total number of traces matching the query.
+
+
getTraces() - Method in class org.hansken.plugin.extraction.api.BatchSearchResult
+
 
+
getTraces() - Method in interface org.hansken.plugin.extraction.api.SearchResult
+
+
Returns all found traces.
+
+
getType() - Method in interface org.hansken.plugin.extraction.api.Trace.TraceletBuilder
+
+
Returns the type of this tracelet.
+
+
getValue() - Method in class org.hansken.plugin.extraction.api.Trace.Tracelet
+
 
+
getValue() - Method in class org.hansken.plugin.extraction.api.Trace.TraceletProperty
+
 
+
+

H

+
+
hashCode() - Method in class org.hansken.plugin.extraction.api.LatLong
+
 
+
hashCode() - Method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Returns a hash code value for this object.
+
+
hashCode() - Method in record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Returns a hash code value for this object.
+
+
hashCode() - Method in class org.hansken.plugin.extraction.api.Vector
+
 
+
hqlMatcher() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the hqlMatcher of this plugin in string format.
+
+
hqlMatcher(String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the hqlMatcher query in string format.
+
+
+

I

+
+
id() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the the unique id of this plugin, consisting of domain, category and name.
+
+
id(String, String, String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the unique id of this plugin, consisting of domain, category and name.
+
+
id(PluginId) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the unique id of this plugin, consisting of domain, category and name.
+
+
IMAGE - Enum constant in enum class org.hansken.plugin.extraction.api.SearchScope
+
+
Searches will be limited to the traces in the same image that is being extracted.
+
+
ImmutableTrace - Interface in org.hansken.plugin.extraction.api
+
+
A trace contains information about processed data.
+
+
isBulkModeEnabled() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Check if this plugin should be run with bulk mode enabled.
+
+
+

L

+
+
latitude() - Method in class org.hansken.plugin.extraction.api.LatLong
+
+
The north-south position of a point on earth.
+
+
LatLong - Class in org.hansken.plugin.extraction.api
+
+
A geographical location consisting of a latitude and a longitude.
+
+
LatLong(double, double) - Constructor for class org.hansken.plugin.extraction.api.LatLong
+
 
+
license() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the name of the license of this plugin.
+
+
license(String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the name of the license of this plugin.
+
+
longitude() - Method in class org.hansken.plugin.extraction.api.LatLong
+
+
The east-west position of a point on earth.
+
+
+

M

+
+
maturityLevel() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the maturity level of this plugin.
+
+
maturityLevel(MaturityLevel) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+ +
+
MaturityLevel - Enum Class in org.hansken.plugin.extraction.api
+
+
Indicates what stage of maturity a certain extraction plugin is in.
+
+
maximumCpu() - Method in class org.hansken.plugin.extraction.api.PluginResources
+
 
+
maximumCpu(float) - Method in class org.hansken.plugin.extraction.api.PluginResources.Builder
+
 
+
maximumMemory() - Method in class org.hansken.plugin.extraction.api.PluginResources
+
 
+
maximumMemory(int) - Method in class org.hansken.plugin.extraction.api.PluginResources.Builder
+
 
+
maximumWorkers() - Method in class org.hansken.plugin.extraction.api.PluginResources
+
 
+
maximumWorkers(int) - Method in class org.hansken.plugin.extraction.api.PluginResources.Builder
+
 
+
META_EXTRACTION_PLUGIN - Enum constant in enum class org.hansken.plugin.extraction.api.PluginType
+
+ +
+
MetaExtractionPlugin - Class in org.hansken.plugin.extraction.api
+
+
Meta extraction plugins can be used by Hansken to process traces during the extraction process.
+
+
MetaExtractionPlugin() - Constructor for class org.hansken.plugin.extraction.api.MetaExtractionPlugin
+
 
+
+

N

+
+
name() - Method in class org.hansken.plugin.extraction.api.Author
+
+
Get the name of the author.
+
+
name() - Method in class org.hansken.plugin.extraction.api.PluginId
+
 
+
name() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Deprecated. +
Use PluginInfo.id() instead.
+
+
+
name(String) - Method in class org.hansken.plugin.extraction.api.Author.Builder
+
+
Set the name.
+
+
name(String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Deprecated. + +
+
+
newChild(String, ThrowingConsumer<Trace, IOException>) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Create and store new child trace of this trace.
+
+
+

O

+
+
of(double, double) - Static method in class org.hansken.plugin.extraction.api.LatLong
+
+
Create a new geographical point with given latitude + and longitude.
+
+
of(float...) - Static method in class org.hansken.plugin.extraction.api.Vector
+
+
Creates a Vector from an array of floating point values.
+
+
of(String) - Static method in class org.hansken.plugin.extraction.api.LatLong
+
 
+
of(Collection<Float>) - Static method in class org.hansken.plugin.extraction.api.Vector
+
+
Creates a Vector from a collection of numbers.
+
+
ofBase64(String) - Static method in class org.hansken.plugin.extraction.api.Vector
+
+
Creates a Vector from a base64 encoded string.
+
+
offset(int) - Method in class org.hansken.plugin.extraction.api.SearchOptions.Builder
+
+
Sets the starting offset for the search results.
+
+
org.hansken.plugin.extraction.api - package org.hansken.plugin.extraction.api
+
+
This is the API of the Extraction Plugins SDK.
+
+
org.hansken.plugin.extraction.api.transformations - package org.hansken.plugin.extraction.api.transformations
+
+
This package contains the Data Transformations.
+
+
org.hansken.plugin.extraction.util - package org.hansken.plugin.extraction.util
+
+
This package provides util classes for the Extraction Plugin SDK API.
+
+
organisation() - Method in class org.hansken.plugin.extraction.api.Author
+
+
Get the name of the organisation the author belongs to.
+
+
organisation(String) - Method in class org.hansken.plugin.extraction.api.Author.Builder
+
+
Set the organisation.
+
+
+

P

+
+
PluginId - Class in org.hansken.plugin.extraction.api
+
+
Identifier of a plugin, consisting of domain, category and name.
+
+
PluginId(String, String, String) - Constructor for class org.hansken.plugin.extraction.api.PluginId
+
+
Create a unique identifier for a plugin, consisting of domain, category and name.
+
+
pluginInfo() - Method in interface org.hansken.plugin.extraction.api.BaseExtractionPlugin
+
+
Get the information of this plugin, such as the author or a description, and the + types of traces and data it matches on.
+
+
PluginInfo - Class in org.hansken.plugin.extraction.api
+
+
Information about an extraction plugin, such as the author or + a human-readable description.
+
+
PluginInfo.Builder - Class in org.hansken.plugin.extraction.api
+
+
A builder for plugin information.
+
+
PluginResources - Class in org.hansken.plugin.extraction.api
+
+
PluginResources contains information about how many resources will be used for a plugin.
+
+
PluginResources.Builder - Class in org.hansken.plugin.extraction.api
+
+
Builder for PluginResources.
+
+
pluginType() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the type of this plugin.
+
+
PluginType - Enum Class in org.hansken.plugin.extraction.api
+
+
The type of plugin, which describes its function.
+
+
pluginVersion() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the version of this plugin.
+
+
pluginVersion(String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+ +
+
position() - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Get the position in the sequence.
+
+
process(Trace) - Method in class org.hansken.plugin.extraction.api.MetaExtractionPlugin
+
+
Start processing a trace without any of its associated data streams.
+
+
process(Trace, DataContext) - Method in interface org.hansken.plugin.extraction.api.ExtractionPlugin
+
+
Start processing a trace with a given data context.
+
+
process(Trace, DataContext) - Method in class org.hansken.plugin.extraction.api.MetaExtractionPlugin
+
 
+
process(Trace, DataContext, TraceSearcher) - Method in interface org.hansken.plugin.extraction.api.DeferredExtractionPlugin
+
+
Start processing a trace.
+
+
process(Trace, DataContext, TraceSearcher) - Method in class org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin
+
 
+
process(Trace, TraceSearcher) - Method in class org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin
+
+
Start processing a trace.
+
+
PRODUCTION_READY - Enum constant in enum class org.hansken.plugin.extraction.api.MaturityLevel
+
+
The plugin is ready to be used in a production environment.
+
+
PROJECT - Enum constant in enum class org.hansken.plugin.extraction.api.SearchScope
+
+
Searches will be limited to the traces in the same project that is being extracted.
+
+
PROOF_OF_CONCEPT - Enum constant in enum class org.hansken.plugin.extraction.api.MaturityLevel
+
+
The plugin is in a proof of concept phase, not yet ready for test or production.
+
+
properties() - Method in interface org.hansken.plugin.extraction.api.ImmutableTrace
+
+
Return the names of all the properties contained in this trace.
+
+
+

R

+
+
RandomAccessData - Interface in org.hansken.plugin.extraction.api
+
+
A random access readable byte sequence.
+
+
RangedDataTransformation - Class in org.hansken.plugin.extraction.api.transformations
+
+
A RangedDataTransformation describes a data transformation consisting of a list of DataRanges.
+
+
RangedDataTransformation(List<DataRange>) - Constructor for class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation
+
+
Create a new RangedDataTransformation given a list of DataRanges.
+
+
RangedDataTransformation(DataRange...) - Constructor for class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation
+
+
Create a new RangedDataTransformation given one or more DataRanges.
+
+
RangedDataTransformation.Builder - Class in org.hansken.plugin.extraction.api.transformations
+
+
Builder for creating RangedDataTransformation using a syntax that is sometimes shorter than using + constructors.
+
+
read(byte[]) - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Read bytes into the given buffer, starting at position 0 in the buffer.
+
+
read(byte[], int) - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Read bytes into the given buffer, starting at position 0 in the buffer.
+
+
read(byte[], int, int) - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Read data into the given buffer, starting at position offset in the buffer.
+
+
readNBytes(int) - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Read from the data sequence, returning the read bytes as an array.The data will be read from the current + position and the amount of bytes read will equal count, unless the sequence contains + fewer remaining bytes.
+
+
READY_FOR_TEST - Enum constant in enum class org.hansken.plugin.extraction.api.MaturityLevel
+
+
The plugin can be used in a test environment and is expected to be fully functional.
+
+
remaining() - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Get the number of remaining bytes in this data sequence.
+
+
resources() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the resources of this plugin.
+
+
resources(PluginResources) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the resources of this plugin (optional).
+
+
+

S

+
+
scope() - Method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Returns the value of the scope record component.
+
+
scope(SearchScope) - Method in class org.hansken.plugin.extraction.api.SearchOptions.Builder
+
+
Sets the search scope.
+
+
search(String) - Method in interface org.hansken.plugin.extraction.api.TraceSearcher
+
+
Searches in Hansken for Traces matching provided query, scoped to the image under extraction.
+
+
search(String, int) - Method in interface org.hansken.plugin.extraction.api.TraceSearcher
+
+
Searches in Hansken for Traces matching provided query, scoped to the image under extraction.
+
+
search(String, int, SearchOptions) - Method in interface org.hansken.plugin.extraction.api.TraceSearcher
+
+
Searches in Hansken for Traces matching provided query.
+
+
search(String, int, SearchScope, int, List<SearchSortOption>) - Method in interface org.hansken.plugin.extraction.api.TraceSearcher
+
+
Searches in Hansken for Traces matching provided query.
+
+
search(String, SearchOptions) - Method in interface org.hansken.plugin.extraction.api.TraceSearcher
+
+
Searches in Hansken for Traces matching provided query.
+
+
SearchOptions - Record Class in org.hansken.plugin.extraction.api
+
+
Represents search options including the search scope, the start offset of the results, and sorting preferences.
+
+
SearchOptions(SearchScope, int, List<SearchSortOption>) - Constructor for record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Creates an instance of a SearchOptions record class.
+
+
SearchOptions.Builder - Class in org.hansken.plugin.extraction.api
+
+
Builder for creating SearchOptions instances.
+
+
SearchResult - Interface in org.hansken.plugin.extraction.api
+
+
A SearchResult represents the result of a TraceSearcher.search(String, int).
+
+
SearchScope - Enum Class in org.hansken.plugin.extraction.api
+
+
Scope options for scoping a search to an image or project level.
+
+
SearchSortOption - Record Class in org.hansken.plugin.extraction.api
+
+
Represents a sort option used in searches, including the field to sort by and the direction.
+
+
SearchSortOption(String, SearchSortOption.Direction) - Constructor for record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Creates an instance of a SearchSortOption record class.
+
+
SearchSortOption.Builder - Class in org.hansken.plugin.extraction.api
+
+
Builder for creating SearchSortOption instances.
+
+
SearchSortOption.Direction - Enum Class in org.hansken.plugin.extraction.api
+
+
The sort direction.
+
+
SearchTrace - Interface in org.hansken.plugin.extraction.api
+
+
A trace contains information about processed data.
+
+
seek(long) - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Move to the given absolute position in the data sequence.
+
+
set(String, Object) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Set a property on this trace with a given value.
+
+
set(String, Object) - Method in interface org.hansken.plugin.extraction.api.Trace.TraceletBuilder
+
+
Set a property on this tracelet with a given value.
+
+
setData(String, InputStream) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Add a data stream of a given type to this Trace (for example, 'raw' or 'html').
+
+
setData(String, List<DataTransformation>) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Set a series of data transformations for a specific dataType.
+
+
setData(String, DataWriter) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Add a data stream of a given type to this Trace (for example, 'raw' or 'html').
+
+
setData(String, DataTransformation...) - Method in interface org.hansken.plugin.extraction.api.Trace
+
+
Set a series of data transformations for a specific dataType.
+
+
setLength(long) - Method in class org.hansken.plugin.extraction.api.transformations.DataRange
+
 
+
setOffset(long) - Method in class org.hansken.plugin.extraction.api.transformations.DataRange
+
 
+
setRanges(List<DataRange>) - Method in class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation
+
 
+
setTraces(SearchTrace[]) - Method in class org.hansken.plugin.extraction.api.BatchSearchResult
+
+
Sets all traces that can be returned by calling getTraces.
+
+
size() - Method in interface org.hansken.plugin.extraction.api.RandomAccessData
+
+
Get the number of bytes contained in this data sequence.
+
+
size() - Method in class org.hansken.plugin.extraction.api.Vector
+
+
Returns the number of dimensions of the vector.
+
+
sort() - Method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Returns the value of the sort record component.
+
+
sort(List<SearchSortOption>) - Method in class org.hansken.plugin.extraction.api.SearchOptions.Builder
+
+
Sets the sort options for the search results.
+
+
start() - Method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Returns the value of the start record component.
+
+
+

T

+
+
ThrowingConsumer<T,E> - Interface in org.hansken.plugin.extraction.util
+
+
Represents an operation that accepts a single input argument and returns no result.
+
+
toBase64() - Method in class org.hansken.plugin.extraction.api.Vector
+
+
Returns a base64 encoded string of the Vector.
+
+
toISO6709() - Method in class org.hansken.plugin.extraction.api.LatLong
+
+
Format to String using ISO 6709.
+
+
toString() - Method in class org.hansken.plugin.extraction.api.LatLong
+
 
+
toString() - Method in class org.hansken.plugin.extraction.api.PluginId
+
 
+
toString() - Method in record class org.hansken.plugin.extraction.api.SearchOptions
+
+
Returns a string representation of this record class.
+
+
toString() - Method in record class org.hansken.plugin.extraction.api.SearchSortOption
+
+
Returns a string representation of this record class.
+
+
toString() - Method in class org.hansken.plugin.extraction.api.Vector
+
 
+
Trace - Interface in org.hansken.plugin.extraction.api
+
+
A trace contains information about processed data.
+
+
Trace.Tracelet - Class in org.hansken.plugin.extraction.api
+
+
a Tracelet represents tracedata that can be present multiple times within a trace.
+
+
Trace.TraceletBuilder - Interface in org.hansken.plugin.extraction.api
+
 
+
Trace.TraceletProperty - Class in org.hansken.plugin.extraction.api
+
+
a TraceletProperty is a property of a Tracelet.
+
+
traceId() - Method in interface org.hansken.plugin.extraction.api.ImmutableTrace
+
+
Get the trace id of this trace.
+
+
Tracelet(String, List<Trace.TraceletProperty>) - Constructor for class org.hansken.plugin.extraction.api.Trace.Tracelet
+
 
+
TraceletProperty(String, Object) - Constructor for class org.hansken.plugin.extraction.api.Trace.TraceletProperty
+
 
+
TraceSearcher - Interface in org.hansken.plugin.extraction.api
+
+
Allows searching for traces within the scope of the process function.
+
+
transformer(List<TransformerLabel>) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the transformers of this plugin (optional).
+
+
TransformerArgument - Class in org.hansken.plugin.extraction.api
+
+
An argument or return value that can be passed to or returned from a Transformer.
+
+
TransformerArgument(Object) - Constructor for class org.hansken.plugin.extraction.api.TransformerArgument
+
+
Takes an Object and validates if it is of an acceptable transformer argument or return type.
+
+
TransformerLabel - Class in org.hansken.plugin.extraction.api
+
+
Description of a transform method of a plugin.
+
+
TransformerLabel(String, Map<String, String>, String) - Constructor for class org.hansken.plugin.extraction.api.TransformerLabel
+
+
Plain constructor that constructs a TransformerLabel.
+
+
transformers() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get a list of possible transform methods this plugin provides.
+
+
types() - Method in interface org.hansken.plugin.extraction.api.ImmutableTrace
+
+
Get all the types of this trace.
+
+
+

V

+
+
valueOf(String) - Static method in enum class org.hansken.plugin.extraction.api.MaturityLevel
+
+
Returns the enum constant of this class with the specified name.
+
+
valueOf(String) - Static method in enum class org.hansken.plugin.extraction.api.PluginType
+
+
Returns the enum constant of this class with the specified name.
+
+
valueOf(String) - Static method in enum class org.hansken.plugin.extraction.api.SearchScope
+
+
Returns the enum constant of this class with the specified name.
+
+
valueOf(String) - Static method in enum class org.hansken.plugin.extraction.api.SearchSortOption.Direction
+
+
Returns the enum constant of this class with the specified name.
+
+
values() - Static method in enum class org.hansken.plugin.extraction.api.MaturityLevel
+
+
Returns an array containing the constants of this enum class, in +the order they are declared.
+
+
values() - Static method in enum class org.hansken.plugin.extraction.api.PluginType
+
+
Returns an array containing the constants of this enum class, in +the order they are declared.
+
+
values() - Static method in enum class org.hansken.plugin.extraction.api.SearchScope
+
+
Returns an array containing the constants of this enum class, in +the order they are declared.
+
+
values() - Static method in enum class org.hansken.plugin.extraction.api.SearchSortOption.Direction
+
+
Returns an array containing the constants of this enum class, in +the order they are declared.
+
+
values() - Method in class org.hansken.plugin.extraction.api.Vector
+
+
Returns the values of the Vector as an array of floats.
+
+
Vector - Class in org.hansken.plugin.extraction.api
+
+
An opaque vector of floating point values.
+
+
+

W

+
+
webpageUrl() - Method in class org.hansken.plugin.extraction.api.PluginInfo
+
+
Get the url of this plugin, could point to git repo or webpage that explains the plugin.
+
+
webpageUrl(String) - Method in class org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
Set the url to a webpage that belongs to this plugin.
+
+
writeTo(OutputStream) - Method in interface org.hansken.plugin.extraction.api.DataWriter
+
+
Write data to given OutputStream.
+
+
+A B C D E F G H I L M N O P R S T V W 
All Classes and Interfaces|All Packages|Constant Field Values
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/index.html b/0.9.16/_static/javadoc/index.html new file mode 100644 index 0000000..af1405a --- /dev/null +++ b/0.9.16/_static/javadoc/index.html @@ -0,0 +1,82 @@ + + + + +Overview (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API

+
+
+
Packages
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+ +
+
This package contains the Data Transformations.
+
+ +
+
This package provides util classes for the Extraction Plugin SDK API.
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/legal/ADDITIONAL_LICENSE_INFO b/0.9.16/_static/javadoc/legal/ADDITIONAL_LICENSE_INFO new file mode 100644 index 0000000..ff700cd --- /dev/null +++ b/0.9.16/_static/javadoc/legal/ADDITIONAL_LICENSE_INFO @@ -0,0 +1,37 @@ + ADDITIONAL INFORMATION ABOUT LICENSING + +Certain files distributed by Oracle America, Inc. and/or its affiliates are +subject to the following clarification and special exception to the GPLv2, +based on the GNU Project exception for its Classpath libraries, known as the +GNU Classpath Exception. + +Note that Oracle includes multiple, independent programs in this software +package. Some of those programs are provided under licenses deemed +incompatible with the GPLv2 by the Free Software Foundation and others. +For example, the package includes programs licensed under the Apache +License, Version 2.0 and may include FreeType. Such programs are licensed +to you under their original licenses. + +Oracle facilitates your further distribution of this package by adding the +Classpath Exception to the necessary parts of its GPLv2 code, which permits +you to use that code in combination with other independent modules not +licensed under the GPLv2. However, note that this would not permit you to +commingle code under an incompatible license with Oracle's GPLv2 licensed +code by, for example, cutting and pasting such code into a file also +containing Oracle's GPLv2 licensed code and then distributing the result. + +Additionally, if you were to remove the Classpath Exception from any of the +files to which it applies and distribute the result, you would likely be +required to license some or all of the other code in that distribution under +the GPLv2 as well, and since the GPLv2 is incompatible with the license terms +of some items included in the distribution by Oracle, removing the Classpath +Exception could therefore effectively compromise your ability to further +distribute the package. + +Failing to distribute notices associated with some files may also create +unexpected legal consequences. + +Proceed with caution and we recommend that you obtain the advice of a lawyer +skilled in open source matters before removing the Classpath Exception or +making modifications to this package which may subsequently be redistributed +and/or involve the use of third party software. diff --git a/0.9.16/_static/javadoc/legal/ASSEMBLY_EXCEPTION b/0.9.16/_static/javadoc/legal/ASSEMBLY_EXCEPTION new file mode 100644 index 0000000..4296666 --- /dev/null +++ b/0.9.16/_static/javadoc/legal/ASSEMBLY_EXCEPTION @@ -0,0 +1,27 @@ + +OPENJDK ASSEMBLY EXCEPTION + +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.org ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 +only ("GPL2"), with the following clarification and special exception. + + Linking this OpenJDK Code statically or dynamically with other code + is making a combined work based on this library. Thus, the terms + and conditions of GPL2 cover the whole combination. + + As a special exception, Oracle gives you permission to link this + OpenJDK Code with certain code licensed by Oracle as indicated at + https://openjdk.org/legal/exception-modules-2007-05-08.html + ("Designated Exception Modules") to produce an executable, + regardless of the license terms of the Designated Exception Modules, + and to copy and distribute the resulting executable under GPL2, + provided that the Designated Exception Modules continue to be + governed by the licenses under which they were offered by Oracle. + +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/0.9.16/_static/javadoc/legal/LICENSE b/0.9.16/_static/javadoc/legal/LICENSE new file mode 100644 index 0000000..8b400c7 --- /dev/null +++ b/0.9.16/_static/javadoc/legal/LICENSE @@ -0,0 +1,347 @@ +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must +make sure that they, too, receive or can get the source code. And you must +show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as +you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the +Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may +at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or + in part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of + this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms +of this License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and +2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord with + Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code +distributed need not include anything that is normally distributed (in either +source or binary form) with the major components (compiler, kernel, and so on) +of the operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source +code from the same place counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance by +third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through +you, then the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In +such case, this License incorporates the limitation as if written in the body +of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software Foundation. +If the Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE +PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + + Copyright (C) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes + with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free + software, and you are welcome to redistribute it under certain conditions; + type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + 'Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + + +"CLASSPATH" EXCEPTION TO THE GPL + +Certain source files distributed by Oracle America and/or its affiliates are +subject to the following clarification and special exception to the GPL, but +only where Oracle has expressly included in the particular source file's header +the words "Oracle designates this particular file as subject to the "Classpath" +exception as provided by Oracle in the LICENSE file that accompanied this code." + + Linking this library statically or dynamically with other modules is making + a combined work based on this library. Thus, the terms and conditions of + the GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules, + and to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent module, + the terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. If + you modify this library, you may extend this exception to your version of + the library, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. diff --git a/0.9.16/_static/javadoc/legal/jquery.md b/0.9.16/_static/javadoc/legal/jquery.md new file mode 100644 index 0000000..d468b31 --- /dev/null +++ b/0.9.16/_static/javadoc/legal/jquery.md @@ -0,0 +1,72 @@ +## jQuery v3.6.1 + +### jQuery License +``` +jQuery v 3.6.1 +Copyright OpenJS Foundation and other contributors, https://openjsf.org/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************** + +The jQuery JavaScript Library v3.6.1 also includes Sizzle.js + +Sizzle.js includes the following license: + +Copyright JS Foundation and other contributors, https://js.foundation/ + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/jquery/sizzle + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +All files located in the node_modules and external directories are +externally maintained libraries used by this software which have their +own licenses; we recommend you read them, as their terms may differ from +the terms above. + +********************* + +``` diff --git a/0.9.16/_static/javadoc/legal/jqueryUI.md b/0.9.16/_static/javadoc/legal/jqueryUI.md new file mode 100644 index 0000000..8bda9d7 --- /dev/null +++ b/0.9.16/_static/javadoc/legal/jqueryUI.md @@ -0,0 +1,49 @@ +## jQuery UI v1.13.2 + +### jQuery UI License +``` +Copyright jQuery Foundation and other contributors, https://jquery.org/ + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/jquery/jquery-ui + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code contained within the demos directory. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +All files located in the node_modules and external directories are +externally maintained libraries used by this software which have their +own licenses; we recommend you read them, as their terms may differ from +the terms above. + +``` diff --git a/0.9.16/_static/javadoc/link.svg b/0.9.16/_static/javadoc/link.svg new file mode 100644 index 0000000..7ccc5ed --- /dev/null +++ b/0.9.16/_static/javadoc/link.svg @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/0.9.16/_static/javadoc/member-search-index.js b/0.9.16/_static/javadoc/member-search-index.js new file mode 100644 index 0000000..1e5f0a8 --- /dev/null +++ b/0.9.16/_static/javadoc/member-search-index.js @@ -0,0 +1 @@ +memberSearchIndex = [{"p":"org.hansken.plugin.extraction.util","c":"ThrowingConsumer","l":"accept(T)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation.Builder","l":"add(DataRange...)","u":"add(org.hansken.plugin.extraction.api.transformations.DataRange...)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation.Builder","l":"add(List)","u":"add(java.util.List)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation.Builder","l":"addRange(long, long)","u":"addRange(long,long)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"addTracelet(String, Consumer)","u":"addTracelet(java.lang.String,java.util.function.Consumer)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"addTracelet(Trace.Tracelet)","u":"addTracelet(org.hansken.plugin.extraction.api.Trace.Tracelet)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"addType(String)","u":"addType(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"addValue(String, T)","u":"addValue(java.lang.String,T)"},{"p":"org.hansken.plugin.extraction.api","c":"TraceSearcher","l":"ALL_SEARCH_RESULTS"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotAllNull(String, Object...)","u":"argNotAllNull(java.lang.String,java.lang.Object...)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotEmpty(String, Collection)","u":"argNotEmpty(java.lang.String,java.util.Collection)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotEmpty(String, String)","u":"argNotEmpty(java.lang.String,java.lang.String)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotEmpty(String, T[])","u":"argNotEmpty(java.lang.String,T[])"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotNegative(String, float)","u":"argNotNegative(java.lang.String,float)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotNegative(String, int)","u":"argNotNegative(java.lang.String,int)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotNegative(String, long)","u":"argNotNegative(java.lang.String,long)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argNotNull(String, T)","u":"argNotNull(java.lang.String,T)"},{"p":"org.hansken.plugin.extraction.util","c":"ArgChecks","l":"argsIsType(String, List, Class)","u":"argsIsType(java.lang.String,java.util.List,java.lang.Class)"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"asBinary()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Direction","l":"ASCENDING"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"asVector(byte[])"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"author()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"author(Author)","u":"author(org.hansken.plugin.extraction.api.Author)"},{"p":"org.hansken.plugin.extraction.api","c":"BatchSearchResult","l":"BatchSearchResult(long)","u":"%3Cinit%3E(long)"},{"p":"org.hansken.plugin.extraction.api","c":"Author.Builder","l":"build()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"build()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources.Builder","l":"build()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions.Builder","l":"build()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Builder","l":"build()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation.Builder","l":"build()"},{"p":"org.hansken.plugin.extraction.api","c":"Author","l":"builder()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources","l":"builder()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"builder()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"builder()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation","l":"builder()"},{"p":"org.hansken.plugin.extraction.api","c":"Author.Builder","l":"Builder()","u":"%3Cinit%3E()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions.Builder","l":"Builder()","u":"%3Cinit%3E()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Builder","l":"Builder()","u":"%3Cinit%3E()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation.Builder","l":"Builder()","u":"%3Cinit%3E()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"builderFor(BaseExtractionPlugin)","u":"builderFor(org.hansken.plugin.extraction.api.BaseExtractionPlugin)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"builderFor(PluginType)","u":"builderFor(org.hansken.plugin.extraction.api.PluginType)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginId","l":"category()"},{"p":"org.hansken.plugin.extraction.api","c":"DataContext","l":"data()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"DataRange","l":"DataRange(long, long)","u":"%3Cinit%3E(long,long)"},{"p":"org.hansken.plugin.extraction.api","c":"DataContext","l":"dataType()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"DEFAULT"},{"p":"org.hansken.plugin.extraction.api","c":"PluginType","l":"DEFERRED_EXTRACTION_PLUGIN"},{"p":"org.hansken.plugin.extraction.api","c":"PluginType","l":"DEFERRED_META_EXTRACTION_PLUGIN"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"deferredIterations()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"deferredIterations(int)"},{"p":"org.hansken.plugin.extraction.api","c":"DeferredMetaExtractionPlugin","l":"DeferredMetaExtractionPlugin()","u":"%3Cinit%3E()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Direction","l":"DESCENDING"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"description()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"description(String)","u":"description(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"direction()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Builder","l":"direction(SearchSortOption.Direction)","u":"direction(org.hansken.plugin.extraction.api.SearchSortOption.Direction)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginId","l":"domain()"},{"p":"org.hansken.plugin.extraction.api","c":"Author","l":"email()"},{"p":"org.hansken.plugin.extraction.api","c":"Author.Builder","l":"email(String)","u":"email(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"enableBulkMode()"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"equals(Object)","u":"equals(java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"equals(Object)","u":"equals(java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"equals(Object)","u":"equals(java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"equals(Object)","u":"equals(java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginType","l":"EXTRACTION_PLUGIN"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"field()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Builder","l":"field(String)","u":"field(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"fullName()"},{"p":"org.hansken.plugin.extraction.api","c":"ImmutableTrace","l":"get(String)","u":"get(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.TraceletBuilder","l":"get(String)","u":"get(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"TransformerArgument","l":"getArgument()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchTrace","l":"getData(String)","u":"getData(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchTrace","l":"getDataTypes()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"DataRange","l":"getLength()"},{"p":"org.hansken.plugin.extraction.api","c":"TransformerLabel","l":"getMethodName()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.Tracelet","l":"getName()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.TraceletProperty","l":"getName()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"getNewTracelets()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"DataRange","l":"getOffset()"},{"p":"org.hansken.plugin.extraction.api","c":"TransformerLabel","l":"getParameters()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation","l":"getRanges()"},{"p":"org.hansken.plugin.extraction.api","c":"TransformerLabel","l":"getReturnType()"},{"p":"org.hansken.plugin.extraction.api","c":"BatchSearchResult","l":"getTotalHits()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchResult","l":"getTotalHits()"},{"p":"org.hansken.plugin.extraction.api","c":"BatchSearchResult","l":"getTraces()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchResult","l":"getTraces()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.TraceletBuilder","l":"getType()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.Tracelet","l":"getValue()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.TraceletProperty","l":"getValue()"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"hashCode()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"hashCode()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"hashCode()"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"hashCode()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"hqlMatcher()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"hqlMatcher(String)","u":"hqlMatcher(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"id()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"id(PluginId)","u":"id(org.hansken.plugin.extraction.api.PluginId)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"id(String, String, String)","u":"id(java.lang.String,java.lang.String,java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchScope","l":"IMAGE"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"isBulkModeEnabled()"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"latitude()"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"LatLong(double, double)","u":"%3Cinit%3E(double,double)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"license()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"license(String)","u":"license(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"longitude()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"maturityLevel()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"maturityLevel(MaturityLevel)","u":"maturityLevel(org.hansken.plugin.extraction.api.MaturityLevel)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources","l":"maximumCpu()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources.Builder","l":"maximumCpu(float)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources","l":"maximumMemory()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources.Builder","l":"maximumMemory(int)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources","l":"maximumWorkers()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginResources.Builder","l":"maximumWorkers(int)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginType","l":"META_EXTRACTION_PLUGIN"},{"p":"org.hansken.plugin.extraction.api","c":"MetaExtractionPlugin","l":"MetaExtractionPlugin()","u":"%3Cinit%3E()"},{"p":"org.hansken.plugin.extraction.api","c":"Author","l":"name()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginId","l":"name()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"name()"},{"p":"org.hansken.plugin.extraction.api","c":"Author.Builder","l":"name(String)","u":"name(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"name(String)","u":"name(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"newChild(String, ThrowingConsumer)","u":"newChild(java.lang.String,org.hansken.plugin.extraction.util.ThrowingConsumer)"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"of(Collection)","u":"of(java.util.Collection)"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"of(double, double)","u":"of(double,double)"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"of(float...)"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"of(String)","u":"of(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"ofBase64(String)","u":"ofBase64(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions.Builder","l":"offset(int)"},{"p":"org.hansken.plugin.extraction.api","c":"Author","l":"organisation()"},{"p":"org.hansken.plugin.extraction.api","c":"Author.Builder","l":"organisation(String)","u":"organisation(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginId","l":"PluginId(String, String, String)","u":"%3Cinit%3E(java.lang.String,java.lang.String,java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"BaseExtractionPlugin","l":"pluginInfo()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"pluginType()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"pluginVersion()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"pluginVersion(String)","u":"pluginVersion(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"position()"},{"p":"org.hansken.plugin.extraction.api","c":"MetaExtractionPlugin","l":"process(Trace)","u":"process(org.hansken.plugin.extraction.api.Trace)"},{"p":"org.hansken.plugin.extraction.api","c":"ExtractionPlugin","l":"process(Trace, DataContext)","u":"process(org.hansken.plugin.extraction.api.Trace,org.hansken.plugin.extraction.api.DataContext)"},{"p":"org.hansken.plugin.extraction.api","c":"MetaExtractionPlugin","l":"process(Trace, DataContext)","u":"process(org.hansken.plugin.extraction.api.Trace,org.hansken.plugin.extraction.api.DataContext)"},{"p":"org.hansken.plugin.extraction.api","c":"DeferredExtractionPlugin","l":"process(Trace, DataContext, TraceSearcher)","u":"process(org.hansken.plugin.extraction.api.Trace,org.hansken.plugin.extraction.api.DataContext,org.hansken.plugin.extraction.api.TraceSearcher)"},{"p":"org.hansken.plugin.extraction.api","c":"DeferredMetaExtractionPlugin","l":"process(Trace, DataContext, TraceSearcher)","u":"process(org.hansken.plugin.extraction.api.Trace,org.hansken.plugin.extraction.api.DataContext,org.hansken.plugin.extraction.api.TraceSearcher)"},{"p":"org.hansken.plugin.extraction.api","c":"DeferredMetaExtractionPlugin","l":"process(Trace, TraceSearcher)","u":"process(org.hansken.plugin.extraction.api.Trace,org.hansken.plugin.extraction.api.TraceSearcher)"},{"p":"org.hansken.plugin.extraction.api","c":"MaturityLevel","l":"PRODUCTION_READY"},{"p":"org.hansken.plugin.extraction.api","c":"SearchScope","l":"PROJECT"},{"p":"org.hansken.plugin.extraction.api","c":"MaturityLevel","l":"PROOF_OF_CONCEPT"},{"p":"org.hansken.plugin.extraction.api","c":"ImmutableTrace","l":"properties()"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation","l":"RangedDataTransformation(DataRange...)","u":"%3Cinit%3E(org.hansken.plugin.extraction.api.transformations.DataRange...)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation","l":"RangedDataTransformation(List)","u":"%3Cinit%3E(java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"read(byte[])"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"read(byte[], int)","u":"read(byte[],int)"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"read(byte[], int, int)","u":"read(byte[],int,int)"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"readNBytes(int)"},{"p":"org.hansken.plugin.extraction.api","c":"MaturityLevel","l":"READY_FOR_TEST"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"remaining()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"resources()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"resources(PluginResources)","u":"resources(org.hansken.plugin.extraction.api.PluginResources)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"scope()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions.Builder","l":"scope(SearchScope)","u":"scope(org.hansken.plugin.extraction.api.SearchScope)"},{"p":"org.hansken.plugin.extraction.api","c":"TraceSearcher","l":"search(String)","u":"search(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"TraceSearcher","l":"search(String, int)","u":"search(java.lang.String,int)"},{"p":"org.hansken.plugin.extraction.api","c":"TraceSearcher","l":"search(String, int, SearchOptions)","u":"search(java.lang.String,int,org.hansken.plugin.extraction.api.SearchOptions)"},{"p":"org.hansken.plugin.extraction.api","c":"TraceSearcher","l":"search(String, int, SearchScope, int, List)","u":"search(java.lang.String,int,org.hansken.plugin.extraction.api.SearchScope,int,java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"TraceSearcher","l":"search(String, SearchOptions)","u":"search(java.lang.String,org.hansken.plugin.extraction.api.SearchOptions)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"SearchOptions(SearchScope, int, List)","u":"%3Cinit%3E(org.hansken.plugin.extraction.api.SearchScope,int,java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"SearchSortOption(String, SearchSortOption.Direction)","u":"%3Cinit%3E(java.lang.String,org.hansken.plugin.extraction.api.SearchSortOption.Direction)"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"seek(long)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"set(String, Object)","u":"set(java.lang.String,java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.TraceletBuilder","l":"set(String, Object)","u":"set(java.lang.String,java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"setData(String, DataTransformation...)","u":"setData(java.lang.String,org.hansken.plugin.extraction.api.transformations.DataTransformation...)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"setData(String, DataWriter)","u":"setData(java.lang.String,org.hansken.plugin.extraction.api.DataWriter)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"setData(String, InputStream)","u":"setData(java.lang.String,java.io.InputStream)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace","l":"setData(String, List)","u":"setData(java.lang.String,java.util.List)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"DataRange","l":"setLength(long)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"DataRange","l":"setOffset(long)"},{"p":"org.hansken.plugin.extraction.api.transformations","c":"RangedDataTransformation","l":"setRanges(List)","u":"setRanges(java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"BatchSearchResult","l":"setTraces(SearchTrace[])","u":"setTraces(org.hansken.plugin.extraction.api.SearchTrace[])"},{"p":"org.hansken.plugin.extraction.api","c":"RandomAccessData","l":"size()"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"size()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"sort()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions.Builder","l":"sort(List)","u":"sort(java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"start()"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"toBase64()"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"toISO6709()"},{"p":"org.hansken.plugin.extraction.api","c":"LatLong","l":"toString()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginId","l":"toString()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchOptions","l":"toString()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption","l":"toString()"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"toString()"},{"p":"org.hansken.plugin.extraction.api","c":"ImmutableTrace","l":"traceId()"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.Tracelet","l":"Tracelet(String, List)","u":"%3Cinit%3E(java.lang.String,java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"Trace.TraceletProperty","l":"TraceletProperty(String, Object)","u":"%3Cinit%3E(java.lang.String,java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"transformer(List)","u":"transformer(java.util.List)"},{"p":"org.hansken.plugin.extraction.api","c":"TransformerArgument","l":"TransformerArgument(Object)","u":"%3Cinit%3E(java.lang.Object)"},{"p":"org.hansken.plugin.extraction.api","c":"TransformerLabel","l":"TransformerLabel(String, Map, String)","u":"%3Cinit%3E(java.lang.String,java.util.Map,java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"transformers()"},{"p":"org.hansken.plugin.extraction.api","c":"ImmutableTrace","l":"types()"},{"p":"org.hansken.plugin.extraction.api","c":"MaturityLevel","l":"valueOf(String)","u":"valueOf(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"PluginType","l":"valueOf(String)","u":"valueOf(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchScope","l":"valueOf(String)","u":"valueOf(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Direction","l":"valueOf(String)","u":"valueOf(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"MaturityLevel","l":"values()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginType","l":"values()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchScope","l":"values()"},{"p":"org.hansken.plugin.extraction.api","c":"SearchSortOption.Direction","l":"values()"},{"p":"org.hansken.plugin.extraction.api","c":"Vector","l":"values()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo","l":"webpageUrl()"},{"p":"org.hansken.plugin.extraction.api","c":"PluginInfo.Builder","l":"webpageUrl(String)","u":"webpageUrl(java.lang.String)"},{"p":"org.hansken.plugin.extraction.api","c":"DataWriter","l":"writeTo(OutputStream)","u":"writeTo(java.io.OutputStream)"}];updateSearchResults(); \ No newline at end of file diff --git a/0.9.16/_static/javadoc/module-search-index.js b/0.9.16/_static/javadoc/module-search-index.js new file mode 100644 index 0000000..0d59754 --- /dev/null +++ b/0.9.16/_static/javadoc/module-search-index.js @@ -0,0 +1 @@ +moduleSearchIndex = [];updateSearchResults(); \ No newline at end of file diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Author.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Author.Builder.html new file mode 100644 index 0000000..bca2455 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Author.Builder.html @@ -0,0 +1,253 @@ + + + + +Author.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class Author.Builder

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.Author.Builder
+
+
+
+
Enclosing class:
+
Author
+
+
+
public static final class Author.Builder +extends Object
+
A builder for an author. +

+ Note: all methods throw a NullPointerException when null + is passed to them, and all properties must be set.

+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      Builder

      +
      public Builder()
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    + +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Author.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Author.html new file mode 100644 index 0000000..945daef --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Author.html @@ -0,0 +1,235 @@ + + + + +Author (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class Author

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.Author
+
+
+
+
public final class Author +extends Object
+
An author of a certain extraction plugin. +

+ Example for creating an author: +

+ 
+ Author.builder()
+     .name("John")
+     .email("johndoe@email.com")
+     .organisation("Netherlands Forensic Institute")
+     .build();
+ 
+ 
+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      builder

      +
      public static Author.Builder builder()
      +
      Start creating a new author.
      +
      +
      Returns:
      +
      a builder for an author
      +
      +
      +
    • +
    • +
      +

      name

      +
      public String name()
      +
      Get the name of the author.
      +
      +
      Returns:
      +
      the name of the author
      +
      +
      +
    • +
    • +
      +

      email

      +
      public String email()
      +
      Get the email address of the author.
      +
      +
      Returns:
      +
      the email address of the author.
      +
      +
      +
    • +
    • +
      +

      organisation

      +
      public String organisation()
      +
      Get the name of the organisation the author belongs to.
      +
      +
      Returns:
      +
      the organisation of the author
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/BaseExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/BaseExtractionPlugin.html new file mode 100644 index 0000000..898222f --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/BaseExtractionPlugin.html @@ -0,0 +1,164 @@ + + + + +BaseExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface BaseExtractionPlugin

+
+
+
+
All Known Subinterfaces:
+
DeferredExtractionPlugin, ExtractionPlugin
+
+
+
All Known Implementing Classes:
+
DeferredMetaExtractionPlugin, MetaExtractionPlugin
+
+
+
public interface BaseExtractionPlugin
+
This the base class for types of Extraction Plugins, and cannot be used solely as a superclass for a plugin. + Implement one of its subclasses that have a 'process' method. + Extraction plugins can be used by Hansken to process data during the extraction process.
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    + + +
    +
    Get the information of this plugin, such as the author or a description, and the + types of traces and data it matches on.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      pluginInfo

      +
      PluginInfo pluginInfo()
      +
      Get the information of this plugin, such as the author or a description, and the + types of traces and data it matches on.
      +
      +
      Returns:
      +
      the metadata of the plugin
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/BatchSearchResult.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/BatchSearchResult.html new file mode 100644 index 0000000..5f90a4d --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/BatchSearchResult.html @@ -0,0 +1,232 @@ + + + + +BatchSearchResult (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class BatchSearchResult

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.BatchSearchResult
+
+
+
+
All Implemented Interfaces:
+
SearchResult
+
+
+
public class BatchSearchResult +extends Object +implements SearchResult
+
A BatchSearchResult is a SearchResult implementation that stores all found traces using a single + setTraces(SearchTrace[]) call. +

+ This class is used by Hansken (the client) to return a single batch of search results.

+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      BatchSearchResult

      +
      public BatchSearchResult(long totalResults)
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getTraces

      +
      public Stream<SearchTrace> getTraces()
      +
      Description copied from interface: SearchResult
      +
      Returns all found traces.
      +
      +
      Specified by:
      +
      getTraces in interface SearchResult
      +
      Returns:
      +
      found traces.
      +
      +
      +
    • +
    • +
      +

      setTraces

      +
      public void setTraces(SearchTrace[] traces)
      +
      Sets all traces that can be returned by calling getTraces.
      +
      +
      Parameters:
      +
      traces - an array of ImmutableTraces.
      +
      +
      +
    • +
    • +
      +

      getTotalHits

      +
      public long getTotalHits()
      +
      Description copied from interface: SearchResult
      +
      Returns the total number of traces matching the query.
      +
      +
      Specified by:
      +
      getTotalHits in interface SearchResult
      +
      Returns:
      +
      total number of matching traces
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DataContext.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DataContext.html new file mode 100644 index 0000000..3fac9c9 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DataContext.html @@ -0,0 +1,182 @@ + + + + +DataContext (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface DataContext

+
+
+
+
public interface DataContext
+
The data context contains information about a data stream of a trace that is currently being + processed by an ExtractionPlugin or DeferredExtractionPlugin.
+
+
See Also:
+
+ +
+
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    + + +
    +
    A data sequence belonging to the trace currently being extracted.
    +
    + + +
    +
    The type of data (see data()) that is being processed.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      dataType

      +
      String dataType()
      +
      The type of data (see data()) that is being processed. The type is never empty or null. + This is the type of data the given data sequence represents, for example "raw" for raw + bytes or "plain" for plaintext. +

      + The data type will be one of those defined on the trace model associated with the trace being processed.

      +
      +
      Returns:
      +
      the name of the data type
      +
      +
      +
    • +
    • +
      +

      data

      + +
      A data sequence belonging to the trace currently being extracted. If necessary, + the type of the underlying data can be requested using dataType().
      +
      +
      Returns:
      +
      the data sequence
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DataWriter.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DataWriter.html new file mode 100644 index 0000000..48cc67e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DataWriter.html @@ -0,0 +1,160 @@ + + + + +DataWriter (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface DataWriter

+
+
+
+
public interface DataWriter
+
Writes data to an OutputStream. Used to enable lambda callbacks in for example + Trace.setData(String, DataWriter).
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    void
    + +
    +
    Write data to given OutputStream.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      writeTo

      +
      void writeTo(OutputStream stream) + throws IOException
      +
      Write data to given OutputStream. +

      + Note: the received output stream should not be closed by the user. It should + also only be used within the scope of the function, other usage may be guarded against or otherwise + result in undefined behaviour.

      +
      +
      Parameters:
      +
      stream - the stream to write data to
      +
      Throws:
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DeferredExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DeferredExtractionPlugin.html new file mode 100644 index 0000000..1907389 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DeferredExtractionPlugin.html @@ -0,0 +1,190 @@ + + + + +DeferredExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface DeferredExtractionPlugin

+
+
+
+
All Superinterfaces:
+
BaseExtractionPlugin
+
+
+
All Known Implementing Classes:
+
DeferredMetaExtractionPlugin
+
+
+
public interface DeferredExtractionPlugin +extends BaseExtractionPlugin
+
Deferred extraction plugins can be used by Hansken to process traces during the extraction process. + A processed trace can be enriched with new information and new child traces can also be created. +

+ The difference between this and a normal ExtractionPlugin is that this plugin is able to run a secondary query + for traces and combine the results with previously retrieved traces. +

+ When a plugin matches on the trace which is currently processed by Hansken + (for example, because it has certain properties), the plugin will receive the + matched trace in order to process it (see process(Trace, DataContext, TraceSearcher)).

+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    + +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DeferredMetaExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DeferredMetaExtractionPlugin.html new file mode 100644 index 0000000..94f3837 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/DeferredMetaExtractionPlugin.html @@ -0,0 +1,258 @@ + + + + +DeferredMetaExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class DeferredMetaExtractionPlugin

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin
+
+
+
+
All Implemented Interfaces:
+
BaseExtractionPlugin, DeferredExtractionPlugin
+
+
+
public abstract class DeferredMetaExtractionPlugin +extends Object +implements DeferredExtractionPlugin
+
Deferred meta extraction plugins can be used by Hansken to process traces during the extraction process. + A processed trace can be enriched with new information and new child traces can also be created. +

+ The difference between this and a normal ExtractionPlugin is that this plugin is able to run a secondary query + for traces and combine the results with previously retrieved traces, and that this plugin does not receive or + process any data, only a trace itself. +

+ When a plugin matches on the trace which is currently processed by Hansken + (for example, because it has certain properties), the plugin will receive the + matched trace in order to process it (see process(Trace, TraceSearcher)). +

+ Note for Hansken core developers: specifying 'meta' in the matcher is + not necessary, the framework takes care of this.

+
+
+ +
+
+ +
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/ExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/ExtractionPlugin.html new file mode 100644 index 0000000..443e0a2 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/ExtractionPlugin.html @@ -0,0 +1,184 @@ + + + + +ExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface ExtractionPlugin

+
+
+
+
All Superinterfaces:
+
BaseExtractionPlugin
+
+
+
All Known Implementing Classes:
+
MetaExtractionPlugin
+
+
+
public interface ExtractionPlugin +extends BaseExtractionPlugin
+
Extraction plugins can be used by Hansken to process traces during the extraction process. + A processed trace can be enriched with new information and new child traces can also be created. +

+ When a plugin matches on the trace which is currently processed by Hansken + (for example, because it has certain properties or a certain type of data sequence), the plugin will receive the + matched trace and data in order to process it (see process(Trace, DataContext)).

+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      process

      +
      void process(Trace trace, + DataContext dataContext) + throws IOException
      +
      Start processing a trace with a given data context. + + When processing a given trace, new properties may be set on it. New children can be added using + Trace.newChild(String, ThrowingConsumer). +

      + A trace can have multiple data sequences of different types. Because of this, a certain trace might + be processed multiple times (depending on if this plugin triggers on the different data types). +

      + Note: the given trace should only be modified within the scope of this method. + Any modifications afterward may be guarded against or result in undefined behavior.

      +
      +
      Parameters:
      +
      trace - the trace to process
      +
      dataContext - data context of the traces data stream that is being processed
      +
      Throws:
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/ImmutableTrace.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/ImmutableTrace.html new file mode 100644 index 0000000..ba37b56 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/ImmutableTrace.html @@ -0,0 +1,215 @@ + + + + +ImmutableTrace (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface ImmutableTrace

+
+
+
+
All Known Subinterfaces:
+
SearchTrace, Trace
+
+
+
public interface ImmutableTrace
+
A trace contains information about processed data. A trace should conform to the trace model defined by Hansken. + Unlike a Trace, an ImmutableTrace instance lacks methods to modify or update its properties and data + streams after the instance is created.
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    <T> T
    +
    get(String name)
    +
    +
    Get the value of the property with given name on this trace.
    +
    + + +
    +
    Return the names of all the properties contained in this trace.
    +
    + + +
    +
    Get the trace id of this trace.
    +
    + + +
    +
    Get all the types of this trace.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      traceId

      +
      String traceId()
      +
      Get the trace id of this trace. + Note: This value is equal to the id of a Hansken Trace.
      +
      +
      Returns:
      +
      the id of this trace
      +
      +
      +
    • +
    • +
      +

      types

      +
      Set<String> types()
      +
      Get all the types of this trace.
      +
      +
      Returns:
      +
      all types of this trace
      +
      +
      +
    • +
    • +
      +

      properties

      +
      Set<String> properties()
      +
      Return the names of all the properties contained in this trace.
      +
      +
      Returns:
      +
      the properties of this trace
      +
      +
      +
    • +
    • +
      +

      get

      +
      <T> T get(String name)
      +
      Get the value of the property with given name on this trace. +

      + Note: the method is declared with a type parameter to allow for + automatic casting. It is an unchecked cast, so implementers have to make sure that + the type of the value returned is of type T.

      +
      +
      Type Parameters:
      +
      T - the type of the value
      +
      Parameters:
      +
      name - the name of the value to get
      +
      Returns:
      +
      the value of the property
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/LatLong.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/LatLong.html new file mode 100644 index 0000000..0d57f33 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/LatLong.html @@ -0,0 +1,298 @@ + + + + +LatLong (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class LatLong

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.LatLong
+
+
+
+
public class LatLong +extends Object
+
A geographical location consisting of a latitude and a longitude.
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      LatLong

      +
      protected LatLong(double latitude, + double longitude)
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      of

      +
      public static LatLong of(double latitude, + double longitude)
      +
      Create a new geographical point with given latitude + and longitude. +

      + Note: this does not do any input validation. Valid + values should be between -90 and +90 inclusive for latitude and + between -180 and +180 inclusive for longitude.

      +
      +
      Parameters:
      +
      latitude - the latitude
      +
      longitude - the longitude
      +
      Returns:
      +
      the new point
      +
      +
      +
    • +
    • +
      +

      of

      +
      public static LatLong of(String coordinates)
      +
      +
    • +
    • +
      +

      latitude

      +
      public double latitude()
      +
      The north-south position of a point on earth.
      +
      +
      Returns:
      +
      the latitude
      +
      +
      +
    • +
    • +
      +

      longitude

      +
      public double longitude()
      +
      The east-west position of a point on earth.
      +
      +
      Returns:
      +
      the longitude
      +
      +
      +
    • +
    • +
      +

      toISO6709

      +
      public String toISO6709()
      +
      Format to String using ISO 6709. The output is in 5 decimals. + The decimal degree precision is 1.1132m at the equator
      +
      +
      Returns:
      +
      notation according to ISO 6709
      +
      +
      +
    • +
    • +
      +

      equals

      +
      public boolean equals(Object o)
      +
      +
      Overrides:
      +
      equals in class Object
      +
      +
      +
    • +
    • +
      +

      hashCode

      +
      public int hashCode()
      +
      +
      Overrides:
      +
      hashCode in class Object
      +
      +
      +
    • +
    • +
      +

      toString

      +
      public String toString()
      +
      +
      Overrides:
      +
      toString in class Object
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/MaturityLevel.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/MaturityLevel.html new file mode 100644 index 0000000..3adccc4 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/MaturityLevel.html @@ -0,0 +1,255 @@ + + + + +MaturityLevel (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Enum Class MaturityLevel

+
+
java.lang.Object +
java.lang.Enum<MaturityLevel> +
org.hansken.plugin.extraction.api.MaturityLevel
+
+
+
+
+
All Implemented Interfaces:
+
Serializable, Comparable<MaturityLevel>, Constable
+
+
+
public enum MaturityLevel +extends Enum<MaturityLevel>
+
Indicates what stage of maturity a certain extraction plugin is in.
+
+
+ +
+
+
    + +
  • +
    +

    Enum Constant Details

    +
      +
    • +
      +

      PROOF_OF_CONCEPT

      +
      public static final MaturityLevel PROOF_OF_CONCEPT
      +
      The plugin is in a proof of concept phase, not yet ready for test or production.
      +
      +
    • +
    • +
      +

      READY_FOR_TEST

      +
      public static final MaturityLevel READY_FOR_TEST
      +
      The plugin can be used in a test environment and is expected to be fully functional.
      +
      +
    • +
    • +
      +

      PRODUCTION_READY

      +
      public static final MaturityLevel PRODUCTION_READY
      +
      The plugin is ready to be used in a production environment.
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      values

      +
      public static MaturityLevel[] values()
      +
      Returns an array containing the constants of this enum class, in +the order they are declared.
      +
      +
      Returns:
      +
      an array containing the constants of this enum class, in the order they are declared
      +
      +
      +
    • +
    • +
      +

      valueOf

      +
      public static MaturityLevel valueOf(String name)
      +
      Returns the enum constant of this class with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this class. (Extraneous whitespace characters are +not permitted.)
      +
      +
      Parameters:
      +
      name - the name of the enum constant to be returned.
      +
      Returns:
      +
      the enum constant with the specified name
      +
      Throws:
      +
      IllegalArgumentException - if this enum class has no constant with the specified name
      +
      NullPointerException - if the argument is null
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/MetaExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/MetaExtractionPlugin.html new file mode 100644 index 0000000..454c220 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/MetaExtractionPlugin.html @@ -0,0 +1,247 @@ + + + + +MetaExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class MetaExtractionPlugin

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.MetaExtractionPlugin
+
+
+
+
All Implemented Interfaces:
+
BaseExtractionPlugin, ExtractionPlugin
+
+
+
public abstract class MetaExtractionPlugin +extends Object +implements ExtractionPlugin
+
Meta extraction plugins can be used by Hansken to process traces during the extraction process. + A processed trace can be enriched with new information and new child traces can also be created. +

+ The difference between this and a normal ExtractionPlugin is that this plugin does not receive + or process any data, only a trace itself. +

+ When a plugin matches on the trace which is currently processed by Hansken + (for example, because it has certain properties), the plugin will receive the + matched trace in order to process it (see process(Trace)). +

+ Note for Hansken core developers: specifying 'meta' in the matcher is + not necessary, the framework takes care of this.

+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      MetaExtractionPlugin

      +
      public MetaExtractionPlugin()
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      process

      +
      public final void process(Trace trace, + DataContext dataContext) + throws IOException
      +
      Description copied from interface: ExtractionPlugin
      +
      Start processing a trace with a given data context. + + When processing a given trace, new properties may be set on it. New children can be added using + Trace.newChild(String, ThrowingConsumer). +

      + A trace can have multiple data sequences of different types. Because of this, a certain trace might + be processed multiple times (depending on if this plugin triggers on the different data types). +

      + Note: the given trace should only be modified within the scope of this method. + Any modifications afterward may be guarded against or result in undefined behavior.

      +
      +
      Specified by:
      +
      process in interface ExtractionPlugin
      +
      Parameters:
      +
      trace - the trace to process
      +
      dataContext - data context of the traces data stream that is being processed
      +
      Throws:
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    • +
      +

      process

      +
      public abstract void process(Trace trace) + throws IOException
      +
      Start processing a trace without any of its associated data streams. + When processing a given trace, new properties may be set on it. New children can be added using + Trace.newChild(String, ThrowingConsumer). +

      + Note: the given trace should only be modified within the scope of this method. + Any modifications afterward may be guarded against or result in undefined behaviour.

      +
      +
      Parameters:
      +
      trace - the trace to process
      +
      Throws:
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginId.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginId.html new file mode 100644 index 0000000..fd1c49e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginId.html @@ -0,0 +1,229 @@ + + + + +PluginId (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class PluginId

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.PluginId
+
+
+
+
public class PluginId +extends Object
+
Identifier of a plugin, consisting of domain, category and name. Needs to be unique among all tools/plugins.
+
+
Author:
+
Netherlands Forensic Institute
+
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      PluginId

      +
      public PluginId(String domain, + String category, + String name)
      +
      Create a unique identifier for a plugin, consisting of domain, category and name.
      +
      +
      Parameters:
      +
      domain - the domain of the organisation, for example "nfi.nl"
      +
      category - the action group of the plugin, for example `extract`, `carve`, `classify` (read the SDK documentation for more details).
      +
      name - the name of the plugin, or in the classic sense, a description detailing the action(s) of the plugin. Note that the name can contain (forward) slashes.
      + example: "nfi.nl/extract/ocr/detection/plugin".
      + in this example nfi.nl is the domain, extract is the category, and ocr/detection/plugin is the name.
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      domain

      +
      public String domain()
      +
      +
    • +
    • +
      +

      category

      +
      public String category()
      +
      +
    • +
    • +
      +

      name

      +
      public String name()
      +
      +
    • +
    • +
      +

      toString

      +
      public String toString()
      +
      +
      Overrides:
      +
      toString in class Object
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginInfo.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginInfo.Builder.html new file mode 100644 index 0000000..5c0f09b --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginInfo.Builder.html @@ -0,0 +1,439 @@ + + + + +PluginInfo.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class PluginInfo.Builder

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.PluginInfo.Builder
+
+
+
+
Enclosing class:
+
PluginInfo
+
+
+
public static final class PluginInfo.Builder +extends Object
+
A builder for plugin information. +

+ Note: all methods throw a NullPointerException when null + is passed to them.

+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      name

      +
      @Deprecated +public PluginInfo.Builder name(String name)
      +
      Deprecated. +
      Use id(PluginId) instead.
      +
      +
      Set the name of this plugin.
      +
      +
      Parameters:
      +
      name - the name
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if the name is empty
      +
      +
      +
    • +
    • +
      +

      pluginVersion

      +
      public PluginInfo.Builder pluginVersion(String version)
      + +
      +
      Parameters:
      +
      version - the plugin version
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if the version is empty
      +
      +
      +
    • +
    • +
      +

      description

      +
      public PluginInfo.Builder description(String description)
      +
      Set the description.
      +
      +
      Parameters:
      +
      description - the description
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if the description is empty
      +
      +
      +
    • +
    • +
      +

      author

      +
      public PluginInfo.Builder author(Author author)
      +
      Set the author.
      +
      +
      Parameters:
      +
      author - the author
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      maturityLevel

      +
      public PluginInfo.Builder maturityLevel(MaturityLevel maturityLevel)
      + +
      +
      Parameters:
      +
      maturityLevel - the maturity level
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      hqlMatcher

      +
      public PluginInfo.Builder hqlMatcher(String hqlMatcher)
      +
      Set the hqlMatcher query in string format.
      +
      +
      Parameters:
      +
      hqlMatcher - the matcher
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      webpageUrl

      +
      public PluginInfo.Builder webpageUrl(String webpageUrl)
      +
      Set the url to a webpage that belongs to this plugin. This can also be a link to a webpage of the git repository of the remote plugin.
      +
      +
      Parameters:
      +
      webpageUrl - url to webpage
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      deferredIterations

      +
      public PluginInfo.Builder deferredIterations(int deferredIterations)
      +
      Set the number of extraction iterations needed for this deferred plugin. + Only relevant for deferred plugins. + If this method is not called upon, default number of iterations will be set to 1.
      +
      +
      Parameters:
      +
      deferredIterations - number of iterations needed for this plugin. Should be between 1 and 20
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      id

      +
      public PluginInfo.Builder id(String domain, + String category, + String name)
      +
      Set the unique id of this plugin, consisting of domain, category and name. +

      + example: "nfi.nl/extract/ocr/detection/plugin".
      + in this example nfi.nl is the domain, extract is the category, and ocr/detection/plugin is the name.

      +
      +
      Parameters:
      +
      domain - the domain of the organisation, for example "nfi.nl"
      +
      category - the action group of the plugin, for example `extract`, `carve`, `classify` (read the SDK documentation for more details).
      +
      name - the name of the plugin, or in the classic sense, a description detailing the action(s) of the plugin. Note that the name can contain (forward) slashes.
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      id

      +
      public PluginInfo.Builder id(PluginId id)
      +
      Set the unique id of this plugin, consisting of domain, category and name.
      +
      +
      Parameters:
      +
      id - the unique id of this plugin, consisting of domain, category and name.
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      license

      +
      public PluginInfo.Builder license(String license)
      +
      Set the name of the license of this plugin.
      +
      +
      Parameters:
      +
      license - name of the license of the plugin
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      resources

      +
      public PluginInfo.Builder resources(PluginResources resources)
      +
      Set the resources of this plugin (optional).
      +
      +
      Parameters:
      +
      resources - the resources of this plugin
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      enableBulkMode

      +
      public PluginInfo.Builder enableBulkMode()
      +
      Set bulk mode (optional).
      +
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      transformer

      +
      public PluginInfo.Builder transformer(List<TransformerLabel> transformers)
      +
      Set the transformers of this plugin (optional).
      +
      +
      Parameters:
      +
      transformers - the transformers of this plugin
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      build

      +
      public PluginInfo build()
      +
      Create the plugin information from the properties set on this builder.
      +
      +
      Returns:
      +
      the created plugin information
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginInfo.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginInfo.html new file mode 100644 index 0000000..36f559f --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginInfo.html @@ -0,0 +1,467 @@ + + + + +PluginInfo (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class PluginInfo

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.PluginInfo
+
+
+
+
public final class PluginInfo +extends Object
+
Information about an extraction plugin, such as the author or + a human-readable description. +

+ Example PluginInfo: +

+     PluginInfo.builderFor(this)
+         .id("nfi.nl", "digest", "sha111")
+         .pluginVersion("0.2.1")
+         .description("Calculates hashes from data streams.")
+         .author(Author.builder()
+             .name("name")
+             .email("test@email.com")
+             .organisation("organisation")
+             .build())
+         .maturityLevel(MaturityLevel.PROOF_OF_CONCEPT)
+         .hqlMatcher("hql-lite query")
+         .webpageUrl("https://github.com/myOrg/digestPlugin")
+         .license("Apache License 2.0")
+         .resources(Resources.builder()
+             .maximumCpu(1)
+             .maximumMemory(1000)
+             .build())
+         .build();
+ 
+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      builderFor

      +
      public static PluginInfo.Builder builderFor(BaseExtractionPlugin plugin)
      +
      Start creating new plugin information for the given plugin.
      +
      +
      Parameters:
      +
      plugin - the plugin to create the plugin information for
      +
      Returns:
      +
      a builder for plugin metadata
      +
      +
      +
    • +
    • +
      +

      builderFor

      +
      public static PluginInfo.Builder builderFor(PluginType type)
      +
      Start creating new plugin information for a plugin of given type.
      +
      +
      Parameters:
      +
      type - the type of plugin to create the plugin information for
      +
      Returns:
      +
      a builder for plugin metadata
      +
      +
      +
    • +
    • +
      +

      pluginType

      +
      public PluginType pluginType()
      +
      Get the type of this plugin.
      +
      +
      Returns:
      +
      the type of this plugin
      +
      +
      +
    • +
    • +
      +

      name

      +
      @Deprecated +public String name()
      +
      Deprecated. +
      Use id() instead.
      +
      +
      Get the name of this plugin.
      +
      +
      Returns:
      +
      the name of this plugin
      +
      +
      +
    • +
    • +
      +

      fullName

      +
      public String fullName()
      +
      Get the full name of this plugin, based on the id. This name will be shown in the + Hansken GUI.
      +
      +
      Returns:
      +
      the full name of this plugin, based on the id
      +
      +
      +
    • +
    • +
      +

      pluginVersion

      +
      public String pluginVersion()
      +
      Get the version of this plugin.
      +
      +
      Returns:
      +
      the version of this plugin
      +
      +
      +
    • +
    • +
      +

      description

      +
      public String description()
      +
      Get a human readable description of this plugin.
      +
      +
      Returns:
      +
      a description of this plugin
      +
      +
      +
    • +
    • +
      +

      author

      +
      public Author author()
      +
      Get the author of this plugin.
      +
      +
      Returns:
      +
      the author of this plugin.
      +
      +
      +
    • +
    • +
      +

      maturityLevel

      +
      public MaturityLevel maturityLevel()
      +
      Get the maturity level of this plugin.
      +
      +
      Returns:
      +
      the maturity level of this plugin
      +
      +
      +
    • +
    • +
      +

      hqlMatcher

      +
      public String hqlMatcher()
      +
      Get the hqlMatcher of this plugin in string format.
      +
      +
      Returns:
      +
      the matcher of this plugin
      +
      +
      +
    • +
    • +
      +

      webpageUrl

      +
      public String webpageUrl()
      +
      Get the url of this plugin, could point to git repo or webpage that explains the plugin.
      +
      +
      Returns:
      +
      the url of this plugin
      +
      +
      +
    • +
    • +
      +

      deferredIterations

      +
      public int deferredIterations()
      +
      Get the number of extraction iterations before the deferred plugin can be applied on traces. + Only relevant for deferred plugins; default value is 1.
      +
      +
      Returns:
      +
      the number of iterations set of this plugin
      +
      +
      +
    • +
    • +
      +

      id

      +
      public PluginId id()
      +
      Get the the unique id of this plugin, consisting of domain, category and name.
      +
      +
      Returns:
      +
      the url of this plugin
      +
      +
      +
    • +
    • +
      +

      license

      +
      public String license()
      +
      Get the name of the license of this plugin.
      +
      +
      Returns:
      +
      the name of the license of this plugin
      +
      +
      +
    • +
    • +
      +

      transformers

      +
      public List<TransformerLabel> transformers()
      +
      Get a list of possible transform methods this plugin provides.
      +
      +
      Returns:
      +
      list of transform methods
      +
      +
      +
    • +
    • +
      +

      resources

      +
      public PluginResources resources()
      +
      Get the resources of this plugin.
      +
      +
      Returns:
      +
      the resources of this plugin
      +
      +
      +
    • +
    • +
      +

      isBulkModeEnabled

      +
      public boolean isBulkModeEnabled()
      +
      Check if this plugin should be run with bulk mode enabled.
      +
      +
      Returns:
      +
      true if bulk mode should be enabled for this plugin.
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginResources.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginResources.Builder.html new file mode 100644 index 0000000..56d7c86 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginResources.Builder.html @@ -0,0 +1,183 @@ + + + + +PluginResources.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class PluginResources.Builder

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.PluginResources.Builder
+
+
+
+
Enclosing class:
+
PluginResources
+
+
+
public static final class PluginResources.Builder +extends Object
+
Builder for PluginResources.
+
+
+ +
+
+ +
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginResources.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginResources.html new file mode 100644 index 0000000..19796c6 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginResources.html @@ -0,0 +1,210 @@ + + + + +PluginResources (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class PluginResources

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.PluginResources
+
+
+
+
public final class PluginResources +extends Object
+
PluginResources contains information about how many resources will be used for a plugin. The most common resources to specify are CPU and memory (RAM). +

+ CPU resources are measured in cpu units. One cpu is equivalent to 1 vCPU/Core for cloud providers and 1 hyperthread on bare-metal Intel processors. + Also, fractional requests are allowed. A plugin that asks 0.5 CPU uses half as much CPU as one that asks for 1 CPU. +

+ Memory resources are measured in Megabytes. +

+ Here is an example to set resources for a plugin: +

+     Resources.builder()
+         .maximumCpu("1.5")
+         .maximumMemory("1024")
+         .build();
+ 
+ In this example the plugin has a limit of 1 cpu and 1G of memory.
+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      maximumCpu

      +
      public Float maximumCpu()
      +
      +
    • +
    • +
      +

      maximumMemory

      +
      public Integer maximumMemory()
      +
      +
    • +
    • +
      +

      maximumWorkers

      +
      public Integer maximumWorkers()
      +
      +
    • +
    • +
      +

      builder

      +
      public static PluginResources.Builder builder()
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginType.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginType.html new file mode 100644 index 0000000..793c1d3 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/PluginType.html @@ -0,0 +1,266 @@ + + + + +PluginType (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Enum Class PluginType

+
+
java.lang.Object +
java.lang.Enum<PluginType> +
org.hansken.plugin.extraction.api.PluginType
+
+
+
+
+
All Implemented Interfaces:
+
Serializable, Comparable<PluginType>, Constable
+
+
+
public enum PluginType +extends Enum<PluginType>
+
The type of plugin, which describes its function.
+
+
+ +
+
+
    + +
  • +
    +

    Enum Constant Details

    + +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      values

      +
      public static PluginType[] values()
      +
      Returns an array containing the constants of this enum class, in +the order they are declared.
      +
      +
      Returns:
      +
      an array containing the constants of this enum class, in the order they are declared
      +
      +
      +
    • +
    • +
      +

      valueOf

      +
      public static PluginType valueOf(String name)
      +
      Returns the enum constant of this class with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this class. (Extraneous whitespace characters are +not permitted.)
      +
      +
      Parameters:
      +
      name - the name of the enum constant to be returned.
      +
      Returns:
      +
      the enum constant with the specified name
      +
      Throws:
      +
      IllegalArgumentException - if this enum class has no constant with the specified name
      +
      NullPointerException - if the argument is null
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/RandomAccessData.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/RandomAccessData.html new file mode 100644 index 0000000..23d2790 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/RandomAccessData.html @@ -0,0 +1,330 @@ + + + + +RandomAccessData (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface RandomAccessData

+
+
+
+
All Superinterfaces:
+
AutoCloseable, Closeable
+
+
+
public interface RandomAccessData +extends Closeable
+
A random access readable byte sequence. It has a fixed length and an associated data type. +

+ Note: implementations are not required to implement any kind of thread safety. + It is up to the client to ensure this if necessary.

+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    long
    + +
    +
    Get the position in the sequence.
    +
    +
    default int
    +
    read(byte[] buffer)
    +
    +
    Read bytes into the given buffer, starting at position 0 in the buffer.
    +
    +
    default int
    +
    read(byte[] buffer, + int count)
    +
    +
    Read bytes into the given buffer, starting at position 0 in the buffer.
    +
    +
    int
    +
    read(byte[] buffer, + int offset, + int count)
    +
    +
    Read data into the given buffer, starting at position offset in the buffer.
    +
    +
    default byte[]
    +
    readNBytes(int count)
    +
    +
    Read from the data sequence, returning the read bytes as an array.The data will be read from the current + position and the amount of bytes read will equal count, unless the sequence contains + fewer remaining bytes.
    +
    +
    default long
    + +
    +
    Get the number of remaining bytes in this data sequence.
    +
    +
    void
    +
    seek(long position)
    +
    +
    Move to the given absolute position in the data sequence.
    +
    +
    long
    + +
    +
    Get the number of bytes contained in this data sequence.
    +
    +
    +
    +
    +
    +

    Methods inherited from interface java.io.Closeable

    +close
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      size

      +
      long size()
      +
      Get the number of bytes contained in this data sequence.
      +
      +
      Returns:
      +
      the size in bytes
      +
      +
      +
    • +
    • +
      +

      position

      +
      long position()
      +
      Get the position in the sequence. The position will be a number in range of + 0 and size(), both inclusive. +

      + For example: if the size is equal to 16, the position can take any positive + value up to and including 16.

      +
      +
      Returns:
      +
      the current position
      +
      +
      +
    • +
    • +
      +

      remaining

      +
      default long remaining()
      +
      Get the number of remaining bytes in this data sequence.
      +
      +
      Returns:
      +
      size() - position()
      +
      +
      +
    • +
    • +
      +

      seek

      +
      void seek(long position) + throws IOException
      +
      Move to the given absolute position in the data sequence.
      +
      +
      Parameters:
      +
      position - the position to move to
      +
      Throws:
      +
      IllegalArgumentException - if given position is not in range 0 and size(), both inclusive
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    • +
      +

      read

      +
      default int read(byte[] buffer) + throws IOException
      +
      Read bytes into the given buffer, starting at position 0 in the buffer. The data will be read from the + current position and the amount of bytes copied will equal the length of the buffer, unless + the data sequence contains fewer remaining bytes. In that case, data is read until the end of the sequence.
      +
      +
      Parameters:
      +
      buffer - the buffer to read into
      +
      Returns:
      +
      the number of bytes actually read
      +
      Throws:
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    • +
      +

      read

      +
      default int read(byte[] buffer, + int count) + throws IOException
      +
      Read bytes into the given buffer, starting at position 0 in the buffer. The data will be read from the + current position and the amount of bytes copied will equal count, unless the data + sequence contains fewer remaining bytes. In that case, data is read until the end of the sequence.
      +
      +
      Parameters:
      +
      buffer - the buffer to read into
      +
      count - the amount of bytes to read
      +
      Returns:
      +
      the number of bytes actually read
      +
      Throws:
      +
      IllegalArgumentException - if count is negative or larger than the size of the buffer
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    • +
      +

      read

      +
      int read(byte[] buffer, + int offset, + int count) + throws IOException
      +
      Read data into the given buffer, starting at position offset in the buffer. The data will be read from + the current position and the amount of bytes read will equal count, unless the + sequence contains fewer remaining bytes. In that case, data is read until the end of the sequence.
      +
      +
      Parameters:
      +
      buffer - the buffer to read into
      +
      offset - the offset in the buffer from which to start writing
      +
      count - the amount of bytes to read
      +
      Returns:
      +
      the number of bytes actually read
      +
      Throws:
      +
      IllegalArgumentException - if count or offset is negative, + or if offset + count is larger than the size of the buffer
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    • +
      +

      readNBytes

      +
      default byte[] readNBytes(int count) + throws IOException
      +
      Read from the data sequence, returning the read bytes as an array.The data will be read from the current + position and the amount of bytes read will equal count, unless the sequence contains + fewer remaining bytes. In that case, data is read until the end of the sequence and a smaller array is returned, + with a length equal to the number of read bytes. +

      + Note: this method will allocate a new buffer each time it is called. It is intended for simple + cases where it is convenient to read a specified number of bytes into a byte array.

      +
      +
      Parameters:
      +
      count - the amount of bytes to read
      +
      Returns:
      +
      a buffer containing the read bytes, or an empty array if we were at the end of the stream
      +
      Throws:
      +
      IllegalArgumentException - if count is negative
      +
      IOException - when an I/O error occurs
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchOptions.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchOptions.Builder.html new file mode 100644 index 0000000..b46513b --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchOptions.Builder.html @@ -0,0 +1,244 @@ + + + + +SearchOptions.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class SearchOptions.Builder

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.SearchOptions.Builder
+
+
+
+
Enclosing class:
+
SearchOptions
+
+
+
public static class SearchOptions.Builder +extends Object
+
Builder for creating SearchOptions instances.
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      Builder

      +
      public Builder()
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      scope

      +
      public SearchOptions.Builder scope(SearchScope scope)
      +
      Sets the search scope.
      +
      +
      Parameters:
      +
      scope - the SearchScope where the search should be performed.
      +
      Returns:
      +
      this builder instance for chaining.
      +
      +
      +
    • +
    • +
      +

      offset

      +
      public SearchOptions.Builder offset(int start)
      +
      Sets the starting offset for the search results.
      +
      +
      Parameters:
      +
      start - the start offset.
      +
      Returns:
      +
      this builder instance for chaining.
      +
      +
      +
    • +
    • +
      +

      sort

      + +
      Sets the sort options for the search results.
      +
      +
      Parameters:
      +
      sort - the list of SearchSortOption.
      +
      Returns:
      +
      this builder instance for chaining.
      +
      +
      +
    • +
    • +
      +

      build

      +
      public SearchOptions build()
      +
      Builds a new SearchOptions instance with the configured values.
      +
      +
      Returns:
      +
      a new SearchOptions.
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchOptions.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchOptions.html new file mode 100644 index 0000000..efae175 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchOptions.html @@ -0,0 +1,365 @@ + + + + +SearchOptions (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Record Class SearchOptions

+
+
java.lang.Object +
java.lang.Record +
org.hansken.plugin.extraction.api.SearchOptions
+
+
+
+
+
Record Components:
+
scope - the SearchScope indicating where the search should be performed.
+
start - the starting offset of the search results.
+
sort - the list of SearchSortOption defining how the results should be sorted.
+
+
+
public record SearchOptions(SearchScope scope, int start, List<SearchSortOption> sort) +extends Record
+
Represents search options including the search scope, the start offset of the results, and sorting preferences.
+
+
+ +
+
+
    + +
  • +
    +

    Field Details

    + +
    +
  • + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      SearchOptions

      +
      public SearchOptions(SearchScope scope, + int start, + List<SearchSortOption> sort)
      +
      Creates an instance of a SearchOptions record class.
      +
      +
      Parameters:
      +
      scope - the value for the scope record component
      +
      start - the value for the start record component
      +
      sort - the value for the sort record component
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      builder

      +
      public static SearchOptions.Builder builder()
      +
      Creates a new SearchOptions.Builder instance for constructing a SearchOptions object.
      +
      +
      Returns:
      +
      a new Builder.
      +
      +
      +
    • +
    • +
      +

      toString

      +
      public final String toString()
      +
      Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components.
      +
      +
      Specified by:
      +
      toString in class Record
      +
      Returns:
      +
      a string representation of this object
      +
      +
      +
    • +
    • +
      +

      hashCode

      +
      public final int hashCode()
      +
      Returns a hash code value for this object. The value is derived from the hash code of each of the record components.
      +
      +
      Specified by:
      +
      hashCode in class Record
      +
      Returns:
      +
      a hash code value for this object
      +
      +
      +
    • +
    • +
      +

      equals

      +
      public final boolean equals(Object o)
      +
      Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. Reference components are compared with Objects::equals(Object,Object); primitive components are compared with '=='.
      +
      +
      Specified by:
      +
      equals in class Record
      +
      Parameters:
      +
      o - the object with which to compare
      +
      Returns:
      +
      true if this object is the same as the o argument; false otherwise.
      +
      +
      +
    • +
    • +
      +

      scope

      +
      public SearchScope scope()
      +
      Returns the value of the scope record component.
      +
      +
      Returns:
      +
      the value of the scope record component
      +
      +
      +
    • +
    • +
      +

      start

      +
      public int start()
      +
      Returns the value of the start record component.
      +
      +
      Returns:
      +
      the value of the start record component
      +
      +
      +
    • +
    • +
      +

      sort

      +
      public List<SearchSortOption> sort()
      +
      Returns the value of the sort record component.
      +
      +
      Returns:
      +
      the value of the sort record component
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchResult.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchResult.html new file mode 100644 index 0000000..3c8cfd8 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchResult.html @@ -0,0 +1,175 @@ + + + + +SearchResult (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface SearchResult

+
+
+
+
All Known Implementing Classes:
+
BatchSearchResult
+
+
+
public interface SearchResult
+
A SearchResult represents the result of a TraceSearcher.search(String, int). + A SearchResult contains found traces and the + total number of traces that respond to a given query. This may not be the same number, because the number + of traces returned is limited by the count provided in a TraceSearcher.search(String, int).
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    long
    + +
    +
    Returns the total number of traces matching the query.
    +
    + + +
    +
    Returns all found traces.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getTraces

      +
      Stream<SearchTrace> getTraces()
      +
      Returns all found traces.
      +
      +
      Returns:
      +
      found traces.
      +
      +
      +
    • +
    • +
      +

      getTotalHits

      +
      long getTotalHits()
      +
      Returns the total number of traces matching the query.
      +
      +
      Returns:
      +
      total number of matching traces
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchScope.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchScope.html new file mode 100644 index 0000000..8a22dc5 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchScope.html @@ -0,0 +1,244 @@ + + + + +SearchScope (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Enum Class SearchScope

+
+
java.lang.Object +
java.lang.Enum<SearchScope> +
org.hansken.plugin.extraction.api.SearchScope
+
+
+
+
+
All Implemented Interfaces:
+
Serializable, Comparable<SearchScope>, Constable
+
+
+
public enum SearchScope +extends Enum<SearchScope>
+
Scope options for scoping a search to an image or project level.
+
+
+ +
+
+
    + +
  • +
    +

    Enum Constant Details

    +
      +
    • +
      +

      IMAGE

      +
      public static final SearchScope IMAGE
      +
      Searches will be limited to the traces in the same image that is being extracted.
      +
      +
    • +
    • +
      +

      PROJECT

      +
      public static final SearchScope PROJECT
      +
      Searches will be limited to the traces in the same project that is being extracted.
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      values

      +
      public static SearchScope[] values()
      +
      Returns an array containing the constants of this enum class, in +the order they are declared.
      +
      +
      Returns:
      +
      an array containing the constants of this enum class, in the order they are declared
      +
      +
      +
    • +
    • +
      +

      valueOf

      +
      public static SearchScope valueOf(String name)
      +
      Returns the enum constant of this class with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this class. (Extraneous whitespace characters are +not permitted.)
      +
      +
      Parameters:
      +
      name - the name of the enum constant to be returned.
      +
      Returns:
      +
      the enum constant with the specified name
      +
      Throws:
      +
      IllegalArgumentException - if this enum class has no constant with the specified name
      +
      NullPointerException - if the argument is null
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.Builder.html new file mode 100644 index 0000000..21abeeb --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.Builder.html @@ -0,0 +1,226 @@ + + + + +SearchSortOption.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class SearchSortOption.Builder

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.SearchSortOption.Builder
+
+
+
+
Enclosing class:
+
SearchSortOption
+
+
+
public static class SearchSortOption.Builder +extends Object
+
Builder for creating SearchSortOption instances.
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      Builder

      +
      public Builder()
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      field

      +
      public SearchSortOption.Builder field(String field)
      +
      Sets the field to sort by.
      +
      +
      Parameters:
      +
      field - the field name to sort on.
      +
      Returns:
      +
      this builder instance for chaining.
      +
      +
      +
    • +
    • +
      +

      direction

      + +
      Sets the sort direction.
      +
      +
      Parameters:
      +
      direction - the sort direction.
      +
      Returns:
      +
      this builder instance for chaining.
      +
      +
      +
    • +
    • +
      +

      build

      +
      public SearchSortOption build()
      +
      Builds a new SearchSortOption instance with the configured values.
      +
      +
      Returns:
      +
      a new SearchSortOption.
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.Direction.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.Direction.html new file mode 100644 index 0000000..debe109 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.Direction.html @@ -0,0 +1,248 @@ + + + + +SearchSortOption.Direction (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Enum Class SearchSortOption.Direction

+
+
java.lang.Object +
java.lang.Enum<SearchSortOption.Direction> +
org.hansken.plugin.extraction.api.SearchSortOption.Direction
+
+
+
+
+
All Implemented Interfaces:
+
Serializable, Comparable<SearchSortOption.Direction>, Constable
+
+
+
Enclosing class:
+
SearchSortOption
+
+
+
public static enum SearchSortOption.Direction +extends Enum<SearchSortOption.Direction>
+
The sort direction.
+
+
+ +
+
+
    + +
  • +
    +

    Enum Constant Details

    + +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      values

      +
      public static SearchSortOption.Direction[] values()
      +
      Returns an array containing the constants of this enum class, in +the order they are declared.
      +
      +
      Returns:
      +
      an array containing the constants of this enum class, in the order they are declared
      +
      +
      +
    • +
    • +
      +

      valueOf

      +
      public static SearchSortOption.Direction valueOf(String name)
      +
      Returns the enum constant of this class with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this class. (Extraneous whitespace characters are +not permitted.)
      +
      +
      Parameters:
      +
      name - the name of the enum constant to be returned.
      +
      Returns:
      +
      the enum constant with the specified name
      +
      Throws:
      +
      IllegalArgumentException - if this enum class has no constant with the specified name
      +
      NullPointerException - if the argument is null
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.html new file mode 100644 index 0000000..0810ba5 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchSortOption.html @@ -0,0 +1,313 @@ + + + + +SearchSortOption (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Record Class SearchSortOption

+
+
java.lang.Object +
java.lang.Record +
org.hansken.plugin.extraction.api.SearchSortOption
+
+
+
+
+
Record Components:
+
field - the name of the field to sort on.
+
direction - the sort direction (ascending or descending).
+
+
+
public record SearchSortOption(String field, SearchSortOption.Direction direction) +extends Record
+
Represents a sort option used in searches, including the field to sort by and the direction.
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      SearchSortOption

      +
      public SearchSortOption(String field, + SearchSortOption.Direction direction)
      +
      Creates an instance of a SearchSortOption record class.
      +
      +
      Parameters:
      +
      field - the value for the field record component
      +
      direction - the value for the direction record component
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      builder

      +
      public static SearchSortOption.Builder builder()
      +
      Creates a new SearchSortOption.Builder instance for constructing a SearchSortOption.
      +
      +
      Returns:
      +
      a new Builder.
      +
      +
      +
    • +
    • +
      +

      toString

      +
      public final String toString()
      +
      Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components.
      +
      +
      Specified by:
      +
      toString in class Record
      +
      Returns:
      +
      a string representation of this object
      +
      +
      +
    • +
    • +
      +

      hashCode

      +
      public final int hashCode()
      +
      Returns a hash code value for this object. The value is derived from the hash code of each of the record components.
      +
      +
      Specified by:
      +
      hashCode in class Record
      +
      Returns:
      +
      a hash code value for this object
      +
      +
      +
    • +
    • +
      +

      equals

      +
      public final boolean equals(Object o)
      +
      Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. All components in this record class are compared with Objects::equals(Object,Object).
      +
      +
      Specified by:
      +
      equals in class Record
      +
      Parameters:
      +
      o - the object with which to compare
      +
      Returns:
      +
      true if this object is the same as the o argument; false otherwise.
      +
      +
      +
    • +
    • +
      +

      field

      +
      public String field()
      +
      Returns the value of the field record component.
      +
      +
      Returns:
      +
      the value of the field record component
      +
      +
      +
    • +
    • +
      +

      direction

      +
      public SearchSortOption.Direction direction()
      +
      Returns the value of the direction record component.
      +
      +
      Returns:
      +
      the value of the direction record component
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchTrace.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchTrace.html new file mode 100644 index 0000000..842d47d --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/SearchTrace.html @@ -0,0 +1,181 @@ + + + + +SearchTrace (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface SearchTrace

+
+
+
+
All Superinterfaces:
+
ImmutableTrace
+
+
+
public interface SearchTrace +extends ImmutableTrace
+
A trace contains information about processed data. A trace should conform to the trace model defined by Hansken. + Unlike a Trace, the SearchTrace contains information about the searched trace. It is able to + directly retrieve all the data contexts belonging to a searched trace. When data type is known a + RandomAccessData can be retrieved directly.
+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getData

      +
      RandomAccessData getData(String type)
      +
      Returns a RandomAccessData for a specific trace data type.
      +
      +
      Parameters:
      +
      type - the data type of the data stream to be retrieved
      +
      Returns:
      +
      the data stream
      +
      +
      +
    • +
    • +
      +

      getDataTypes

      +
      List<String> getDataTypes()
      +
      Returns all available data types for this search trace.
      +
      +
      Returns:
      +
      available data types
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.Tracelet.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.Tracelet.html new file mode 100644 index 0000000..5b2c49f --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.Tracelet.html @@ -0,0 +1,196 @@ + + + + +Trace.Tracelet (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class Trace.Tracelet

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.Trace.Tracelet
+
+
+
+
Enclosing interface:
+
Trace
+
+
+
public static class Trace.Tracelet +extends Object
+
a Tracelet represents tracedata that can be present multiple times within a trace. + The API doesn't specify the cardinality , but the implementation is limited to + cardinality Few.
+
+
+ +
+
+ +
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.TraceletBuilder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.TraceletBuilder.html new file mode 100644 index 0000000..1484e59 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.TraceletBuilder.html @@ -0,0 +1,198 @@ + + + + +Trace.TraceletBuilder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface Trace.TraceletBuilder

+
+
+
+
Enclosing interface:
+
Trace
+
+
+
public static interface Trace.TraceletBuilder
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    <T> T
    +
    get(String name)
    +
    +
    Returns the currently set value (if any) for the requested property.
    +
    + + +
    +
    Returns the type of this tracelet.
    +
    + +
    set(String name, + Object value)
    +
    +
    Set a property on this tracelet with a given value.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      set

      +
      Trace.TraceletBuilder set(String name, + Object value)
      +
      Set a property on this tracelet with a given value.
      +
      +
      Parameters:
      +
      name - the name of the property to set
      +
      value - the value to set
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if the property or value of the property is invalid as per the trace model
      +
      +
      +
    • +
    • +
      +

      get

      +
      <T> T get(String name)
      +
      Returns the currently set value (if any) for the requested property.
      +
      +
      Type Parameters:
      +
      T - the type of the value to get
      +
      Parameters:
      +
      name - property name
      +
      Returns:
      +
      the currently set value of this property
      +
      +
      +
    • +
    • +
      +

      getType

      +
      String getType()
      +
      Returns the type of this tracelet.
      +
      +
      Returns:
      +
      the tracelet type
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.TraceletProperty.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.TraceletProperty.html new file mode 100644 index 0000000..f90901d --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.TraceletProperty.html @@ -0,0 +1,194 @@ + + + + +Trace.TraceletProperty (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class Trace.TraceletProperty

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.Trace.TraceletProperty
+
+
+
+
Enclosing interface:
+
Trace
+
+
+
public static class Trace.TraceletProperty +extends Object
+
a TraceletProperty is a property of a Tracelet.
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      TraceletProperty

      +
      public TraceletProperty(String name, + Object value)
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getName

      +
      public String getName()
      +
      +
    • +
    • +
      +

      getValue

      +
      public Object getValue()
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.html new file mode 100644 index 0000000..8eb67c7 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Trace.html @@ -0,0 +1,506 @@ + + + + +Trace (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface Trace

+
+
+
+
All Superinterfaces:
+
ImmutableTrace
+
+
+
public interface Trace +extends ImmutableTrace
+
A trace contains information about processed data. A trace should conform to the trace model defined by Hansken. +

+ A trace can have multiple types (e.g. file or chat). For these types, the trace can contain a set of properties and + associated values. A trace can be associated with a set of data sequences. + During extraction, an extraction plugin may receive a currently processed trace + and accompanying data sequence. +

+ Implementers of a plugin should ensure that setting a property on a trace is valid as per the trace model + which is defined for the traces generated by the plugin. +

+ Note: implementations are not required to implement any kind of thread safety. + It is up to the client to ensure this if necessary.

+
+
See Also:
+
+ +
+
+
+
+ +
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      addType

      +
      Trace addType(String type)
      +
      Add a type to this trace (for example: "file"). If this trace already had given type, + nothing changes.
      +
      +
      Parameters:
      +
      type - the type to add
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      set

      +
      Trace set(String name, + Object value)
      +
      Set a property on this trace with a given value.
      +
      +
      Parameters:
      +
      name - the name of the property to set
      +
      value - the value of the property
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if the property or value of the property is invalid as per the trace model
      +
      +
      +
    • +
    • +
      +

      addTracelet

      +
      default Trace addTracelet(String type, + Consumer<Trace.TraceletBuilder> callback)
      +
      Add a tracelet to the trace. +

      + Example usage: +

      
      +     trace.addTracelet("prediction", tracelet -> tracelet
      +         .set("type", "type")
      +         .set("model", "model")
      +         .set("label", "label")
      +         .set("confidence", .50));
      +     );
      + }
      +
      +
      Parameters:
      +
      type - the type of tracelet to add
      +
      callback - callback to set the tracelet properties
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      addTracelet

      +
      @Deprecated +Trace addTracelet(Trace.Tracelet tracelet)
      +
      Deprecated. +
      use addTracelet(type, callback)
      +
      +
      Add a tracelet to the trace.
      +
      +
      Parameters:
      +
      tracelet - the name and properties of the Tracelet
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      getNewTracelets

      +
      List<Trace.Tracelet> getNewTracelets()
      +
      Retrieve the tracelets that were added by the plugin. +

      + Note that this does not return the tracelets that were already present on the trace prior to the execution + of the plugin.

      +
      +
      Returns:
      +
      the list of tracelets that were added by the plugin.
      +
      +
      +
    • +
    • +
      +

      setData

      +
      Trace setData(String dataType, + DataWriter writer) + throws IOException
      +
      Add a data stream of a given type to this Trace (for example, 'raw' or 'html'). + A trace can only have a single data stream for each data type. A callback function can be passed + which receives an OutputStream to write the data to. +

      + Note: the received output stream should not be closed by the user. It should + also only be used within the scope of the callback, other usage may be guarded against or otherwise + result in undefined behaviour. +

      + Example usage: +

      
      +     final PacketSequencer sequencer = ...;
      +     final RandomAccessData input = dataContext.data();
      +
      +     trace.setData("packets", data -> {
      +         sequencer.process(input).forEach(packet -> {
      +             data.write(packet);
      +         });
      +     });
      + 
      +
      +
      Parameters:
      +
      dataType - the type of the data stream to add
      +
      writer - callback that receives the stream to write to as input
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if this trace already had an associated data stream of given type
      +
      IOException - when the given callback throws one
      +
      +
      +
    • +
    • +
      +

      setData

      +
      default Trace setData(String dataType, + DataTransformation... transformations)
      +
      Set a series of data transformations for a specific dataType. + + Transformations are pointers to actual raw data. They describe how data can be obtained by reading on certain + positions, using decryption, or combinations of these. The benefit of using Transformations is that they take up + less space than the actual data.
      +
      +
      Parameters:
      +
      dataType - the type of the datastream
      +
      transformations - the data transformations
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      setData

      +
      Trace setData(String dataType, + List<DataTransformation> transformation)
      +
      Set a series of data transformations for a specific dataType.
      +
      +
      Parameters:
      +
      dataType - the type of the datastream
      +
      transformation - the data transformations
      +
      Returns:
      +
      this
      +
      +
      +
    • +
    • +
      +

      setData

      +
      default Trace setData(String dataType, + InputStream stream) + throws IOException
      +
      Add a data stream of a given type to this Trace (for example, 'raw' or 'html'). + A trace can only have a single data stream for each data type. +

      + The given InputStream will not be closed by this method. +

      + Example usage: +

      
      +     final ThumbnailDetector detector = ...;
      +     final RandomAccessData input = dataContext.data();
      +     final InputStream thumbnails = detector.detect(input);
      +     trace.setData("preview", thumbnails);
      + 
      +
      +
      Parameters:
      +
      dataType - the type of the data stream to add
      +
      stream - the data stream itself
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalArgumentException - if this trace already had an associated data stream of given type
      +
      IOException - when an I/O error occurs while reading the input
      +
      +
      +
    • +
    • +
      +

      addValue

      +
      default <T> void addValue(String property, + T value)
      +
      Adds a value to a property that's a List. + This method will create a new list if the property has no value yet.
      +
      +
      Type Parameters:
      +
      T - the type of the value to set
      +
      Parameters:
      +
      property - the name of the property to add the value to
      +
      value - the value to add to the list property
      +
      +
      +
    • +
    • +
      +

      newChild

      +
      Trace newChild(String name, + ThrowingConsumer<Trace,IOException> enrichChildCallback) + throws IOException
      +
      Create and store new child trace of this trace. A callback function + can be passed in order to enrich the created child trace (which will have no types + or properties set yet), or even recursively add new children under it. After the + trace goes out of scope of the callback, it can no longer be updated. +

      + As an example, say we have a Node type with the following API +

      
      +   interface Node {
      +     String name();
      +     List<Node> children();
      +   }
      +
      + A recursive function for creating traces from a node, where the initial node + should be mapped to a single child under the trace being processed: +
      
      +     public void process(final Trace trace, final DataContext dataContext) {
      +         final Node node = createNode(); // get the node from somewhere
      +         createTree(node, trace);
      +     }
      +
      +     void createTree(final Node childNode, final Trace parentTrace) {
      +         parentTrace.newChild(childNode.name(), child -> {
      +             // set information from child node on child trace
      +             child.type("file").set("file.name", "password.txt");
      +             // recursively create more children
      +             childNode.children().forEach(node -> {
      +                 createTree(node, child);
      +             });
      +         });
      +     }
      + 
      +
      +
      Parameters:
      +
      name - the name of the child
      +
      enrichChildCallback - callback that gets the new child trace as input
      +
      Returns:
      +
      this
      +
      Throws:
      +
      IllegalStateException - if the trace was not yet saved
      +
      IOException - when the given callback throws one
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TraceSearcher.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TraceSearcher.html new file mode 100644 index 0000000..bf30a7b --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TraceSearcher.html @@ -0,0 +1,312 @@ + + + + +TraceSearcher (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface TraceSearcher

+
+
+
+
public interface TraceSearcher
+
Allows searching for traces within the scope of the process function.
+
+
+
    + +
  • +
    +

    Field Summary

    +
    Fields
    +
    +
    Modifier and Type
    +
    Field
    +
    Description
    +
    static final int
    + +
     
    +
    +
    +
  • + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    default SearchResult
    +
    search(String query)
    +
    +
    Searches in Hansken for Traces matching provided query, scoped to the image under extraction.
    +
    +
    default SearchResult
    +
    search(String query, + int count)
    +
    +
    Searches in Hansken for Traces matching provided query, scoped to the image under extraction.
    +
    +
    default SearchResult
    +
    search(String query, + int count, + SearchOptions options)
    +
    +
    Searches in Hansken for Traces matching provided query.
    +
    + +
    search(String query, + int count, + SearchScope scope, + int start, + List<SearchSortOption> sort)
    +
    +
    Searches in Hansken for Traces matching provided query.
    +
    +
    default SearchResult
    +
    search(String query, + SearchOptions options)
    +
    +
    Searches in Hansken for Traces matching provided query.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Field Details

    +
      +
    • +
      +

      ALL_SEARCH_RESULTS

      +
      static final int ALL_SEARCH_RESULTS
      +
      +
      See Also:
      +
      + +
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      search

      +
      default SearchResult search(String query) + throws InterruptedException, +ExecutionException
      +
      Searches in Hansken for Traces matching provided query, scoped to the image under extraction.
      +
      +
      Parameters:
      +
      query - Search query to match traces. This is an HQL query.
      +
      Returns:
      +
      SearchResult containing traces matching the provided query.
      +
      Throws:
      +
      InterruptedException - if a thread searching for traces is interrupted.
      +
      ExecutionException - if searching for traces is throws an exception.
      +
      +
      +
    • +
    • +
      +

      search

      +
      default SearchResult search(String query, + int count) + throws InterruptedException, +ExecutionException
      +
      Searches in Hansken for Traces matching provided query, scoped to the image under extraction.
      +
      +
      Parameters:
      +
      query - Search query to match traces. This is an HQL query.
      +
      count - Maximum number of traces to return.
      +
      Returns:
      +
      SearchResult containing traces matching the provided query.
      +
      Throws:
      +
      InterruptedException - if a thread searching for traces is interrupted.
      +
      ExecutionException - if searching for traces is throws an exception.
      +
      +
      +
    • +
    • +
      +

      search

      +
      default SearchResult search(String query, + SearchOptions options) + throws InterruptedException, +ExecutionException
      +
      Searches in Hansken for Traces matching provided query.
      +
      +
      Parameters:
      +
      query - Search query to match traces. This is an HQL query.
      +
      options - SearchOptions object containing various search options.
      +
      Returns:
      +
      SearchResult containing traces matching the provided query.
      +
      Throws:
      +
      InterruptedException - if a thread searching for traces is interrupted.
      +
      ExecutionException - if searching for traces is throws an exception.
      +
      +
      +
    • +
    • +
      +

      search

      +
      default SearchResult search(String query, + int count, + SearchOptions options) + throws InterruptedException, +ExecutionException
      +
      Searches in Hansken for Traces matching provided query.
      +
      +
      Parameters:
      +
      query - Search query to match traces. This is an HQL query.
      +
      count - Maximum number of traces to return.
      +
      options - SearchOptions object containing various search options.
      +
      Returns:
      +
      SearchResult containing traces matching the provided query.
      +
      Throws:
      +
      InterruptedException - if a thread searching for traces is interrupted.
      +
      ExecutionException - if searching for traces is throws an exception.
      +
      +
      +
    • +
    • +
      +

      search

      +
      SearchResult search(String query, + int count, + SearchScope scope, + int start, + List<SearchSortOption> sort) + throws InterruptedException, +ExecutionException
      +
      Searches in Hansken for Traces matching provided query.
      +
      +
      Parameters:
      +
      query - Search query to match traces. This is an HQL query.
      +
      count - Maximum number of traces to return.
      +
      scope - Scope the search to image or project level.
      +
      start - Starting index of traces.
      +
      sort - Field to sort on.
      +
      Returns:
      +
      SearchResult containing traces matching the provided query.
      +
      Throws:
      +
      InterruptedException - if a thread searching for traces is interrupted.
      +
      ExecutionException - if searching for traces is throws an exception.
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TransformerArgument.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TransformerArgument.html new file mode 100644 index 0000000..ecfea05 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TransformerArgument.html @@ -0,0 +1,197 @@ + + + + +TransformerArgument (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class TransformerArgument

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.TransformerArgument
+
+
+
+
public class TransformerArgument +extends Object
+
An argument or return value that can be passed to or returned from a Transformer.
+
+
Author:
+
Netherlands Forensic Institute
+
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      TransformerArgument

      +
      public TransformerArgument(Object argument)
      +
      Takes an Object and validates if it is of an acceptable transformer argument or return type.
      +
      +
      Parameters:
      +
      argument - The object that is to be passed to or returned from a transformer.
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getArgument

      +
      public Object getArgument()
      +
      Retrieves the Transformer argument as an Object.
      +
      +
      Returns:
      +
      The Transformer argument as an Object.
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TransformerLabel.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TransformerLabel.html new file mode 100644 index 0000000..fa22e08 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/TransformerLabel.html @@ -0,0 +1,233 @@ + + + + +TransformerLabel (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class TransformerLabel

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.TransformerLabel
+
+
+
+
public class TransformerLabel +extends Object
+
Description of a transform method of a plugin. + The transform method is a method, specified by method name, of a Transformer capable plugin + that transforms input to output of a specified type (returnType)
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      TransformerLabel

      +
      public TransformerLabel(String methodName, + Map<String,String> parameters, + String returnType)
      +
      Plain constructor that constructs a TransformerLabel.
      +
      +
      Parameters:
      +
      methodName - The method name of the Transformer.
      +
      parameters - The parameters of the Transformer as a name, type mapping. Currently only str is supported.
      +
      returnType - The return type of the Transformer method. Currently only vector is supported.
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getMethodName

      +
      public String getMethodName()
      +
      Retrieves the method name of the transformer.
      +
      +
      Returns:
      +
      The method name of the transformer.
      +
      +
      +
    • +
    • +
      +

      getParameters

      +
      public Map<String,String> getParameters()
      +
      Retrieves the parameters of the transformer method as a name, type mapping.
      +
      +
      Returns:
      +
      The parameters of the transformer method.
      +
      +
      +
    • +
    • +
      +

      getReturnType

      +
      public String getReturnType()
      +
      Retrieves the return type of the transformer method. Currently only vector is supported.
      +
      +
      Returns:
      +
      The return type of the transformer method.
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Vector.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Vector.html new file mode 100644 index 0000000..2a54def --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/Vector.html @@ -0,0 +1,329 @@ + + + + +Vector (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class Vector

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.Vector
+
+
+
+
public final class Vector +extends Object
+
An opaque vector of floating point values.
+
+
Author:
+
Netherlands Forensic Institute
+
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    byte[]
    + +
    +
    Returns the binary representation of the Vector.
    +
    +
    static Vector
    +
    asVector(byte[] bytes)
    +
    +
    Creates a vector from a binary representation.
    +
    +
    boolean
    + +
     
    +
    int
    + +
     
    +
    static Vector
    +
    of(float... values)
    +
    +
    Creates a Vector from an array of floating point values.
    +
    +
    static Vector
    +
    of(Collection<Float> values)
    +
    +
    Creates a Vector from a collection of numbers.
    +
    +
    static Vector
    +
    ofBase64(String base64)
    +
    +
    Creates a Vector from a base64 encoded string.
    +
    +
    int
    + +
    +
    Returns the number of dimensions of the vector.
    +
    + + +
    +
    Returns a base64 encoded string of the Vector.
    +
    + + +
     
    +
    float[]
    + +
    +
    Returns the values of the Vector as an array of floats.
    +
    +
    +
    +
    +
    +

    Methods inherited from class java.lang.Object

    +clone, finalize, getClass, notify, notifyAll, wait, wait, wait
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      of

      +
      public static Vector of(float... values)
      +
      Creates a Vector from an array of floating point values.
      +
      +
      Parameters:
      +
      values - the values to use
      +
      Returns:
      +
      a vector
      +
      +
      +
    • +
    • +
      +

      of

      +
      public static Vector of(Collection<Float> values)
      +
      Creates a Vector from a collection of numbers. + Note that all numbers are converted to floats internally, so loss of precision may occur when doubles or longs are offered.
      +
      +
      Parameters:
      +
      values - the values to use
      +
      Returns:
      +
      a vector
      +
      +
      +
    • +
    • +
      +

      ofBase64

      +
      public static Vector ofBase64(String base64)
      +
      Creates a Vector from a base64 encoded string.
      +
      +
      Parameters:
      +
      base64 - the base64 encoded string to use
      +
      Returns:
      +
      a vector
      +
      +
      +
    • +
    • +
      +

      asVector

      +
      public static Vector asVector(byte[] bytes)
      +
      Creates a vector from a binary representation. + Vector.asBinary() can be used to obtain a binary representation. + Note that this directly sets the internal state of the Vector, use {code asVector(bytes.clone()} to store a safe, immutable copy.
      +
      +
      Parameters:
      +
      bytes - the bytes to convert to a vector.
      +
      Returns:
      +
      a vector
      +
      +
      +
    • +
    • +
      +

      asBinary

      +
      public byte[] asBinary()
      +
      Returns the binary representation of the Vector. + Vector.asVector(byte[]) can be used to convert the binary representation back to the original vector. + The format of the returned bytes is a sequence of the floating point values of the vector, stored as big-endian IEEE 754 encoded 32-bit floating point values. + Note that this exposes the internal state of the Vector, use {code asBinary().clone()} to obtain a safely mutable copy.
      +
      +
      Returns:
      +
      a binary representation of the vector.
      +
      +
      +
    • +
    • +
      +

      size

      +
      public int size()
      +
      Returns the number of dimensions of the vector.
      +
      +
      Returns:
      +
      the number of dimensions of the vector.
      +
      +
      +
    • +
    • +
      +

      values

      +
      public float[] values()
      +
      Returns the values of the Vector as an array of floats.
      +
      +
      Returns:
      +
      the values of the Vector as an array of floats.
      +
      +
      +
    • +
    • +
      +

      toBase64

      +
      public String toBase64()
      +
      Returns a base64 encoded string of the Vector. + Vector.ofBase64() can be used to convert the return base64 encoded string back to a Vector.
      +
      +
      Returns:
      +
      a base64 encoded string of the Vector.
      +
      +
      +
    • +
    • +
      +

      toString

      +
      public String toString()
      +
      +
      Overrides:
      +
      toString in class Object
      +
      +
      +
    • +
    • +
      +

      hashCode

      +
      public int hashCode()
      +
      +
      Overrides:
      +
      hashCode in class Object
      +
      +
      +
    • +
    • +
      +

      equals

      +
      public boolean equals(Object obj)
      +
      +
      Overrides:
      +
      equals in class Object
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Author.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Author.Builder.html new file mode 100644 index 0000000..7b6a947 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Author.Builder.html @@ -0,0 +1,107 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.Author.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.Author.Builder

+
+
Packages that use Author.Builder
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Author.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Author.html new file mode 100644 index 0000000..b56e8fa --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Author.html @@ -0,0 +1,108 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.Author (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.Author

+
+
Packages that use Author
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/BaseExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/BaseExtractionPlugin.html new file mode 100644 index 0000000..0d979b5 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/BaseExtractionPlugin.html @@ -0,0 +1,124 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.BaseExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.BaseExtractionPlugin

+
+
Packages that use BaseExtractionPlugin
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/BatchSearchResult.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/BatchSearchResult.html new file mode 100644 index 0000000..ab077f7 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/BatchSearchResult.html @@ -0,0 +1,63 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.BatchSearchResult (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.BatchSearchResult

+
+No usage of org.hansken.plugin.extraction.api.BatchSearchResult
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DataContext.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DataContext.html new file mode 100644 index 0000000..91742c2 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DataContext.html @@ -0,0 +1,109 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.DataContext (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.DataContext

+
+
Packages that use DataContext
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DataWriter.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DataWriter.html new file mode 100644 index 0000000..2d787fb --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DataWriter.html @@ -0,0 +1,93 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.DataWriter (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.DataWriter

+
+
Packages that use DataWriter
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DeferredExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DeferredExtractionPlugin.html new file mode 100644 index 0000000..2f5326e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DeferredExtractionPlugin.html @@ -0,0 +1,92 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.DeferredExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.DeferredExtractionPlugin

+
+
Packages that use DeferredExtractionPlugin
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DeferredMetaExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DeferredMetaExtractionPlugin.html new file mode 100644 index 0000000..d144ee7 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/DeferredMetaExtractionPlugin.html @@ -0,0 +1,63 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin

+
+No usage of org.hansken.plugin.extraction.api.DeferredMetaExtractionPlugin
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/ExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/ExtractionPlugin.html new file mode 100644 index 0000000..0661ab7 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/ExtractionPlugin.html @@ -0,0 +1,92 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.ExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.ExtractionPlugin

+
+
Packages that use ExtractionPlugin
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/ImmutableTrace.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/ImmutableTrace.html new file mode 100644 index 0000000..55f6161 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/ImmutableTrace.html @@ -0,0 +1,97 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.ImmutableTrace (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.ImmutableTrace

+
+
Packages that use ImmutableTrace
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/LatLong.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/LatLong.html new file mode 100644 index 0000000..967b799 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/LatLong.html @@ -0,0 +1,97 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.LatLong (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.LatLong

+
+
Packages that use LatLong
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/MaturityLevel.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/MaturityLevel.html new file mode 100644 index 0000000..630746b --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/MaturityLevel.html @@ -0,0 +1,114 @@ + + + + +Uses of Enum Class org.hansken.plugin.extraction.api.MaturityLevel (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Enum Class
org.hansken.plugin.extraction.api.MaturityLevel

+
+
Packages that use MaturityLevel
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/MetaExtractionPlugin.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/MetaExtractionPlugin.html new file mode 100644 index 0000000..20301d8 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/MetaExtractionPlugin.html @@ -0,0 +1,63 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.MetaExtractionPlugin (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.MetaExtractionPlugin

+
+No usage of org.hansken.plugin.extraction.api.MetaExtractionPlugin
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginId.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginId.html new file mode 100644 index 0000000..ed5c764 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginId.html @@ -0,0 +1,103 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.PluginId (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.PluginId

+
+
Packages that use PluginId
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginInfo.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginInfo.Builder.html new file mode 100644 index 0000000..b5dc1e1 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginInfo.Builder.html @@ -0,0 +1,171 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.PluginInfo.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.PluginInfo.Builder

+
+
Packages that use PluginInfo.Builder
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginInfo.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginInfo.html new file mode 100644 index 0000000..d108d9e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginInfo.html @@ -0,0 +1,98 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.PluginInfo (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.PluginInfo

+
+
Packages that use PluginInfo
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginResources.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginResources.Builder.html new file mode 100644 index 0000000..d77cfa0 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginResources.Builder.html @@ -0,0 +1,99 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.PluginResources.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.PluginResources.Builder

+
+
Packages that use PluginResources.Builder
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginResources.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginResources.html new file mode 100644 index 0000000..1fc089e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginResources.html @@ -0,0 +1,106 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.PluginResources (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.PluginResources

+
+
Packages that use PluginResources
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginType.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginType.html new file mode 100644 index 0000000..95c5cee --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/PluginType.html @@ -0,0 +1,114 @@ + + + + +Uses of Enum Class org.hansken.plugin.extraction.api.PluginType (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Enum Class
org.hansken.plugin.extraction.api.PluginType

+
+
Packages that use PluginType
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/RandomAccessData.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/RandomAccessData.html new file mode 100644 index 0000000..afd0d44 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/RandomAccessData.html @@ -0,0 +1,97 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.RandomAccessData (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.RandomAccessData

+
+
Packages that use RandomAccessData
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchOptions.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchOptions.Builder.html new file mode 100644 index 0000000..b2f202f --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchOptions.Builder.html @@ -0,0 +1,107 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.SearchOptions.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.SearchOptions.Builder

+
+
Packages that use SearchOptions.Builder
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchOptions.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchOptions.html new file mode 100644 index 0000000..7d2a4b3 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchOptions.html @@ -0,0 +1,122 @@ + + + + +Uses of Record Class org.hansken.plugin.extraction.api.SearchOptions (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Record Class
org.hansken.plugin.extraction.api.SearchOptions

+
+
Packages that use SearchOptions
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchResult.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchResult.html new file mode 100644 index 0000000..6408bd5 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchResult.html @@ -0,0 +1,132 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.SearchResult (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.SearchResult

+
+
Packages that use SearchResult
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchScope.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchScope.html new file mode 100644 index 0000000..4cf4708 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchScope.html @@ -0,0 +1,136 @@ + + + + +Uses of Enum Class org.hansken.plugin.extraction.api.SearchScope (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Enum Class
org.hansken.plugin.extraction.api.SearchScope

+
+
Packages that use SearchScope
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.Builder.html new file mode 100644 index 0000000..5930d74 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.Builder.html @@ -0,0 +1,102 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.SearchSortOption.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.SearchSortOption.Builder

+
+
Packages that use SearchSortOption.Builder
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.Direction.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.Direction.html new file mode 100644 index 0000000..a48cba7 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.Direction.html @@ -0,0 +1,126 @@ + + + + +Uses of Enum Class org.hansken.plugin.extraction.api.SearchSortOption.Direction (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Enum Class
org.hansken.plugin.extraction.api.SearchSortOption.Direction

+
+
Packages that use SearchSortOption.Direction
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.html new file mode 100644 index 0000000..2db41a4 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchSortOption.html @@ -0,0 +1,136 @@ + + + + +Uses of Record Class org.hansken.plugin.extraction.api.SearchSortOption (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Record Class
org.hansken.plugin.extraction.api.SearchSortOption

+
+
Packages that use SearchSortOption
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchTrace.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchTrace.html new file mode 100644 index 0000000..c24589b --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/SearchTrace.html @@ -0,0 +1,106 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.SearchTrace (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.SearchTrace

+
+
Packages that use SearchTrace
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.Tracelet.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.Tracelet.html new file mode 100644 index 0000000..d5e862c --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.Tracelet.html @@ -0,0 +1,105 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.Trace.Tracelet (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.Trace.Tracelet

+
+
Packages that use Trace.Tracelet
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.TraceletBuilder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.TraceletBuilder.html new file mode 100644 index 0000000..a51b69e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.TraceletBuilder.html @@ -0,0 +1,105 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.Trace.TraceletBuilder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.Trace.TraceletBuilder

+
+
Packages that use Trace.TraceletBuilder
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.TraceletProperty.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.TraceletProperty.html new file mode 100644 index 0000000..2d12074 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.TraceletProperty.html @@ -0,0 +1,100 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.Trace.TraceletProperty (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.Trace.TraceletProperty

+
+
Packages that use Trace.TraceletProperty
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.html new file mode 100644 index 0000000..7de068d --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Trace.html @@ -0,0 +1,192 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.Trace (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.Trace

+
+
Packages that use Trace
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TraceSearcher.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TraceSearcher.html new file mode 100644 index 0000000..c1878a1 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TraceSearcher.html @@ -0,0 +1,105 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.TraceSearcher (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.TraceSearcher

+
+
Packages that use TraceSearcher
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TransformerArgument.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TransformerArgument.html new file mode 100644 index 0000000..e4b0bba --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TransformerArgument.html @@ -0,0 +1,63 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.TransformerArgument (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.TransformerArgument

+
+No usage of org.hansken.plugin.extraction.api.TransformerArgument
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TransformerLabel.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TransformerLabel.html new file mode 100644 index 0000000..4525fd7 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/TransformerLabel.html @@ -0,0 +1,103 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.TransformerLabel (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.TransformerLabel

+
+
Packages that use TransformerLabel
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Vector.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Vector.html new file mode 100644 index 0000000..932fc6c --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/class-use/Vector.html @@ -0,0 +1,107 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.Vector (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.Vector

+
+
Packages that use Vector
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-summary.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-summary.html new file mode 100644 index 0000000..5a68b49 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-summary.html @@ -0,0 +1,268 @@ + + + + +org.hansken.plugin.extraction.api (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Package org.hansken.plugin.extraction.api

+
+
+
package org.hansken.plugin.extraction.api
+
+
This is the API of the Extraction Plugins SDK. +

+ + This module defines the interfaces used for the Extraction Plugin SDK. +

+
+
Since:
+
0.0.1
+
Author:
+
Netherlands Forensic Institute
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-tree.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-tree.html new file mode 100644 index 0000000..9f77ae0 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-tree.html @@ -0,0 +1,157 @@ + + + + +org.hansken.plugin.extraction.api Class Hierarchy (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Hierarchy For Package org.hansken.plugin.extraction.api

+
+Package Hierarchies: + +
+

Class Hierarchy

+ +
+
+

Interface Hierarchy

+ +
+
+

Enum Class Hierarchy

+ +
+
+

Record Class Hierarchy

+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-use.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-use.html new file mode 100644 index 0000000..9d2a255 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/package-use.html @@ -0,0 +1,213 @@ + + + + +Uses of Package org.hansken.plugin.extraction.api (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Package
org.hansken.plugin.extraction.api

+
+ +
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/DataRange.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/DataRange.html new file mode 100644 index 0000000..53b80a3 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/DataRange.html @@ -0,0 +1,220 @@ + + + + +DataRange (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ + +
java.lang.Object +
org.hansken.plugin.extraction.api.transformations.DataRange
+
+
+
+
public class DataRange +extends Object
+
A DataRange describes a range of bytes with an offset and length.
+
+
Author:
+
Netherlands Forensic Institute
+
+
+
+ +
+
+
    + +
  • +
    +

    Constructor Details

    +
      +
    • +
      +

      DataRange

      +
      public DataRange(long offset, + long length)
      +
      Creates a DataRange which describes a range of bytes.
      +
      +
      Parameters:
      +
      offset - the starting point of the data
      +
      length - the size of the data
      +
      +
      +
    • +
    +
    +
  • + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      getOffset

      +
      public long getOffset()
      +
      +
    • +
    • +
      +

      getLength

      +
      public long getLength()
      +
      +
    • +
    • +
      +

      setOffset

      +
      public void setOffset(long offset)
      +
      +
    • +
    • +
      +

      setLength

      +
      public void setLength(long length)
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/DataTransformation.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/DataTransformation.html new file mode 100644 index 0000000..33a0bfe --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/DataTransformation.html @@ -0,0 +1,115 @@ + + + + +DataTransformation (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface DataTransformation

+
+
+
+
All Known Implementing Classes:
+
RangedDataTransformation
+
+
+
public interface DataTransformation
+
A data transformation that the Extraction Plugin can write to a Trace using + Trace.setData(String, DataTransformation...). + + Currently only RangedDataTransformations are supported.
+
+
Author:
+
Netherlands Forensic Institute
+
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/RangedDataTransformation.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/RangedDataTransformation.Builder.html new file mode 100644 index 0000000..d22efeb --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/RangedDataTransformation.Builder.html @@ -0,0 +1,213 @@ + + + + +RangedDataTransformation.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class RangedDataTransformation.Builder

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder
+
+
+
+
Enclosing class:
+
RangedDataTransformation
+
+
+
public static class RangedDataTransformation.Builder +extends Object
+
Builder for creating RangedDataTransformation using a syntax that is sometimes shorter than using + constructors.
+
+
+ +
+
+ +
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/RangedDataTransformation.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/RangedDataTransformation.html new file mode 100644 index 0000000..5e20c50 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/RangedDataTransformation.html @@ -0,0 +1,253 @@ + + + + +RangedDataTransformation (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class RangedDataTransformation

+
+
java.lang.Object +
org.hansken.plugin.extraction.api.transformations.RangedDataTransformation
+
+
+
+
All Implemented Interfaces:
+
DataTransformation
+
+
+
public class RangedDataTransformation +extends Object +implements DataTransformation
+
A RangedDataTransformation describes a data transformation consisting of a list of DataRanges.
+
+
Author:
+
Netherlands Forensic Institute
+
+
+
+ +
+
+ +
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/DataRange.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/DataRange.html new file mode 100644 index 0000000..3fe8a8e --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/DataRange.html @@ -0,0 +1,133 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.transformations.DataRange (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.transformations.DataRange

+
+
Packages that use DataRange
+
+
Package
+
Description
+ +
+
This package contains the Data Transformations.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/DataTransformation.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/DataTransformation.html new file mode 100644 index 0000000..a257d08 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/DataTransformation.html @@ -0,0 +1,125 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.api.transformations.DataTransformation (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.api.transformations.DataTransformation

+
+
Packages that use DataTransformation
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+ +
+
This package contains the Data Transformations.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/RangedDataTransformation.Builder.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/RangedDataTransformation.Builder.html new file mode 100644 index 0000000..7790ed3 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/RangedDataTransformation.Builder.html @@ -0,0 +1,102 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.transformations.RangedDataTransformation.Builder

+
+ +
+
Package
+
Description
+ +
+
This package contains the Data Transformations.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/RangedDataTransformation.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/RangedDataTransformation.html new file mode 100644 index 0000000..d23a851 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/class-use/RangedDataTransformation.html @@ -0,0 +1,90 @@ + + + + +Uses of Class org.hansken.plugin.extraction.api.transformations.RangedDataTransformation (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.api.transformations.RangedDataTransformation

+
+
Packages that use RangedDataTransformation
+
+
Package
+
Description
+ +
+
This package contains the Data Transformations.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-summary.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-summary.html new file mode 100644 index 0000000..e4aaf6d --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-summary.html @@ -0,0 +1,141 @@ + + + + +org.hansken.plugin.extraction.api.transformations (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Package org.hansken.plugin.extraction.api.transformations

+
+
+
package org.hansken.plugin.extraction.api.transformations
+
+
This package contains the Data Transformations. +

+ + Currently only the RangedDataTransformation is supported. +

+
+
Since:
+
0.3.0
+
Author:
+
Netherlands Forensic Institute
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-tree.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-tree.html new file mode 100644 index 0000000..06f64a4 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-tree.html @@ -0,0 +1,85 @@ + + + + +org.hansken.plugin.extraction.api.transformations Class Hierarchy (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Hierarchy For Package org.hansken.plugin.extraction.api.transformations

+
+Package Hierarchies: + +
+

Class Hierarchy

+ +
+
+

Interface Hierarchy

+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-use.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-use.html new file mode 100644 index 0000000..b5902fb --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/api/transformations/package-use.html @@ -0,0 +1,121 @@ + + + + +Uses of Package org.hansken.plugin.extraction.api.transformations (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Package
org.hansken.plugin.extraction.api.transformations

+
+ +
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+ +
+
This package contains the Data Transformations.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/ArgChecks.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/ArgChecks.html new file mode 100644 index 0000000..c545e99 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/ArgChecks.html @@ -0,0 +1,466 @@ + + + + +ArgChecks (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Class ArgChecks

+
+
java.lang.Object +
org.hansken.plugin.extraction.util.ArgChecks
+
+
+
+
public final class ArgChecks +extends Object
+
A collection of methods for defensively checking arguments passed to methods.
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    static Object[]
    +
    argNotAllNull(String name, + Object... values)
    +
    +
    Check that not all values with given name are null, otherwise throw an exception.
    +
    +
    static String
    +
    argNotEmpty(String name, + String value)
    +
    +
    Check that the string with given name is not null or empty, otherwise throw an exception.
    +
    +
    static <T> Collection<T>
    +
    argNotEmpty(String name, + Collection<T> value)
    +
    +
    Check that the collection value with given name is not empty, otherwise throw an exception.
    +
    +
    static <T> T[]
    +
    argNotEmpty(String name, + T[] value)
    +
    +
    Check that the array value with given name is not empty, otherwise throw an exception.
    +
    +
    static float
    +
    argNotNegative(String name, + float value)
    +
    +
    Check that the float with given name is not negative, otherwise throw an exception.
    +
    +
    static int
    +
    argNotNegative(String name, + int value)
    +
    +
    Check that the int with given name is not negative, otherwise throw an exception.
    +
    +
    static long
    +
    argNotNegative(String name, + long value)
    +
    +
    Check that the long with given name is not negative, otherwise throw an exception.
    +
    +
    static <T> T
    +
    argNotNull(String name, + T value)
    +
    +
    Check that the value with given name is not null, otherwise throw an exception.
    +
    +
    static <T> List<T>
    +
    argsIsType(String name, + List<T> value, + Class<?> type)
    +
    +
    Check that the value with given name is of type type, otherwise throw an exception.
    +
    +
    +
    +
    +
    +

    Methods inherited from class java.lang.Object

    +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      argNotNull

      +
      public static <T> T argNotNull(String name, + T value)
      +
      Check that the value with given name is not null, otherwise throw an exception. +

      + Example usage: +

      + 
      +     private final Author author;
      +
      +     public Book(final Author author) {
      +          // this throws a NullPointerException when the author is null
      +          this.author = argNotNull("author", author);
      +     }
      + 
      + 
      +
      +
      Type Parameters:
      +
      T - the type of the value
      +
      Parameters:
      +
      name - a descriptive name for the value (most likely the argument name)
      +
      value - the value itself
      +
      Returns:
      +
      the value, so it can be used to inline in an assignment
      +
      Throws:
      +
      NullPointerException - if value == null
      +
      +
      +
    • +
    • +
      +

      argsIsType

      +
      public static <T> List<T> argsIsType(String name, + List<T> value, + Class<?> type)
      +
      Check that the value with given name is of type type, otherwise throw an exception. +

      + Example usage: +

      + 
      +     public Book(final List<Object> authors) {
      +          // this throws a ClassCastException when authors contains a type other than Author.class
      +          argsIsType("author", authors, Author.class);
      +     }
      + 
      + 
      +
      +
      Type Parameters:
      +
      T - the type of the value
      +
      Parameters:
      +
      name - a descriptive name for the value (most likely the argument name)
      +
      value - the value itself
      +
      type - the class type we want to check against value
      +
      Returns:
      +
      the value, so it can be used to inline in an assignment
      +
      Throws:
      +
      ClassCastException - if value.allMatch(type::isInstance) is false
      +
      +
      +
    • +
    • +
      +

      argNotAllNull

      +
      public static Object[] argNotAllNull(String name, + Object... values)
      +
      Check that not all values with given name are null, otherwise throw an exception. +

      + Example usage: +

      + 
      +     private final Author author;
      +
      +     public Book(final Author... authors) {
      +          // this throws a NullPointerException when the author is null
      +          this.author = argNotAllNull("authors", authors);
      +     }
      + 
      + 
      +
      +
      Parameters:
      +
      name - a descriptive name for the values (most likely the argument name)
      +
      values - the values, which can be different types
      +
      Returns:
      +
      the values, so it can be used to inline in an assignment
      +
      Throws:
      +
      NullPointerException - if values.allMatch(Objects::isNull)
      +
      +
      +
    • +
    • +
      +

      argNotEmpty

      +
      public static <T> T[] argNotEmpty(String name, + T[] value)
      +
      Check that the array value with given name is not empty, otherwise throw an exception. +

      + Example usage: +

      + 
      +     private final Author[] author;
      +
      +     public Book(final Author[] author) {
      +          // this throws a NullPointerException when the author array is empty
      +          this.author = argNotEmpty("author", author);
      +     }
      + 
      + 
      +
      +
      Type Parameters:
      +
      T - the type of the value
      +
      Parameters:
      +
      name - a descriptive name for the value (most likely the argument name)
      +
      value - the value itself
      +
      Returns:
      +
      the value, so it can be used to inline in an assignment
      +
      Throws:
      +
      IllegalArgumentException - if value == null || value.length == 0
      +
      +
      +
    • +
    • +
      +

      argNotEmpty

      +
      public static <T> Collection<T> argNotEmpty(String name, + Collection<T> value)
      +
      Check that the collection value with given name is not empty, otherwise throw an exception. +

      + Example usage: +

      + 
      +     private final Collection<Author> author;
      +
      +     public Book(final Collection<Author> author) {
      +          // this throws a NullPointerException when the author collection is empty
      +          this.author = argNotEmpty("author", author);
      +     }
      + 
      + 
      +
      +
      Type Parameters:
      +
      T - the type of the value
      +
      Parameters:
      +
      name - a descriptive name for the value (most likely the argument name)
      +
      value - the value itself
      +
      Returns:
      +
      the value, so it can be used to inline in an assignment
      +
      Throws:
      +
      IllegalArgumentException - if value == null || value.isEmpty()
      +
      +
      +
    • +
    • +
      +

      argNotEmpty

      +
      public static String argNotEmpty(String name, + String value)
      +
      Check that the string with given name is not null or empty, otherwise throw an exception. +

      + Example usage: +

      + 
      +     private final String title;
      +
      +     public Book(final String title) {
      +          // this throws a NullPointerException when the author is null
      +          // or an IllegalArgumentException when author is an empty String
      +          this.title = argNotEmpty("title", title);
      +     }
      + 
      + 
      +
      +
      Parameters:
      +
      name - a descriptive name for the string (most likely the argument name)
      +
      value - the string itself
      +
      Returns:
      +
      the string, so it can be used to inline in an assignment
      +
      Throws:
      +
      NullPointerException - if value == null
      +
      IllegalArgumentException - if value.isEmpty()
      +
      +
      +
    • +
    • +
      +

      argNotNegative

      +
      public static int argNotNegative(String name, + int value)
      +
      Check that the int with given name is not negative, otherwise throw an exception. + Example usage: +
      + 
      +     private final int pageCount;
      +
      +     public Book(final int pageCount) {
      +          // this throws an IllegalArgumentException when pageCount is negative
      +          this.pageCount = argNotNegative("pageCount", pageCount);
      +     }
      + 
      + 
      +
      +
      Parameters:
      +
      name - a descriptive name for the int (most likely the argument name)
      +
      value - the int itself
      +
      Returns:
      +
      the int, so it can be used in an inline assignment
      +
      Throws:
      +
      IllegalArgumentException - if value < 0
      +
      +
      +
    • +
    • +
      +

      argNotNegative

      +
      public static long argNotNegative(String name, + long value)
      +
      Check that the long with given name is not negative, otherwise throw an exception. + Example usage: +
      + 
      +     private final long pageCount;
      +
      +     public Book(final long pageCount) {
      +          // this throws an IllegalArgumentException when pageCount is negative
      +          this.pageCount = argNotNegative("pageCount", pageCount);
      +     }
      + 
      + 
      +
      +
      Parameters:
      +
      name - a descriptive name for the long (most likely the argument name)
      +
      value - the long itself
      +
      Returns:
      +
      the long, so it can be used in an inline assignment
      +
      Throws:
      +
      IllegalArgumentException - if value < 0
      +
      +
      +
    • +
    • +
      +

      argNotNegative

      +
      public static float argNotNegative(String name, + float value)
      +
      Check that the float with given name is not negative, otherwise throw an exception. + Example usage: +
      + 
      +     private final float pageCount;
      +
      +     public Book(final float pageCount) {
      +          // this throws an IllegalArgumentException when pageCount is negative
      +          this.pageCount = argNotNegative("pageCount", pageCount);
      +     }
      + 
      + 
      +
      +
      Parameters:
      +
      name - a descriptive name for the float (most likely the argument name)
      +
      value - the float itself
      +
      Returns:
      +
      the float, so it can be used in an inline assignment
      +
      Throws:
      +
      IllegalArgumentException - if value < 0
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/ThrowingConsumer.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/ThrowingConsumer.html new file mode 100644 index 0000000..bea86fe --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/ThrowingConsumer.html @@ -0,0 +1,167 @@ + + + + +ThrowingConsumer (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Interface ThrowingConsumer<T,E extends Throwable>

+
+
+
+
Type Parameters:
+
T - the type of the input to the operation
+
E - the type of the Throwable which can be thrown by the operation
+
+
+
Functional Interface:
+
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
+
+
+
@FunctionalInterface +public interface ThrowingConsumer<T,E extends Throwable>
+
Represents an operation that accepts a single input argument and returns no result. + Replaces the normal Java Consumer and enables throwing an Exception from the callback. Used to enable + lambda callbacks in for example Trace.newChild(String, ThrowingConsumer).
+
+
+
    + +
  • +
    +

    Method Summary

    +
    +
    +
    +
    +
    Modifier and Type
    +
    Method
    +
    Description
    +
    void
    +
    accept(T t)
    +
    +
    Performs this operation on the given argument.
    +
    +
    +
    +
    +
    +
  • +
+
+
+
    + +
  • +
    +

    Method Details

    +
      +
    • +
      +

      accept

      +
      void accept(T t) + throws E
      +
      Performs this operation on the given argument.
      +
      +
      Parameters:
      +
      t - the input argument
      +
      Throws:
      +
      E - when an exception occurs
      +
      +
      +
    • +
    +
    +
  • +
+
+ +
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/class-use/ArgChecks.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/class-use/ArgChecks.html new file mode 100644 index 0000000..3513ec1 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/class-use/ArgChecks.html @@ -0,0 +1,63 @@ + + + + +Uses of Class org.hansken.plugin.extraction.util.ArgChecks (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
org.hansken.plugin.extraction.util.ArgChecks

+
+No usage of org.hansken.plugin.extraction.util.ArgChecks
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/class-use/ThrowingConsumer.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/class-use/ThrowingConsumer.html new file mode 100644 index 0000000..d35338f --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/class-use/ThrowingConsumer.html @@ -0,0 +1,93 @@ + + + + +Uses of Interface org.hansken.plugin.extraction.util.ThrowingConsumer (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Interface
org.hansken.plugin.extraction.util.ThrowingConsumer

+
+
Packages that use ThrowingConsumer
+
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-summary.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-summary.html new file mode 100644 index 0000000..0b46e0d --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-summary.html @@ -0,0 +1,115 @@ + + + + +org.hansken.plugin.extraction.util (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Package org.hansken.plugin.extraction.util

+
+
+
package org.hansken.plugin.extraction.util
+
+
This package provides util classes for the Extraction Plugin SDK API. +

+
+
Since:
+
0.0.1
+
Author:
+
Netherlands Forensic Institute
+
+
+
+
    +
  • +
    +
    +
    +
    +
    Class
    +
    Description
    + +
    +
    A collection of methods for defensively checking arguments passed to methods.
    +
    + +
    +
    Represents an operation that accepts a single input argument and returns no result.
    +
    +
    +
    +
    +
  • +
+
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-tree.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-tree.html new file mode 100644 index 0000000..9a0c928 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-tree.html @@ -0,0 +1,83 @@ + + + + +org.hansken.plugin.extraction.util Class Hierarchy (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Hierarchy For Package org.hansken.plugin.extraction.util

+
+Package Hierarchies: + +
+

Class Hierarchy

+ +
+
+

Interface Hierarchy

+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-use.html b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-use.html new file mode 100644 index 0000000..21f4621 --- /dev/null +++ b/0.9.16/_static/javadoc/org/hansken/plugin/extraction/util/package-use.html @@ -0,0 +1,89 @@ + + + + +Uses of Package org.hansken.plugin.extraction.util (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Package
org.hansken.plugin.extraction.util

+
+ +
+
Package
+
Description
+ +
+
This is the API of the Extraction Plugins SDK.
+
+
+
+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/overview-summary.html b/0.9.16/_static/javadoc/overview-summary.html new file mode 100644 index 0000000..5c7f6ec --- /dev/null +++ b/0.9.16/_static/javadoc/overview-summary.html @@ -0,0 +1,26 @@ + + + + +Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API + + + + + + + + + + + +
+ +

index.html

+
+ + diff --git a/0.9.16/_static/javadoc/overview-tree.html b/0.9.16/_static/javadoc/overview-tree.html new file mode 100644 index 0000000..b63d567 --- /dev/null +++ b/0.9.16/_static/javadoc/overview-tree.html @@ -0,0 +1,165 @@ + + + + +Class Hierarchy (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Hierarchy For All Packages

+
+Package Hierarchies: + +
+

Class Hierarchy

+ +
+
+

Interface Hierarchy

+ +
+
+

Enum Class Hierarchy

+ +
+
+

Record Class Hierarchy

+ +
+
+
+
+ +
+
+
+ + diff --git a/0.9.16/_static/javadoc/package-search-index.js b/0.9.16/_static/javadoc/package-search-index.js new file mode 100644 index 0000000..c7fa0c3 --- /dev/null +++ b/0.9.16/_static/javadoc/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","u":"allpackages-index.html"},{"l":"org.hansken.plugin.extraction.api"},{"l":"org.hansken.plugin.extraction.api.transformations"},{"l":"org.hansken.plugin.extraction.util"}];updateSearchResults(); \ No newline at end of file diff --git a/0.9.16/_static/javadoc/resources/glass.png b/0.9.16/_static/javadoc/resources/glass.png new file mode 100644 index 0000000..a7f591f Binary files /dev/null and b/0.9.16/_static/javadoc/resources/glass.png differ diff --git a/0.9.16/_static/javadoc/resources/x.png b/0.9.16/_static/javadoc/resources/x.png new file mode 100644 index 0000000..30548a7 Binary files /dev/null and b/0.9.16/_static/javadoc/resources/x.png differ diff --git a/0.9.16/_static/javadoc/script-dir/jquery-3.6.1.min.js b/0.9.16/_static/javadoc/script-dir/jquery-3.6.1.min.js new file mode 100644 index 0000000..2c69bc9 --- /dev/null +++ b/0.9.16/_static/javadoc/script-dir/jquery-3.6.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=x(e||this.defaultElement||this)[0],this.element=x(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=x(),this.hoverable=x(),this.focusable=x(),this.classesElementLookup={},e!==this&&(x.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=x(e.style?e.ownerDocument:e.document||e),this.window=x(this.document[0].defaultView||this.document[0].parentWindow)),this.options=x.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:x.noop,_create:x.noop,_init:x.noop,destroy:function(){var i=this;this._destroy(),x.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:x.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return x.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=x.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return x("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthC(E(s),E(n))?o.important="horizontal":o.important="vertical",c.using.call(this,t,o)}),l.offset(x.extend(u,{using:t}))})},x.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,l=s-o,a=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=x(t.target),i=x(x.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){x.contains(this.element[0],x.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=x(t.target).closest(".ui-menu-item"),i=x(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=x(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case x.ui.keyCode.PAGE_UP:this.previousPage(t);break;case x.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case x.ui.keyCode.HOME:this._move("first","first",t);break;case x.ui.keyCode.END:this._move("last","last",t);break;case x.ui.keyCode.UP:this.previous(t);break;case x.ui.keyCode.DOWN:this.next(t);break;case x.ui.keyCode.LEFT:this.collapse(t);break;case x.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case x.ui.keyCode.ENTER:case x.ui.keyCode.SPACE:this._activate(t);break;case x.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=x(this),e=t.prev(),i=x("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=x(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!x.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(x.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(x.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=x.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=x.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=x("
    ").appendTo(this._appendTo()).menu({role:null}).hide().attr({unselectable:"on"}).menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault()},menufocus:function(t,e){var i,s;if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),void this.document.one("mousemove",function(){x(t.target).trigger(t.originalEvent)});s=e.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:s})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value),(i=e.item.attr("aria-label")||s.value)&&String.prototype.trim.call(i).length&&(clearTimeout(this.liveRegionTimer),this.liveRegionTimer=this._delay(function(){this.liveRegion.html(x("
    ").text(i))},100))},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==x.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=x("
    ",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(t){var e=this.menu.element[0];return t.target===this.element[0]||t.target===e||x.contains(e,t.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?x(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_initSource:function(){var i,s,n=this;Array.isArray(this.options.source)?(i=this.options.source,this.source=function(t,e){e(x.ui.autocomplete.filter(i,t.term))}):"string"==typeof this.options.source?(s=this.options.source,this.source=function(t,e){n.xhr&&n.xhr.abort(),n.xhr=x.ajax({url:s,data:t,dataType:"json",success:function(t){e(t)},error:function(){e([])}})}):this.source=this.options.source},_searchTimeout:function(s){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),e=this.menu.element.is(":visible"),i=s.altKey||s.ctrlKey||s.metaKey||s.shiftKey;t&&(e||i)||(this.selectedItem=null,this.search(null,s))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length").append(x("
    ").text(e.label)).appendTo(t)},_move:function(t,e){if(this.menu.element.is(":visible"))return this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),void this.menu.blur()):void this.menu[t](e);this.search(null,e)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){this.isMultiLine&&!this.menu.element.is(":visible")||(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),x.extend(x.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,e){var i=new RegExp(x.ui.autocomplete.escapeRegex(e),"i");return x.grep(t,function(t){return i.test(t.label||t.value||t)})}}),x.widget("ui.autocomplete",x.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(1").text(e))},100))}});x.ui.autocomplete}); \ No newline at end of file diff --git a/0.9.16/_static/javadoc/script.js b/0.9.16/_static/javadoc/script.js new file mode 100644 index 0000000..8b9691a --- /dev/null +++ b/0.9.16/_static/javadoc/script.js @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; + +var oddRowColor = "odd-row-color"; +var evenRowColor = "even-row-color"; +var sortAsc = "sort-asc"; +var sortDesc = "sort-desc"; +var tableTab = "table-tab"; +var activeTableTab = "active-table-tab"; + +function loadScripts(doc, tag) { + createElem(doc, tag, 'search.js'); + + createElem(doc, tag, 'module-search-index.js'); + createElem(doc, tag, 'package-search-index.js'); + createElem(doc, tag, 'type-search-index.js'); + createElem(doc, tag, 'member-search-index.js'); + createElem(doc, tag, 'tag-search-index.js'); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +// Helper for making content containing release names comparable lexicographically +function makeComparable(s) { + return s.toLowerCase().replace(/(\d+)/g, + function(n, m) { + return ("000" + m).slice(-4); + }); +} + +// Switches between two styles depending on a condition +function toggleStyle(classList, condition, trueStyle, falseStyle) { + if (condition) { + classList.remove(falseStyle); + classList.add(trueStyle); + } else { + classList.remove(trueStyle); + classList.add(falseStyle); + } +} + +// Sorts the rows in a table lexicographically by the content of a specific column +function sortTable(header, columnIndex, columns) { + var container = header.parentElement; + var descending = header.classList.contains(sortAsc); + container.querySelectorAll("div.table-header").forEach( + function(header) { + header.classList.remove(sortAsc); + header.classList.remove(sortDesc); + } + ) + var cells = container.children; + var rows = []; + for (var i = columns; i < cells.length; i += columns) { + rows.push(Array.prototype.slice.call(cells, i, i + columns)); + } + var comparator = function(a, b) { + var ka = makeComparable(a[columnIndex].textContent); + var kb = makeComparable(b[columnIndex].textContent); + if (ka < kb) + return descending ? 1 : -1; + if (ka > kb) + return descending ? -1 : 1; + return 0; + }; + var sorted = rows.sort(comparator); + var visible = 0; + sorted.forEach(function(row) { + if (row[0].style.display !== 'none') { + var isEvenRow = visible++ % 2 === 0; + } + row.forEach(function(cell) { + toggleStyle(cell.classList, isEvenRow, evenRowColor, oddRowColor); + container.appendChild(cell); + }) + }); + toggleStyle(header.classList, descending, sortDesc, sortAsc); +} + +// Toggles the visibility of a table category in all tables in a page +function toggleGlobal(checkbox, selected, columns) { + var display = checkbox.checked ? '' : 'none'; + document.querySelectorAll("div.table-tabs").forEach(function(t) { + var id = t.parentElement.getAttribute("id"); + var selectedClass = id + "-tab" + selected; + // if selected is empty string it selects all uncategorized entries + var selectUncategorized = !Boolean(selected); + var visible = 0; + document.querySelectorAll('div.' + id) + .forEach(function(elem) { + if (selectUncategorized) { + if (elem.className.indexOf(selectedClass) === -1) { + elem.style.display = display; + } + } else if (elem.classList.contains(selectedClass)) { + elem.style.display = display; + } + if (elem.style.display === '') { + var isEvenRow = visible++ % (columns * 2) < columns; + toggleStyle(elem.classList, isEvenRow, evenRowColor, oddRowColor); + } + }); + var displaySection = visible === 0 ? 'none' : ''; + t.parentElement.style.display = displaySection; + document.querySelector("li#contents-" + id).style.display = displaySection; + }) +} + +// Shows the elements of a table belonging to a specific category +function show(tableId, selected, columns) { + if (tableId !== selected) { + document.querySelectorAll('div.' + tableId + ':not(.' + selected + ')') + .forEach(function(elem) { + elem.style.display = 'none'; + }); + } + document.querySelectorAll('div.' + selected) + .forEach(function(elem, index) { + elem.style.display = ''; + var isEvenRow = index % (columns * 2) < columns; + toggleStyle(elem.classList, isEvenRow, evenRowColor, oddRowColor); + }); + updateTabs(tableId, selected); +} + +function updateTabs(tableId, selected) { + document.querySelector('div#' + tableId +' .summary-table') + .setAttribute('aria-labelledby', selected); + document.querySelectorAll('button[id^="' + tableId + '"]') + .forEach(function(tab, index) { + if (selected === tab.id || (tableId === selected && index === 0)) { + tab.className = activeTableTab; + tab.setAttribute('aria-selected', true); + tab.setAttribute('tabindex',0); + } else { + tab.className = tableTab; + tab.setAttribute('aria-selected', false); + tab.setAttribute('tabindex',-1); + } + }); +} + +function switchTab(e) { + var selected = document.querySelector('[aria-selected=true]'); + if (selected) { + if ((e.keyCode === 37 || e.keyCode === 38) && selected.previousSibling) { + // left or up arrow key pressed: move focus to previous tab + selected.previousSibling.click(); + selected.previousSibling.focus(); + e.preventDefault(); + } else if ((e.keyCode === 39 || e.keyCode === 40) && selected.nextSibling) { + // right or down arrow key pressed: move focus to next tab + selected.nextSibling.click(); + selected.nextSibling.focus(); + e.preventDefault(); + } + } +} + +var updateSearchResults = function() {}; + +function indexFilesLoaded() { + return moduleSearchIndex + && packageSearchIndex + && typeSearchIndex + && memberSearchIndex + && tagSearchIndex; +} +// Copy the contents of the local snippet to the clipboard +function copySnippet(button) { + copyToClipboard(button.nextElementSibling.innerText); + switchCopyLabel(button, button.firstElementChild); +} +function copyToClipboard(content) { + var textarea = document.createElement("textarea"); + textarea.style.height = 0; + document.body.appendChild(textarea); + textarea.value = content; + textarea.select(); + document.execCommand("copy"); + document.body.removeChild(textarea); +} +function switchCopyLabel(button, span) { + var copied = span.getAttribute("data-copied"); + button.classList.add("visible"); + var initialLabel = span.innerHTML; + span.innerHTML = copied; + setTimeout(function() { + button.classList.remove("visible"); + setTimeout(function() { + if (initialLabel !== copied) { + span.innerHTML = initialLabel; + } + }, 100); + }, 1900); +} +// Workaround for scroll position not being included in browser history (8249133) +document.addEventListener("DOMContentLoaded", function(e) { + var contentDiv = document.querySelector("div.flex-content"); + window.addEventListener("popstate", function(e) { + if (e.state !== null) { + contentDiv.scrollTop = e.state; + } + }); + window.addEventListener("hashchange", function(e) { + history.replaceState(contentDiv.scrollTop, document.title); + }); + var timeoutId; + contentDiv.addEventListener("scroll", function(e) { + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(function() { + history.replaceState(contentDiv.scrollTop, document.title); + }, 100); + }); + if (!location.hash) { + history.replaceState(contentDiv.scrollTop, document.title); + } +}); diff --git a/0.9.16/_static/javadoc/search-page.js b/0.9.16/_static/javadoc/search-page.js new file mode 100644 index 0000000..540c90f --- /dev/null +++ b/0.9.16/_static/javadoc/search-page.js @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +"use strict"; +$(function() { + var copy = $("#page-search-copy"); + var expand = $("#page-search-expand"); + var searchLink = $("span#page-search-link"); + var redirect = $("input#search-redirect"); + function setSearchUrlTemplate() { + var href = document.location.href.split(/[#?]/)[0]; + href += "?q=" + "%s"; + if (redirect.is(":checked")) { + href += "&r=1"; + } + searchLink.html(href); + copy[0].onmouseenter(); + } + function copyLink(e) { + copyToClipboard(this.previousSibling.innerText); + switchCopyLabel(this, this.lastElementChild); + } + copy.click(copyLink); + copy[0].onmouseenter = function() {}; + redirect.click(setSearchUrlTemplate); + setSearchUrlTemplate(); + copy.prop("disabled", false); + redirect.prop("disabled", false); + expand.click(function (e) { + var searchInfo = $("div.page-search-info"); + if(this.parentElement.hasAttribute("open")) { + searchInfo.attr("style", "border-width: 0;"); + } else { + searchInfo.attr("style", "border-width: 1px;").height(searchInfo.prop("scrollHeight")); + } + }); +}); +$(window).on("load", function() { + var input = $("#page-search-input"); + var reset = $("#page-search-reset"); + var notify = $("#page-search-notify"); + var resultSection = $("div#result-section"); + var resultContainer = $("div#result-container"); + var searchTerm = ""; + var activeTab = ""; + var fixedTab = false; + var visibleTabs = []; + var feelingLucky = false; + function renderResults(result) { + if (!result.length) { + notify.html(messages.noResult); + } else if (result.length === 1) { + notify.html(messages.oneResult); + } else { + notify.html(messages.manyResults.replace("{0}", result.length)); + } + resultContainer.empty(); + var r = { + "types": [], + "members": [], + "packages": [], + "modules": [], + "searchTags": [] + }; + for (var i in result) { + var item = result[i]; + var arr = r[item.category]; + arr.push(item); + } + if (!activeTab || r[activeTab].length === 0 || !fixedTab) { + Object.keys(r).reduce(function(prev, curr) { + if (r[curr].length > 0 && r[curr][0].score > prev) { + activeTab = curr; + return r[curr][0].score; + } + return prev; + }, 0); + } + if (feelingLucky && activeTab) { + notify.html(messages.redirecting) + var firstItem = r[activeTab][0]; + window.location = getURL(firstItem.indexItem, firstItem.category); + return; + } + if (result.length > 20) { + if (searchTerm[searchTerm.length - 1] === ".") { + if (activeTab === "types" && r["members"].length > r["types"].length) { + activeTab = "members"; + } else if (activeTab === "packages" && r["types"].length > r["packages"].length) { + activeTab = "types"; + } + } + } + var categoryCount = Object.keys(r).reduce(function(prev, curr) { + return prev + (r[curr].length > 0 ? 1 : 0); + }, 0); + visibleTabs = []; + var tabContainer = $("
    ").appendTo(resultContainer); + for (var key in r) { + var id = "#result-tab-" + key.replace("searchTags", "search_tags"); + if (r[key].length) { + var count = r[key].length >= 1000 ? "999+" : r[key].length; + if (result.length > 20 && categoryCount > 1) { + var button = $("").appendTo(tabContainer); + button.click(key, function(e) { + fixedTab = true; + renderResult(e.data, $(this)); + }); + visibleTabs.push(key); + } else { + $("" + categories[key] + + " (" + count + ")").appendTo(tabContainer); + renderTable(key, r[key]).appendTo(resultContainer); + tabContainer = $("
    ").appendTo(resultContainer); + + } + } + } + if (activeTab && result.length > 20 && categoryCount > 1) { + $("button#result-tab-" + activeTab).addClass("active-table-tab"); + renderTable(activeTab, r[activeTab]).appendTo(resultContainer); + } + resultSection.show(); + function renderResult(category, button) { + activeTab = category; + setSearchUrl(); + resultContainer.find("div.summary-table").remove(); + renderTable(activeTab, r[activeTab]).appendTo(resultContainer); + button.siblings().removeClass("active-table-tab"); + button.addClass("active-table-tab"); + } + } + function selectTab(category) { + $("button#result-tab-" + category).click(); + } + function renderTable(category, items) { + var table = $("
    ") + .addClass(category === "modules" + ? "one-column-search-results" + : "two-column-search-results"); + var col1, col2; + if (category === "modules") { + col1 = "Module"; + } else if (category === "packages") { + col1 = "Module"; + col2 = "Package"; + } else if (category === "types") { + col1 = "Package"; + col2 = "Class" + } else if (category === "members") { + col1 = "Class"; + col2 = "Member"; + } else if (category === "searchTags") { + col1 = "Location"; + col2 = "Name"; + } + $("
    " + col1 + "
    ").appendTo(table); + if (category !== "modules") { + $("
    " + col2 + "
    ").appendTo(table); + } + $.each(items, function(index, item) { + var rowColor = index % 2 ? "odd-row-color" : "even-row-color"; + renderItem(item, table, rowColor); + }); + return table; + } + function renderItem(item, table, rowColor) { + var label = getHighlightedText(item.input, item.boundaries, item.prefix.length, item.input.length); + var link = $("") + .attr("href", getURL(item.indexItem, item.category)) + .attr("tabindex", "0") + .addClass("search-result-link") + .html(label); + var container = getHighlightedText(item.input, item.boundaries, 0, item.prefix.length - 1); + if (item.category === "searchTags") { + container = item.indexItem.h || ""; + } + if (item.category !== "modules") { + $("
    ").html(container).addClass("col-plain").addClass(rowColor).appendTo(table); + } + $("
    ").html(link).addClass("col-last").addClass(rowColor).appendTo(table); + } + var timeout; + function schedulePageSearch() { + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(function () { + doPageSearch() + }, 100); + } + function doPageSearch() { + setSearchUrl(); + var term = searchTerm = input.val().trim(); + if (term === "") { + notify.html(messages.enterTerm); + activeTab = ""; + fixedTab = false; + resultContainer.empty(); + resultSection.hide(); + } else { + notify.html(messages.searching); + doSearch({ term: term, maxResults: 1200 }, renderResults); + } + } + function setSearchUrl() { + var query = input.val().trim(); + var url = document.location.pathname; + if (query) { + url += "?q=" + encodeURI(query); + if (activeTab && fixedTab) { + url += "&c=" + activeTab; + } + } + history.replaceState({query: query}, "", url); + } + input.on("input", function(e) { + feelingLucky = false; + schedulePageSearch(); + }); + $(document).keydown(function(e) { + if ((e.ctrlKey || e.metaKey) && (e.key === "ArrowLeft" || e.key === "ArrowRight")) { + if (activeTab && visibleTabs.length > 1) { + var idx = visibleTabs.indexOf(activeTab); + idx += e.key === "ArrowLeft" ? visibleTabs.length - 1 : 1; + selectTab(visibleTabs[idx % visibleTabs.length]); + return false; + } + } + }); + reset.click(function() { + notify.html(messages.enterTerm); + resultSection.hide(); + activeTab = ""; + fixedTab = false; + resultContainer.empty(); + input.val('').focus(); + setSearchUrl(); + }); + input.prop("disabled", false); + reset.prop("disabled", false); + + var urlParams = new URLSearchParams(window.location.search); + if (urlParams.has("q")) { + input.val(urlParams.get("q")) + } + if (urlParams.has("c")) { + activeTab = urlParams.get("c"); + fixedTab = true; + } + if (urlParams.get("r")) { + feelingLucky = true; + } + if (input.val()) { + doPageSearch(); + } else { + notify.html(messages.enterTerm); + } + input.select().focus(); +}); diff --git a/0.9.16/_static/javadoc/search.html b/0.9.16/_static/javadoc/search.html new file mode 100644 index 0000000..26d7894 --- /dev/null +++ b/0.9.16/_static/javadoc/search.html @@ -0,0 +1,78 @@ + + + + +Search (Hansken Extraction Plugin SDK - API 0.9.16-master-188-037fa906 API) + + + + + + + + + + + + + + +
    + +
    +
    +

    Search

    +
    + + +
    +Additional resources +
    +
    +
    +

    The help page provides an introduction to the scope and syntax of JavaDoc search.

    +

    You can use the <ctrl> or <cmd> keys in combination with the left and right arrow keys to switch between result tabs in this page.

    +

    The URL template below may be used to configure this page as a search engine in browsers that support this feature. It has been tested to work in Google Chrome and Mozilla Firefox. Note that other browsers may not support this feature or require a different URL format.

    +link +

    + +

    +
    +

    Loading search index...

    + +
    +
    +
    + +
    +
    +
    + + diff --git a/0.9.16/_static/javadoc/search.js b/0.9.16/_static/javadoc/search.js new file mode 100644 index 0000000..d398670 --- /dev/null +++ b/0.9.16/_static/javadoc/search.js @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +"use strict"; +const messages = { + enterTerm: "Enter a search term", + noResult: "No results found", + oneResult: "Found one result", + manyResults: "Found {0} results", + loading: "Loading search index...", + searching: "Searching...", + redirecting: "Redirecting to first result...", + linkIcon: "Link icon", + linkToSection: "Link to this section" +} +const categories = { + modules: "Modules", + packages: "Packages", + types: "Classes and Interfaces", + members: "Members", + searchTags: "Search Tags" +}; +const highlight = "$&"; +const NO_MATCH = {}; +const MAX_RESULTS = 300; +function checkUnnamed(name, separator) { + return name === "" || !name ? "" : name + separator; +} +function escapeHtml(str) { + return str.replace(//g, ">"); +} +function getHighlightedText(str, boundaries, from, to) { + var start = from; + var text = ""; + for (var i = 0; i < boundaries.length; i += 2) { + var b0 = boundaries[i]; + var b1 = boundaries[i + 1]; + if (b0 >= to || b1 <= from) { + continue; + } + text += escapeHtml(str.slice(start, Math.max(start, b0))); + text += ""; + text += escapeHtml(str.slice(Math.max(start, b0), Math.min(to, b1))); + text += ""; + start = Math.min(to, b1); + } + text += escapeHtml(str.slice(start, to)); + return text; +} +function getURLPrefix(item, category) { + var urlPrefix = ""; + var slash = "/"; + if (category === "modules") { + return item.l + slash; + } else if (category === "packages" && item.m) { + return item.m + slash; + } else if (category === "types" || category === "members") { + if (item.m) { + urlPrefix = item.m + slash; + } else { + $.each(packageSearchIndex, function(index, it) { + if (it.m && item.p === it.l) { + urlPrefix = it.m + slash; + } + }); + } + } + return urlPrefix; +} +function getURL(item, category) { + if (item.url) { + return item.url; + } + var url = getURLPrefix(item, category); + if (category === "modules") { + url += "module-summary.html"; + } else if (category === "packages") { + if (item.u) { + url = item.u; + } else { + url += item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (category === "types") { + if (item.u) { + url = item.u; + } else { + url += checkUnnamed(item.p, "/").replace(/\./g, '/') + item.l + ".html"; + } + } else if (category === "members") { + url += checkUnnamed(item.p, "/").replace(/\./g, '/') + item.c + ".html" + "#"; + if (item.u) { + url += item.u; + } else { + url += item.l; + } + } else if (category === "searchTags") { + url += item.u; + } + item.url = url; + return url; +} +function createMatcher(term, camelCase) { + if (camelCase && !isUpperCase(term)) { + return null; // no need for camel-case matcher for lower case query + } + var pattern = ""; + var upperCase = []; + term.trim().split(/\s+/).forEach(function(w, index, array) { + var tokens = w.split(/(?=[A-Z,.()<>?[\/])/); + for (var i = 0; i < tokens.length; i++) { + var s = tokens[i]; + // ',' and '?' are the only delimiters commonly followed by space in java signatures + pattern += "(" + $.ui.autocomplete.escapeRegex(s).replace(/[,?]/g, "$&\\s*?") + ")"; + upperCase.push(false); + var isWordToken = /\w$/.test(s); + if (isWordToken) { + if (i === tokens.length - 1 && index < array.length - 1) { + // space in query string matches all delimiters + pattern += "(.*?)"; + upperCase.push(isUpperCase(s[0])); + } else { + if (!camelCase && isUpperCase(s) && s.length === 1) { + pattern += "()"; + } else { + pattern += "([a-z0-9$<>?[\\]]*?)"; + } + upperCase.push(isUpperCase(s[0])); + } + } else { + pattern += "()"; + upperCase.push(false); + } + } + }); + var re = new RegExp(pattern, "gi"); + re.upperCase = upperCase; + return re; +} +function findMatch(matcher, input, startOfName, endOfName) { + var from = startOfName; + matcher.lastIndex = from; + var match = matcher.exec(input); + // Expand search area until we get a valid result or reach the beginning of the string + while (!match || match.index + match[0].length < startOfName || endOfName < match.index) { + if (from === 0) { + return NO_MATCH; + } + from = input.lastIndexOf(".", from - 2) + 1; + matcher.lastIndex = from; + match = matcher.exec(input); + } + var boundaries = []; + var matchEnd = match.index + match[0].length; + var score = 5; + var start = match.index; + var prevEnd = -1; + for (var i = 1; i < match.length; i += 2) { + var isUpper = isUpperCase(input[start]); + var isMatcherUpper = matcher.upperCase[i]; + // capturing groups come in pairs, match and non-match + boundaries.push(start, start + match[i].length); + // make sure groups are anchored on a left word boundary + var prevChar = input[start - 1] || ""; + var nextChar = input[start + 1] || ""; + if (start !== 0 && !/[\W_]/.test(prevChar) && !/[\W_]/.test(input[start])) { + if (isUpper && (isLowerCase(prevChar) || isLowerCase(nextChar))) { + score -= 0.1; + } else if (isMatcherUpper && start === prevEnd) { + score -= isUpper ? 0.1 : 1.0; + } else { + return NO_MATCH; + } + } + prevEnd = start + match[i].length; + start += match[i].length + match[i + 1].length; + + // lower score for parts of the name that are missing + if (match[i + 1] && prevEnd < endOfName) { + score -= rateNoise(match[i + 1]); + } + } + // lower score if a type name contains unmatched camel-case parts + if (input[matchEnd - 1] !== "." && endOfName > matchEnd) + score -= rateNoise(input.slice(matchEnd, endOfName)); + score -= rateNoise(input.slice(0, Math.max(startOfName, match.index))); + + if (score <= 0) { + return NO_MATCH; + } + return { + input: input, + score: score, + boundaries: boundaries + }; +} +function isUpperCase(s) { + return s !== s.toLowerCase(); +} +function isLowerCase(s) { + return s !== s.toUpperCase(); +} +function rateNoise(str) { + return (str.match(/([.(])/g) || []).length / 5 + + (str.match(/([A-Z]+)/g) || []).length / 10 + + str.length / 20; +} +function doSearch(request, response) { + var term = request.term.trim(); + var maxResults = request.maxResults || MAX_RESULTS; + if (term.length === 0) { + return this.close(); + } + var matcher = { + plainMatcher: createMatcher(term, false), + camelCaseMatcher: createMatcher(term, true) + } + var indexLoaded = indexFilesLoaded(); + + function getPrefix(item, category) { + switch (category) { + case "packages": + return checkUnnamed(item.m, "/"); + case "types": + return checkUnnamed(item.p, "."); + case "members": + return checkUnnamed(item.p, ".") + item.c + "."; + default: + return ""; + } + } + function useQualifiedName(category) { + switch (category) { + case "packages": + return /[\s/]/.test(term); + case "types": + case "members": + return /[\s.]/.test(term); + default: + return false; + } + } + function searchIndex(indexArray, category) { + var matches = []; + if (!indexArray) { + if (!indexLoaded) { + matches.push({ l: messages.loading, category: category }); + } + return matches; + } + $.each(indexArray, function (i, item) { + var prefix = getPrefix(item, category); + var simpleName = item.l; + var qualifiedName = prefix + simpleName; + var useQualified = useQualifiedName(category); + var input = useQualified ? qualifiedName : simpleName; + var startOfName = useQualified ? prefix.length : 0; + var endOfName = category === "members" && input.indexOf("(", startOfName) > -1 + ? input.indexOf("(", startOfName) : input.length; + var m = findMatch(matcher.plainMatcher, input, startOfName, endOfName); + if (m === NO_MATCH && matcher.camelCaseMatcher) { + m = findMatch(matcher.camelCaseMatcher, input, startOfName, endOfName); + } + if (m !== NO_MATCH) { + m.indexItem = item; + m.prefix = prefix; + m.category = category; + if (!useQualified) { + m.input = qualifiedName; + m.boundaries = m.boundaries.map(function(b) { + return b + prefix.length; + }); + } + matches.push(m); + } + return true; + }); + return matches.sort(function(e1, e2) { + return e2.score - e1.score; + }).slice(0, maxResults); + } + + var result = searchIndex(moduleSearchIndex, "modules") + .concat(searchIndex(packageSearchIndex, "packages")) + .concat(searchIndex(typeSearchIndex, "types")) + .concat(searchIndex(memberSearchIndex, "members")) + .concat(searchIndex(tagSearchIndex, "searchTags")); + + if (!indexLoaded) { + updateSearchResults = function() { + doSearch(request, response); + } + } else { + updateSearchResults = function() {}; + } + response(result); +} +// JQuery search menu implementation +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> .result-item"); + // workaround for search result scrolling + this.menu._scrollIntoView = function _scrollIntoView( item ) { + var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; + if ( this._hasScroll() ) { + borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0; + paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0; + offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; + scroll = this.activeMenu.scrollTop(); + elementHeight = this.activeMenu.height() - 26; + itemHeight = item.outerHeight(); + + if ( offset < 0 ) { + this.activeMenu.scrollTop( scroll + offset ); + } else if ( offset + itemHeight > elementHeight ) { + this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); + } + } + }; + }, + _renderMenu: function(ul, items) { + var currentCategory = ""; + var widget = this; + widget.menu.bindings = $(); + $.each(items, function(index, item) { + if (item.category && item.category !== currentCategory) { + ul.append("
  • " + categories[item.category] + "
  • "); + currentCategory = item.category; + } + var li = widget._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", categories[item.category] + " : " + item.l); + } else { + li.attr("aria-label", item.l); + } + li.attr("class", "result-item"); + }); + ul.append(""); + }, + _renderItem: function(ul, item) { + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + var label = item.l + ? item.l + : getHighlightedText(item.input, item.boundaries, 0, item.input.length); + var idx = item.indexItem; + if (item.category === "searchTags" && idx && idx.h) { + if (idx.d) { + div.html(label + " (" + idx.h + ")
    " + + idx.d + "
    "); + } else { + div.html(label + " (" + idx.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + var expanded = false; + var windowWidth; + function collapse() { + if (expanded) { + $("div#navbar-top").removeAttr("style"); + $("button#navbar-toggle-button") + .removeClass("expanded") + .attr("aria-expanded", "false"); + expanded = false; + } + } + $("button#navbar-toggle-button").click(function (e) { + if (expanded) { + collapse(); + } else { + var navbar = $("div#navbar-top"); + navbar.height(navbar.prop("scrollHeight")); + $("button#navbar-toggle-button") + .addClass("expanded") + .attr("aria-expanded", "true"); + expanded = true; + windowWidth = window.innerWidth; + } + }); + $("ul.sub-nav-list-small li a").click(collapse); + $("input#search-input").focus(collapse); + $("main").click(collapse); + $("section[id] > :header, :header[id], :header:has(a[id])").each(function(idx, el) { + // Create anchor links for headers with an associated id attribute + var hdr = $(el); + var id = hdr.attr("id") || hdr.parent("section").attr("id") || hdr.children("a").attr("id"); + if (id) { + hdr.append(" " + messages.linkIcon +""); + } + }); + $(window).on("orientationchange", collapse).on("resize", function(e) { + if (expanded && windowWidth !== window.innerWidth) collapse(); + }); + var search = $("#search-input"); + var reset = $("#reset-button"); + search.catcomplete({ + minLength: 1, + delay: 200, + source: doSearch, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push({ l: messages.noResult }); + } else { + $("#search-input").empty(); + } + }, + autoFocus: true, + focus: function(event, ui) { + return false; + }, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.indexItem) { + var url = getURL(ui.item.indexItem, ui.item.category); + window.location.href = pathtoroot + url; + $("#search-input").focus(); + } + } + }); + search.val(''); + search.prop("disabled", false); + reset.prop("disabled", false); + reset.click(function() { + search.val('').focus(); + }); + search.focus(); +}); diff --git a/0.9.16/_static/javadoc/stylesheet.css b/0.9.16/_static/javadoc/stylesheet.css new file mode 100644 index 0000000..f71489f --- /dev/null +++ b/0.9.16/_static/javadoc/stylesheet.css @@ -0,0 +1,1272 @@ +/* + * Javadoc style sheet + */ + +@import url('resources/fonts/dejavu.css'); + +/* + * These CSS custom properties (variables) define the core color and font + * properties used in this stylesheet. + */ +:root { + /* body, block and code fonts */ + --body-font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; + --block-font-family: 'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + --code-font-family: 'DejaVu Sans Mono', monospace; + /* Base font sizes for body and code elements */ + --body-font-size: 14px; + --code-font-size: 14px; + /* Text colors for body and block elements */ + --body-text-color: #353833; + --block-text-color: #474747; + /* Background colors for various structural elements */ + --body-background-color: #ffffff; + --section-background-color: #f8f8f8; + --detail-background-color: #ffffff; + /* Colors for navigation bar and table captions */ + --navbar-background-color: #4D7A97; + --navbar-text-color: #ffffff; + /* Background color for subnavigation and various headers */ + --subnav-background-color: #dee3e9; + /* Background and text colors for selected tabs and navigation items */ + --selected-background-color: #f8981d; + --selected-text-color: #253441; + --selected-link-color: #1f389c; + /* Background colors for generated tables */ + --even-row-color: #ffffff; + --odd-row-color: #eeeeef; + /* Text color for page title */ + --title-color: #2c4557; + /* Text colors for links */ + --link-color: #4A6782; + --link-color-active: #bb7a2a; + /* Snippet colors */ + --snippet-background-color: #ebecee; + --snippet-text-color: var(--block-text-color); + --snippet-highlight-color: #f7c590; + /* Border colors for structural elements and user defined tables */ + --border-color: #ededed; + --table-border-color: #000000; + /* Search input colors */ + --search-input-background-color: #ffffff; + --search-input-text-color: #000000; + --search-input-placeholder-color: #909090; + /* Highlight color for active search tag target */ + --search-tag-highlight-color: #ffff00; + /* Adjustments for icon and active background colors of copy-to-clipboard buttons */ + --copy-icon-brightness: 100%; + --copy-button-background-color-active: rgba(168, 168, 176, 0.3); + /* Colors for invalid tag notifications */ + --invalid-tag-background-color: #ffe6e6; + --invalid-tag-text-color: #000000; +} +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ +body { + background-color:var(--body-background-color); + color:var(--body-text-color); + font-family:var(--body-font-family); + font-size:var(--body-font-size); + margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; +} +a:link, a:visited { + text-decoration:none; + color:var(--link-color); +} +a[href]:hover, a[href]:focus { + text-decoration:none; + color:var(--link-color-active); +} +pre { + font-family:var(--code-font-family); + font-size:1em; +} +h1 { + font-size:1.428em; +} +h2 { + font-size:1.285em; +} +h3 { + font-size:1.14em; +} +h4 { + font-size:1.072em; +} +h5 { + font-size:1.001em; +} +h6 { + font-size:0.93em; +} +/* Disable font boosting for selected elements */ +h1, h2, h3, h4, h5, h6, div.member-signature { + max-height: 1000em; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:var(--code-font-family); +} +:not(h1, h2, h3, h4, h5, h6) > code, +:not(h1, h2, h3, h4, h5, h6) > tt { + font-size:var(--code-font-size); + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:var(--code-font-family); + font-size:1em; + padding-top:4px; +} +.summary-table dt code { + font-family:var(--code-font-family); + font-size:1em; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} +button { + font-family: var(--body-font-family); + font-size: 1em; +} +/* + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ +.about-language { + float:right; + padding:0 21px 8px 8px; + font-size:0.915em; + margin-top:-9px; + height:2.9em; +} +.legal-copy { + margin-left:.5em; +} +/* + * Styles for navigation bar. + */ +@media screen { + div.flex-box { + position:fixed; + display:flex; + flex-direction:column; + height: 100%; + width: 100%; + } + header.flex-header { + flex: 0 0 auto; + } + div.flex-content { + flex: 1 1 auto; + overflow-y: auto; + } +} +.top-nav { + background-color:var(--navbar-background-color); + color:var(--navbar-text-color); + float:left; + width:100%; + clear:right; + min-height:2.8em; + padding:10px 0 0 0; + overflow:hidden; + font-size:0.857em; +} +button#navbar-toggle-button { + display:none; +} +ul.sub-nav-list-small { + display: none; +} +.sub-nav { + background-color:var(--subnav-background-color); + float:left; + width:100%; + overflow:hidden; + font-size:0.857em; +} +.sub-nav div { + clear:left; + float:left; + padding:6px; + text-transform:uppercase; +} +.sub-nav .sub-nav-list { + padding-top:4px; +} +ul.nav-list { + display:block; + margin:0 25px 0 0; + padding:0; +} +ul.sub-nav-list { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.nav-list li { + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +.sub-nav .nav-list-search { + float:right; + margin:0; + padding:6px; + clear:none; + text-align:right; + position:relative; +} +ul.sub-nav-list li { + list-style:none; + float:left; +} +.top-nav a:link, .top-nav a:active, .top-nav a:visited { + color:var(--navbar-text-color); + text-decoration:none; + text-transform:uppercase; +} +.top-nav a:hover { + color:var(--link-color-active); +} +.nav-bar-cell1-rev { + background-color:var(--selected-background-color); + color:var(--selected-text-color); + margin: auto 5px; +} +.skip-nav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* + * Hide navigation links and search box in print layout + */ +@media print { + ul.nav-list, div.sub-nav { + display:none; + } +} +/* + * Styles for page header. + */ +.title { + color:var(--title-color); + margin:10px 0; +} +.sub-title { + margin:5px 0 0 0; +} +ul.contents-list { + margin: 0 0 15px 0; + padding: 0; + list-style: none; +} +ul.contents-list li { + font-size:0.93em; +} +/* + * Styles for headings. + */ +body.class-declaration-page .summary h2, +body.class-declaration-page .details h2, +body.class-use-page h2, +body.module-declaration-page .block-list h2 { + font-style: italic; + padding:0; + margin:15px 0; +} +body.class-declaration-page .summary h3, +body.class-declaration-page .details h3, +body.class-declaration-page .summary .inherited-list h2 { + background-color:var(--subnav-background-color); + border:1px solid var(--border-color); + margin:0 0 6px -8px; + padding:7px 5px; +} +/* + * Styles for page layout containers. + */ +main { + clear:both; + padding:10px 20px; + position:relative; +} +dl.notes > dt { + font-family: var(--body-font-family); + font-size:0.856em; + font-weight:bold; + margin:10px 0 0 0; + color:var(--body-text-color); +} +dl.notes > dd { + margin:5px 10px 10px 0; + font-size:1em; + font-family:var(--block-font-family) +} +dl.name-value > dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +dl.name-value > dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* + * Styles for lists. + */ +li.circle { + list-style:circle; +} +ul.horizontal li { + display:inline; + font-size:0.9em; +} +div.inheritance { + margin:0; + padding:0; +} +div.inheritance div.inheritance { + margin-left:2em; +} +ul.block-list, +ul.details-list, +ul.member-list, +ul.summary-list { + margin:10px 0 10px 0; + padding:0; +} +ul.block-list > li, +ul.details-list > li, +ul.member-list > li, +ul.summary-list > li { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.ref-list { + padding:0; + margin:0; +} +ul.ref-list > li { + list-style:none; +} +.summary-table dl, .summary-table dl dt, .summary-table dl dd { + margin-top:0; + margin-bottom:1px; +} +ul.tag-list, ul.tag-list-long { + padding-left: 0; + list-style: none; +} +ul.tag-list li { + display: inline; +} +ul.tag-list li:not(:last-child):after, +ul.tag-list-long li:not(:last-child):after +{ + content: ", "; + white-space: pre-wrap; +} +ul.preview-feature-list { + list-style: none; + margin:0; + padding:0.1em; + line-height: 1.6em; +} +/* + * Styles for tables. + */ +.summary-table, .details-table { + width:100%; + border-spacing:0; + border:1px solid var(--border-color); + border-top:0; + padding:0; +} +.caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:var(--selected-text-color); + clear:none; + overflow:hidden; + padding: 10px 0 0 1px; + margin:0; +} +.caption a:link, .caption a:visited { + color:var(--selected-link-color); +} +.caption a:hover, +.caption a:active { + color:var(--navbar-text-color); +} +.caption span { + font-weight:bold; + white-space:nowrap; + padding:5px 12px 7px 12px; + display:inline-block; + float:left; + background-color:var(--selected-background-color); + border: none; + height:16px; +} +div.table-tabs { + padding:10px 0 0 1px; + margin:10px 0 0 0; +} +div.table-tabs > button { + border: none; + cursor: pointer; + padding: 5px 12px 7px 12px; + font-weight: bold; + margin-right: 8px; +} +div.table-tabs > .active-table-tab { + background: var(--selected-background-color); + color: var(--selected-text-color); +} +div.table-tabs > button.table-tab { + background: var(--navbar-background-color); + color: var(--navbar-text-color); +} +.two-column-search-results { + display: grid; + grid-template-columns: minmax(400px, max-content) minmax(400px, auto); +} +div.checkboxes { + line-height: 2em; +} +div.checkboxes > span { + margin-left: 10px; +} +div.checkboxes > label { + margin-left: 8px; + white-space: nowrap; +} +div.checkboxes > label > input { + margin: 0 2px; +} +.two-column-summary { + display: grid; + grid-template-columns: minmax(25%, max-content) minmax(25%, auto); +} +.three-column-summary { + display: grid; + grid-template-columns: minmax(15%, max-content) minmax(20%, max-content) minmax(20%, auto); +} +.three-column-release-summary { + display: grid; + grid-template-columns: minmax(40%, max-content) minmax(10%, max-content) minmax(40%, auto); +} +.four-column-summary { + display: grid; + grid-template-columns: minmax(10%, max-content) minmax(15%, max-content) minmax(15%, max-content) minmax(15%, auto); +} +@media screen and (max-width: 1000px) { + .four-column-summary { + display: grid; + grid-template-columns: minmax(15%, max-content) minmax(15%, auto); + } +} +@media screen and (max-width: 800px) { + .two-column-search-results { + display: grid; + grid-template-columns: minmax(40%, max-content) minmax(40%, auto); + } + .three-column-summary { + display: grid; + grid-template-columns: minmax(10%, max-content) minmax(25%, auto); + } + .three-column-release-summary { + display: grid; + grid-template-columns: minmax(70%, max-content) minmax(30%, max-content) + } + .three-column-summary .col-last, + .three-column-release-summary .col-last{ + grid-column-end: span 2; + } +} +@media screen and (max-width: 600px) { + .two-column-summary { + display: grid; + grid-template-columns: 1fr; + } +} +.summary-table > div, .details-table > div { + text-align:left; + padding: 8px 3px 3px 7px; + overflow-x: auto; + scrollbar-width: thin; +} +.col-first, .col-second, .col-last, .col-constructor-name, .col-summary-item-name { + vertical-align:top; + padding-right:0; + padding-top:8px; + padding-bottom:3px; +} +.table-header { + background:var(--subnav-background-color); + font-weight: bold; +} +/* Sortable table columns */ +.table-header[onclick] { + cursor: pointer; +} +.table-header[onclick]::after { + content:""; + display:inline-block; + background-image:url('data:image/svg+xml; utf8, \ + \ + '); + background-size:100% 100%; + width:9px; + height:14px; + margin-left:4px; + margin-bottom:-3px; +} +.table-header[onclick].sort-asc::after { + background-image:url('data:image/svg+xml; utf8, \ + \ + \ + '); + +} +.table-header[onclick].sort-desc::after { + background-image:url('data:image/svg+xml; utf8, \ + \ + \ + '); +} +.col-first, .col-first { + font-size:0.93em; +} +.col-second, .col-second, .col-last, .col-constructor-name, .col-summary-item-name, .col-last { + font-size:0.93em; +} +.col-first, .col-second, .col-constructor-name { + vertical-align:top; + overflow: auto; +} +.col-last { + white-space:normal; +} +.col-first a:link, .col-first a:visited, +.col-second a:link, .col-second a:visited, +.col-first a:link, .col-first a:visited, +.col-second a:link, .col-second a:visited, +.col-constructor-name a:link, .col-constructor-name a:visited, +.col-summary-item-name a:link, .col-summary-item-name a:visited { + font-weight:bold; +} +.even-row-color, .even-row-color .table-header { + background-color:var(--even-row-color); +} +.odd-row-color, .odd-row-color .table-header { + background-color:var(--odd-row-color); +} +/* + * Styles for contents. + */ +div.block { + font-size:var(--body-font-size); + font-family:var(--block-font-family); +} +.col-last div { + padding-top:0; +} +.col-last a { + padding-bottom:3px; +} +.module-signature, +.package-signature, +.type-signature, +.member-signature { + font-family:var(--code-font-family); + font-size:1em; + margin:14px 0; + white-space: pre-wrap; +} +.module-signature, +.package-signature, +.type-signature { + margin-top: 0; +} +.member-signature .type-parameters-long, +.member-signature .parameters, +.member-signature .exceptions { + display: inline-block; + vertical-align: top; + white-space: pre; +} +.member-signature .type-parameters { + white-space: normal; +} +/* + * Styles for formatting effect. + */ +.source-line-no { + /* Color of line numbers in source pages can be set via custom property below */ + color:var(--source-linenumber-color, green); + padding:0 30px 0 0; +} +.block { + display:block; + margin:0 10px 5px 0; + color:var(--block-text-color); +} +.deprecated-label, .description-from-type-label, .implementation-label, .member-name-link, +.module-label-in-package, .module-label-in-type, .package-label-in-type, +.package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label { + font-weight:bold; +} +.deprecation-comment, .help-footnote, .preview-comment { + font-style:italic; +} +.deprecation-block { + font-size:1em; + font-family:var(--block-font-family); + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +.preview-block { + font-size:1em; + font-family:var(--block-font-family); + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecation-comment { + font-style:normal; +} +details.invalid-tag, span.invalid-tag { + font-size:1em; + font-family:var(--block-font-family); + color: var(--invalid-tag-text-color); + background: var(--invalid-tag-background-color); + border: thin solid var(--table-border-color); + border-radius:2px; + padding: 2px 4px; + display:inline-block; +} +details summary { + cursor: pointer; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-state-active { + /* Overrides the color of selection used in jQuery UI */ + background: var(--selected-background-color); + border: 1px solid var(--selected-background-color); + color: var(--selected-text-color); +} +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:var(--navbar-background-color); + color:var(--navbar-text-color); +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:auto; + overflow-x:auto; + scrollbar-width: thin; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:1; + background-color: var(--body-background-color); +} +ul.ui-autocomplete li { + float:left; + clear:both; + min-width:100%; +} +ul.ui-autocomplete li.ui-static-link { + position:sticky; + bottom:0; + left:0; + background: var(--subnav-background-color); + padding: 5px 0; + font-family: var(--body-font-family); + font-size: 0.93em; + font-weight: bolder; + z-index: 2; +} +li.ui-static-link a, li.ui-static-link a:visited { + text-decoration:none; + color:var(--link-color); + float:right; + margin-right:20px; +} +.ui-autocomplete .result-item { + font-size: inherit; +} +.ui-autocomplete .result-highlight { + font-weight:bold; +} +#search-input, #page-search-input { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + background-color: var(--search-input-background-color); + color: var(--search-input-text-color); + border-color: var(--border-color); + padding-left:20px; + width: 250px; + margin: 0; +} +#search-input { + margin-left: 4px; +} +#reset-button { + background-color: transparent; + background-image:url('resources/x.png'); + background-repeat:no-repeat; + background-size:contain; + border:0; + border-radius:0; + width:12px; + height:12px; + position:absolute; + right:12px; + top:10px; + font-size:0; +} +::placeholder { + color:var(--search-input-placeholder-color); + opacity: 1; +} +.search-tag-desc-result { + font-style:italic; + font-size:11px; +} +.search-tag-holder-result { + font-style:italic; + font-size:12px; +} +.search-tag-result:target { + background-color:var(--search-tag-highlight-color); +} +details.page-search-details { + display: inline-block; +} +div#result-container { + font-size: 1em; +} +div#result-container a.search-result-link { + padding: 0; + margin: 4px 0; + width: 100%; +} +#result-container .result-highlight { + font-weight:bolder; +} +.page-search-info { + background-color: var(--subnav-background-color); + border-radius: 3px; + border: 0 solid var(--border-color); + padding: 0 8px; + overflow: hidden; + height: 0; + transition: all 0.2s ease; +} +div.table-tabs > button.table-tab { + background: var(--navbar-background-color); + color: var(--navbar-text-color); +} +.page-search-header { + padding: 5px 12px 7px 12px; + font-weight: bold; + margin-right: 3px; + background-color:var(--navbar-background-color); + color:var(--navbar-text-color); + display: inline-block; +} +button.page-search-header { + border: none; + cursor: pointer; +} +span#page-search-link { + text-decoration: underline; +} +.module-graph span, .sealed-graph span { + display:none; + position:absolute; +} +.module-graph:hover span, .sealed-graph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.inherited-list { + margin: 10px 0 10px 0; +} +section.class-description { + line-height: 1.4; +} +.summary section[class$="-summary"], .details section[class$="-details"], +.class-uses .detail, .serialized-class-details { + padding: 0 20px 5px 10px; + border: 1px solid var(--border-color); + background-color: var(--section-background-color); +} +.inherited-list, section[class$="-details"] .detail { + padding:0 0 5px 8px; + background-color:var(--detail-background-color); + border:none; +} +.vertical-separator { + padding: 0 5px; +} +ul.help-section-list { + margin: 0; +} +ul.help-subtoc > li { + display: inline-block; + padding-right: 5px; + font-size: smaller; +} +ul.help-subtoc > li::before { + content: "\2022" ; + padding-right:2px; +} +.help-note { + font-style: italic; +} +/* + * Indicator icon for external links. + */ +main a[href*="://"]::after { + content:""; + display:inline-block; + background-image:url('data:image/svg+xml; utf8, \ + \ + \ + '); + background-size:100% 100%; + width:7px; + height:7px; + margin-left:2px; + margin-bottom:4px; +} +main a[href*="://"]:hover::after, +main a[href*="://"]:focus::after { + background-image:url('data:image/svg+xml; utf8, \ + \ + \ + '); +} +/* + * Styles for header/section anchor links + */ +a.anchor-link { + opacity: 0; + transition: opacity 0.1s; +} +:hover > a.anchor-link { + opacity: 80%; +} +a.anchor-link:hover, +a.anchor-link:focus-visible, +a.anchor-link.visible { + opacity: 100%; +} +a.anchor-link > img { + width: 0.9em; + height: 0.9em; +} +/* + * Styles for copy-to-clipboard buttons + */ +button.copy { + opacity: 70%; + border: none; + border-radius: 3px; + position: relative; + background:none; + transition: opacity 0.3s; + cursor: pointer; +} +:hover > button.copy { + opacity: 80%; +} +button.copy:hover, +button.copy:active, +button.copy:focus-visible, +button.copy.visible { + opacity: 100%; +} +button.copy img { + position: relative; + background: none; + filter: brightness(var(--copy-icon-brightness)); +} +button.copy:active { + background-color: var(--copy-button-background-color-active); +} +button.copy span { + color: var(--body-text-color); + position: relative; + top: -0.1em; + transition: all 0.1s; + font-size: 0.76rem; + line-height: 1.2em; + opacity: 0; +} +button.copy:hover span, +button.copy:focus-visible span, +button.copy.visible span { + opacity: 100%; +} +/* search page copy button */ +button#page-search-copy { + margin-left: 0.4em; + padding:0.3em; + top:0.13em; +} +button#page-search-copy img { + width: 1.2em; + height: 1.2em; + padding: 0.01em 0; + top: 0.15em; +} +button#page-search-copy span { + color: var(--body-text-color); + line-height: 1.2em; + padding: 0.2em; + top: -0.18em; +} +div.page-search-info:hover button#page-search-copy span { + opacity: 100%; +} +/* snippet copy button */ +button.snippet-copy { + position: absolute; + top: 6px; + right: 6px; + height: 1.7em; + padding: 2px; +} +button.snippet-copy img { + width: 18px; + height: 18px; + padding: 0.05em 0; +} +button.snippet-copy span { + line-height: 1.2em; + padding: 0.2em; + position: relative; + top: -0.5em; +} +div.snippet-container:hover button.snippet-copy span { + opacity: 100%; +} +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid var(--table-border-color); +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid var(--table-border-color); +} +table.striped { + border-collapse: collapse; + border: 1px solid var(--table-border-color); +} +table.striped > thead { + background-color: var(--subnav-background-color); +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid var(--table-border-color); +} +table.striped > tbody > tr:nth-child(even) { + background-color: var(--odd-row-color) +} +table.striped > tbody > tr:nth-child(odd) { + background-color: var(--even-row-color) +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid var(--table-border-color); + border-right: 1px solid var(--table-border-color); +} +table.striped > tbody > tr > th { + font-weight: normal; +} +/** + * Tweak style for small screens. + */ +@media screen and (max-width: 920px) { + header.flex-header { + max-height: 100vh; + overflow-y: auto; + } + div#navbar-top { + height: 2.8em; + transition: height 0.35s ease; + } + ul.nav-list { + display: block; + width: 40%; + float:left; + clear: left; + margin: 10px 0 0 0; + padding: 0; + } + ul.nav-list li { + float: none; + padding: 6px; + margin-left: 10px; + margin-top: 2px; + } + ul.sub-nav-list-small { + display:block; + height: 100%; + width: 50%; + float: right; + clear: right; + background-color: var(--subnav-background-color); + color: var(--body-text-color); + margin: 6px 0 0 0; + padding: 0; + } + ul.sub-nav-list-small ul { + padding-left: 20px; + } + ul.sub-nav-list-small a:link, ul.sub-nav-list-small a:visited { + color:var(--link-color); + } + ul.sub-nav-list-small a:hover { + color:var(--link-color-active); + } + ul.sub-nav-list-small li { + list-style:none; + float:none; + padding: 6px; + margin-top: 1px; + text-transform:uppercase; + } + ul.sub-nav-list-small > li { + margin-left: 10px; + } + ul.sub-nav-list-small li p { + margin: 5px 0; + } + div#navbar-sub-list { + display: none; + } + .top-nav a:link, .top-nav a:active, .top-nav a:visited { + display: block; + } + button#navbar-toggle-button { + width: 3.4em; + height: 2.8em; + background-color: transparent; + display: block; + float: left; + border: 0; + margin: 0 10px; + cursor: pointer; + font-size: 10px; + } + button#navbar-toggle-button .nav-bar-toggle-icon { + display: block; + width: 24px; + height: 3px; + margin: 1px 0 4px 0; + border-radius: 2px; + transition: all 0.1s; + background-color: var(--navbar-text-color); + } + button#navbar-toggle-button.expanded span.nav-bar-toggle-icon:nth-child(1) { + transform: rotate(45deg); + transform-origin: 10% 10%; + width: 26px; + } + button#navbar-toggle-button.expanded span.nav-bar-toggle-icon:nth-child(2) { + opacity: 0; + } + button#navbar-toggle-button.expanded span.nav-bar-toggle-icon:nth-child(3) { + transform: rotate(-45deg); + transform-origin: 10% 90%; + width: 26px; + } +} +@media screen and (max-width: 800px) { + .about-language { + padding-right: 16px; + } + ul.nav-list li { + margin-left: 5px; + } + ul.sub-nav-list-small > li { + margin-left: 5px; + } + main { + padding: 10px; + } + .summary section[class$="-summary"], .details section[class$="-details"], + .class-uses .detail, .serialized-class-details { + padding: 0 8px 5px 8px; + } + body { + -webkit-text-size-adjust: none; + } +} +@media screen and (max-width: 400px) { + .about-language { + font-size: 10px; + padding-right: 12px; + } +} +@media screen and (max-width: 400px) { + .nav-list-search { + width: 94%; + } + #search-input, #page-search-input { + width: 70%; + } +} +@media screen and (max-width: 320px) { + .nav-list-search > label { + display: none; + } + .nav-list-search { + width: 90%; + } + #search-input, #page-search-input { + width: 80%; + } +} + +pre.snippet { + background-color: var(--snippet-background-color); + color: var(--snippet-text-color); + padding: 10px; + margin: 12px 0; + overflow: auto; + white-space: pre; +} +div.snippet-container { + position: relative; +} +@media screen and (max-width: 800px) { + pre.snippet { + padding-top: 26px; + } + button.snippet-copy { + top: 4px; + right: 4px; + } +} +pre.snippet .italic { + font-style: italic; +} +pre.snippet .bold { + font-weight: bold; +} +pre.snippet .highlighted { + background-color: var(--snippet-highlight-color); + border-radius: 10%; +} diff --git a/0.9.16/_static/javadoc/tag-search-index.js b/0.9.16/_static/javadoc/tag-search-index.js new file mode 100644 index 0000000..f2a440c --- /dev/null +++ b/0.9.16/_static/javadoc/tag-search-index.js @@ -0,0 +1 @@ +tagSearchIndex = [{"l":"Constant Field Values","h":"","u":"constant-values.html"}];updateSearchResults(); \ No newline at end of file diff --git a/0.9.16/_static/javadoc/type-search-index.js b/0.9.16/_static/javadoc/type-search-index.js new file mode 100644 index 0000000..89f5470 --- /dev/null +++ b/0.9.16/_static/javadoc/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"l":"All Classes and Interfaces","u":"allclasses-index.html"},{"p":"org.hansken.plugin.extraction.util","l":"ArgChecks"},{"p":"org.hansken.plugin.extraction.api","l":"Author"},{"p":"org.hansken.plugin.extraction.api","l":"BaseExtractionPlugin"},{"p":"org.hansken.plugin.extraction.api","l":"BatchSearchResult"},{"p":"org.hansken.plugin.extraction.api","l":"Author.Builder"},{"p":"org.hansken.plugin.extraction.api","l":"PluginInfo.Builder"},{"p":"org.hansken.plugin.extraction.api","l":"PluginResources.Builder"},{"p":"org.hansken.plugin.extraction.api.transformations","l":"RangedDataTransformation.Builder"},{"p":"org.hansken.plugin.extraction.api","l":"SearchOptions.Builder"},{"p":"org.hansken.plugin.extraction.api","l":"SearchSortOption.Builder"},{"p":"org.hansken.plugin.extraction.api","l":"DataContext"},{"p":"org.hansken.plugin.extraction.api.transformations","l":"DataRange"},{"p":"org.hansken.plugin.extraction.api.transformations","l":"DataTransformation"},{"p":"org.hansken.plugin.extraction.api","l":"DataWriter"},{"p":"org.hansken.plugin.extraction.api","l":"DeferredExtractionPlugin"},{"p":"org.hansken.plugin.extraction.api","l":"DeferredMetaExtractionPlugin"},{"p":"org.hansken.plugin.extraction.api","l":"SearchSortOption.Direction"},{"p":"org.hansken.plugin.extraction.api","l":"ExtractionPlugin"},{"p":"org.hansken.plugin.extraction.api","l":"ImmutableTrace"},{"p":"org.hansken.plugin.extraction.api","l":"LatLong"},{"p":"org.hansken.plugin.extraction.api","l":"MaturityLevel"},{"p":"org.hansken.plugin.extraction.api","l":"MetaExtractionPlugin"},{"p":"org.hansken.plugin.extraction.api","l":"PluginId"},{"p":"org.hansken.plugin.extraction.api","l":"PluginInfo"},{"p":"org.hansken.plugin.extraction.api","l":"PluginResources"},{"p":"org.hansken.plugin.extraction.api","l":"PluginType"},{"p":"org.hansken.plugin.extraction.api","l":"RandomAccessData"},{"p":"org.hansken.plugin.extraction.api.transformations","l":"RangedDataTransformation"},{"p":"org.hansken.plugin.extraction.api","l":"SearchOptions"},{"p":"org.hansken.plugin.extraction.api","l":"SearchResult"},{"p":"org.hansken.plugin.extraction.api","l":"SearchScope"},{"p":"org.hansken.plugin.extraction.api","l":"SearchSortOption"},{"p":"org.hansken.plugin.extraction.api","l":"SearchTrace"},{"p":"org.hansken.plugin.extraction.util","l":"ThrowingConsumer"},{"p":"org.hansken.plugin.extraction.api","l":"Trace"},{"p":"org.hansken.plugin.extraction.api","l":"Trace.Tracelet"},{"p":"org.hansken.plugin.extraction.api","l":"Trace.TraceletBuilder"},{"p":"org.hansken.plugin.extraction.api","l":"Trace.TraceletProperty"},{"p":"org.hansken.plugin.extraction.api","l":"TraceSearcher"},{"p":"org.hansken.plugin.extraction.api","l":"TransformerArgument"},{"p":"org.hansken.plugin.extraction.api","l":"TransformerLabel"},{"p":"org.hansken.plugin.extraction.api","l":"Vector"}];updateSearchResults(); \ No newline at end of file diff --git a/0.9.16/_static/jquery.js b/0.9.16/_static/jquery.js new file mode 100644 index 0000000..c4c6022 --- /dev/null +++ b/0.9.16/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0
    "),n("table.docutils.footnote").wrap("
    "),n("table.docutils.citation").wrap("
    "),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t a.language.name.localeCompare(b.language.name)); + + const languagesHTML = ` +
    +
    Languages
    + ${languages + .map( + (translation) => ` +
    + ${translation.language.code} +
    + `, + ) + .join("\n")} +
    + `; + return languagesHTML; + } + + function renderVersions(config) { + if (!config.versions.active.length) { + return ""; + } + const versionsHTML = ` +
    +
    Versions
    + ${config.versions.active + .map( + (version) => ` +
    + ${version.slug} +
    + `, + ) + .join("\n")} +
    + `; + return versionsHTML; + } + + function renderDownloads(config) { + if (!Object.keys(config.versions.current.downloads).length) { + return ""; + } + const downloadsNameDisplay = { + pdf: "PDF", + epub: "Epub", + htmlzip: "HTML", + }; + + const downloadsHTML = ` +
    +
    Downloads
    + ${Object.entries(config.versions.current.downloads) + .map( + ([name, url]) => ` +
    + ${downloadsNameDisplay[name]} +
    + `, + ) + .join("\n")} +
    + `; + return downloadsHTML; + } + + document.addEventListener("readthedocs-addons-data-ready", function (event) { + const config = event.detail.data(); + + const flyout = ` +
    + + Read the Docs + v: ${config.versions.current.slug} + + +
    +
    + ${renderLanguages(config)} + ${renderVersions(config)} + ${renderDownloads(config)} +
    +
    On Read the Docs
    +
    + Project Home +
    +
    + Builds +
    +
    + Downloads +
    +
    +
    +
    Search
    +
    +
    + +
    +
    +
    +
    + + Hosted by Read the Docs + +
    +
    + `; + + // Inject the generated flyout into the body HTML element. + document.body.insertAdjacentHTML("beforeend", flyout); + + // Trigger the Read the Docs Addons Search modal when clicking on the "Search docs" input from inside the flyout. + document + .querySelector("#flyout-search-form") + .addEventListener("focusin", () => { + const event = new CustomEvent("readthedocs-search-show"); + document.dispatchEvent(event); + }); + }) +} + +if (themeLanguageSelector || themeVersionSelector) { + function onSelectorSwitch(event) { + const option = event.target.selectedIndex; + const item = event.target.options[option]; + window.location.href = item.dataset.url; + } + + document.addEventListener("readthedocs-addons-data-ready", function (event) { + const config = event.detail.data(); + + const versionSwitch = document.querySelector( + "div.switch-menus > div.version-switch", + ); + if (themeVersionSelector) { + let versions = config.versions.active; + if (config.versions.current.hidden || config.versions.current.type === "external") { + versions.unshift(config.versions.current); + } + const versionSelect = ` + + `; + + versionSwitch.innerHTML = versionSelect; + versionSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); + } + + const languageSwitch = document.querySelector( + "div.switch-menus > div.language-switch", + ); + + if (themeLanguageSelector) { + if (config.projects.translations.length) { + // Add the current language to the options on the selector + let languages = config.projects.translations.concat( + config.projects.current, + ); + languages = languages.sort((a, b) => + a.language.name.localeCompare(b.language.name), + ); + + const languageSelect = ` + + `; + + languageSwitch.innerHTML = languageSelect; + languageSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); + } + else { + languageSwitch.remove(); + } + } + }); +} + +document.addEventListener("readthedocs-addons-data-ready", function (event) { + // Trigger the Read the Docs Addons Search modal when clicking on "Search docs" input from the topnav. + document + .querySelector("[role='search'] input") + .addEventListener("focusin", () => { + const event = new CustomEvent("readthedocs-search-show"); + document.dispatchEvent(event); + }); +}); \ No newline at end of file diff --git a/0.9.16/_static/language_data.js b/0.9.16/_static/language_data.js new file mode 100644 index 0000000..367b8ed --- /dev/null +++ b/0.9.16/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, if available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/0.9.16/_static/minus.png b/0.9.16/_static/minus.png new file mode 100644 index 0000000..d96755f Binary files /dev/null and b/0.9.16/_static/minus.png differ diff --git a/0.9.16/_static/plus.png b/0.9.16/_static/plus.png new file mode 100644 index 0000000..7107cec Binary files /dev/null and b/0.9.16/_static/plus.png differ diff --git a/0.9.16/_static/pygments.css b/0.9.16/_static/pygments.css new file mode 100644 index 0000000..22c2539 --- /dev/null +++ b/0.9.16/_static/pygments.css @@ -0,0 +1,75 @@ +pre { line-height: 125%; } +td.linenos .normal { color: #666666; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: #666666; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f0f0f0; } +.highlight .c { color: #60A0B0; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #F00 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666 } /* Operator */ +.highlight .ch { color: #60A0B0; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #60A0B0; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #60A0B0; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #60A0B0; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #60A0B0; background-color: #FFF0F0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #F00 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888 } /* Generic.Output */ +.highlight .gp { color: #C65D09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #04D } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #40A070 } /* Literal.Number */ +.highlight .s { color: #4070A0 } /* Literal.String */ +.highlight .na { color: #4070A0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0E84B5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60ADD5 } /* Name.Constant */ +.highlight .nd { color: #555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #D55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287E } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0E84B5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #BB60D5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #BBB } /* Text.Whitespace */ +.highlight .mb { color: #40A070 } /* Literal.Number.Bin */ +.highlight .mf { color: #40A070 } /* Literal.Number.Float */ +.highlight .mh { color: #40A070 } /* Literal.Number.Hex */ +.highlight .mi { color: #40A070 } /* Literal.Number.Integer */ +.highlight .mo { color: #40A070 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070A0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070A0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070A0 } /* Literal.String.Char */ +.highlight .dl { color: #4070A0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070A0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070A0 } /* Literal.String.Double */ +.highlight .se { color: #4070A0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070A0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70A0D0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #C65D09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070A0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287E } /* Name.Function.Magic */ +.highlight .vc { color: #BB60D5 } /* Name.Variable.Class */ +.highlight .vg { color: #BB60D5 } /* Name.Variable.Global */ +.highlight .vi { color: #BB60D5 } /* Name.Variable.Instance */ +.highlight .vm { color: #BB60D5 } /* Name.Variable.Magic */ +.highlight .il { color: #40A070 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/0.9.16/_static/searchtools.js b/0.9.16/_static/searchtools.js new file mode 100644 index 0000000..92da3f8 --- /dev/null +++ b/0.9.16/_static/searchtools.js @@ -0,0 +1,619 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlinks", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/0.9.16/_static/sphinx_highlight.js b/0.9.16/_static/sphinx_highlight.js new file mode 100644 index 0000000..8a96c69 --- /dev/null +++ b/0.9.16/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/0.9.16/_static/wider_pages.css b/0.9.16/_static/wider_pages.css new file mode 100644 index 0000000..bf5fc66 --- /dev/null +++ b/0.9.16/_static/wider_pages.css @@ -0,0 +1,3 @@ +.wy-nav-content { + max-width: 1200px !important; +} diff --git a/0.9.16/changes.html b/0.9.16/changes.html new file mode 100644 index 0000000..760861f --- /dev/null +++ b/0.9.16/changes.html @@ -0,0 +1,833 @@ + + + + + + + + + Changelog — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Changelog

    +

    The following page lists all (technical) changes in the extraction plugin SDK.

    +

    Programming language specific API changes are described in more detail on API changelog pages. +These pages list new API functionalities, and describe how to update your plugins when API changes are in order. +For the API changelog pages see:

    + +
    +

    Release-0.9.16 +

    +
      +
    • HANSKEN-23424: Introduce PLUGIN_PORT environment variable to enable overriding default GRPC port 8999

    • +
    • HANSKEN-23401: Update external dependencies for Extraction Plugin Python SDK

    • +
    • HANSKEN-23402: Fix compatibility issues with newer logbook versions for (Python)

    • +
    • HANSKEN-23403: Fix standalone test framework not working (since 0.9.10)

    • +
    • HANSKEN-23399: Update external dependencies for Extraction Plugin Java SDK

    • +
    +
    +
    +

    Release-0.9.15

    +
    +
    +

    Release-0.9.14

    +
      +
    • HANSKEN-23330: Fix bug where adding properties to data stream failed with IllegalStateException

    • +
    +
    +
    +

    Release-0.9.13

    +
      +
    • HANSKEN-23258: Add new field bulkMode to PluginInfo

    • +
    +
    +
    +

    Release-0.9.12

    +
      +
    • HANSKEN-23051: Fix bug where reading lots of data or searching for multiple child traces in a Python plugin would cause an RpcSyncAck error

    • +
    +
    +
    +

    Release-0.9.11

    +
      +
    • HANSKEN-22900: Fix typo in resource labels created by Maven for Java plugins

    • +
    • HANSKEN-22755: Add batched search result to allow for getting infinite results for Java plugins

    • +
    • HANSKEN-22730: Fix the build and release pipeline of the hansken extraction plugin sdk

    • +
    +
    +
    +

    Release-0.9.10

    +
      +
    • HANSKEN-22788: Allow JSON test results to be compared line by line, to avoid memory issues when comparing large files

    • +
    • HANSKEN-22728: Add batched search result to allow for getting infinite results for Python plugins

    • +
    • HANSKEN-22724: Improve searcher for Deferred Plugins

    • +
    • HANSKEN-22752: Add deferred meta extraction plugins to the Java framework

    • +
    +
    +
    +

    Release-0.9.9

    +
      +
    • HANSKEN-22647: Add deferred meta extraction plugins to the test framework

    • +
    • HANSKEN-22639: Added documentation for the DeferredMetaExtractionPlugin

    • +
    • HANSKEN-22638: Plugin runner should be able to process DeferredMetaExtractionPlugin

    • +
    • HANSKEN-22637: Add support to extraction plugin server with DeferredMetaExtractionPlugin

    • +
    • HANSKEN-22636: Support DeferredMetaExtractionPlugin in pack()

    • +
    • HANSKEN-22635: Add DeferredMetaExtractionPlugin as plugin base class

    • +
    • HANSKEN-22634: Add DeferredMetaExtractionPlugin type to gRPC protocol

    • +
    • HANSKEN-22172: Adjust Jenkins pipeline to show red builds after pushing while a build is still going on

    • +
    • HANSKEN-22500: Enable loading a plugin from either a file (dir/plugin.py) or an object reference (my_module:AwesomePlugin)

    • +
    +
    +
    +

    Release-0.9.8

    +
      +
    • HANSKEN-22505: Correctly write nested maps with sibling values in tests, to avoid missing misc properties

    • +
    +
    +
    +

    Release-0.9.7

    +
      +
    • HANSKEN-22279: Expose newly added tracelets in Trace interface

    • +
    +
    +
    +

    Release-0.9.6

    +
      +
    • HANSKEN-22002: Fix Error occured during initialization of VM error that was caused by inadvertently including jmockit in the super-pom

    • +
    • HANSKEN-21689: Add a build_plugin_ci utility that can be used to build plugins in a pipeline in a more reliable way

    • +
    • HANSKEN-21942: Updated the release process notes with additional steps

    • +
    +
    +
    +

    Release-0.9.5

    +
      +
    • HANSKEN-21817: Change transformer argument types ‘long’ into ‘int’ and ‘double’ into ‘real’

    • +
    • HANSKEN-21819: Updated documentation of transformer, datetime, supported return type and Rest Call

    • +
    • HANSKEN-21818: Fix deserializing LatLongs

    • +
    • HANSKEN-21840: Fix bug in testing framework that switched around actual and expected

    • +
    +
    +
    +

    Release-0.9.4

    +
      +
    • HANSKEN-21816: Fix for Stream is already completed, no further calls are allowed that was caused by an RpcSync being sent after RpcFinish

    • +
    • HANSKEN-21436: Update to JDK 21

    • +
    • HANSKEN-21803: Fix dict object retrieved when requesting image property of trace

    • +
    • HANSKEN-21694: Fixed datetime serialization error in Transformer plugins

    • +
    • HANSKEN-21540: Support all types of arguments when executing a transformer using execute_transformer

    • +
    +
    +
    +

    Release-0.9.2

    +
      +
    • HANSKEN-21135: Implement flow control to avoid flooding the client with messages, (fixes connection RST)

    • +
    • HANSKEN-21684: Fixed wrong transformer primitive type mapping and sequence in deserializer

    • +
    • HANSKEN-21582: Improve test to improve build and release stability

    • +
    +
    +
    +

    Release-0.9.1

    +
      +
    • HANSKEN-21684: Fix python wheel not including generated proto files

    • +
    +
    +
    +

    Release-0.9.0

    +
      +
    • HANSKEN-21495: Add timeout option to build_plugin and label_plugin scripts and renamed the name option to target-name

    • +
    • HANSKEN-21571: Implement serialization from JSON to TransformerArgument

    • +
    • HANSKEN-21385: Enhance support for transformer arguments to accommodate multiple parameter types

    • +
    • HANSKEN-21411: Update build_plugin and label_plugin scripts to output docker container logs to terminal

    • +
    • HANSKEN-21221: Add option to execute transformers in Python plugins by implementing transform

    • +
    • HANSKEN-21222: Implemented transform for the ExtractionPluginClient and extraction_plugin_server.py

    • +
    • HANSKEN-21073: Add script to call transform function on a running plugin

    • +
    • HANSKEN-21247: Merge transformer class from HANSKEN-21218 and HANSKEN-21219

    • +
    • HANSKEN-21219: Add decorator to API that analyzes and registers decorated python functions

    • +
    +
    +
    +

    Release-0.8.4

    +
      +
    • HANSKEN-21220: Allow label_plugin script to set transformer labels on Docker images

    • +
    • HANSKEN-21217: Update Protobuf plugininfo definition with a list of transform method signatures

    • +
    • HANSKEN-21218: Support serializing and deserializing of plugininfo.tranformers in Python

    • +
    • HANSKEN-21486: Fixed the label_plugin script to support the same docker parameters as build_plugin.

    • +
    • HANSKEN-21410: Removed support for Python versions 3.8 and 3.9 and added support for Python versions 3.11, 3.12 and 3.13

    • +
    +
    +
    +

    Release-0.8.3

    +
      +
    • HANSKEN-21097: Keep health and pluginInfo calls responsive when plugin is busy (Python).

    • +
    • HANSKEN-21132: Fail with a clear message when reading data of a trace without data (Python).

    • +
    +
    +
    +

    Release-0.8.2

    +
      +
    • HANSKEN-21104: Reduce the level of details for some debug-logs (Python)

    • +
    • HANSKEN-21130: Use a default_buffer_size of 6M for trace.open() calls.

    • +
    • HANSKEN-21096: Support new buffer_size argument also for searched traces data reads (.open(buffer_size=...)).

    • +
    • HANSKEN-20962: Add option to specify read and write buffers, and support mode w for trace.open(...) (python).

    • +
    • HANSKEN-20938: Update build_plugin, to not require a fully installed environment when running building and labeling a plugin.

    • +
    • HANSKEN-20852: Plugin client: change log level of wrapped StatusRuntimeExceptions from INFO to DEBUG for less verbose logging.

    • +
    +
    +
    +

    Release-0.8.1

    +
      +
    • HANSKEN-20824: Performance improvement Python: never execute reads of size 0 over grpc (e.g. when using pillow).

    • +
    • HANSKEN-20812: Relax python sdk dependencies (to be compatible with Tensorflow).

    • +
    • HANSKEN-20814: Support lists of ints and doubles in the test framework

    • +
    • HANSKEN-20813: Let test framework write runtime profiles to txt files in tests results folders

    • +
    • HANSKEN-20735: Add basic profiling to Python extraction plugins for performance debugging in Hansken.

    • +
    • HANSKEN-20733: Set number of gRPC connections equal to the number of workers, to support improved better load balancing strategies (Python).

    • +
    +
    +
    +

    Release-0.8.0

    +
      +
    • HANSKEN-20128: Scope trace searches by default to the image under extraction, but allow project-wide searches by passing an optional argument (Java).

    • +
    • HANSKEN-20127: Scope trace searches by default to the image under extraction, but allow project-wide searches by passing an optional argument (Python).

    • +
    • HANSKEN-20552: Support trace property types of list[float] (Python), List (Java), List (Java), and List (Java).

    • +
    • HANSKEN-20389: Update project dependencies

    • +
    +
    +
    +

    Release-0.7.4

    +
      +
    • HANSKEN-20410: Fix label_plugin and build_plugin were not packaged correctly

    • +
    +
    +
    +

    Release-0.7.3

    +
      +
    • HANSKEN-19436: Introduced label_plugin utility as replacement for build_plugin

    • +
    +
    +
    +

    Release-0.7.2

    +
      +
    • HANSKEN-19954: Wait for slow plugins to start before testing (Python test framework)

    • +
    • HANSKEN-14216: Use Docker API instead of subprocess (Python test framework)

    • +
    +
    +
    +

    Release-0.7.1

    +
      +
    • HANSKEN-19759: Fix bug where wildcard in matcher query did not match on multiline values

    • +
    • HANSKEN-19064: Allow plugins to import local modules (Python) (second attempt)

    • +
    • HANSKEN-19448: Prettier exception when test_plugin can not load plugin

    • +
    • HANSKEN-19447: Test java and docker in test framework, to give the user better error messages if java/docker is missing or is outdated

    • +
    • HANSKEN-19435: Unclutter test framework output in case of failure and fail with correct exit code (Python)

    • +
    • HANSKEN-19151: Added configurable workers to the plugin resources

    • +
    +
    +
    +

    Release-0.7.0

    +
      +
    • HANSKEN-18677: Added HQL-Lite auto-escaping & fixed fullmatch wildcard support

    • +
    • HANSKEN-19179: Update all project dependencies

    • +
    • HANSKEN-19148: Improve build_plugin and test framework output (by passing subprocess output directly to the terminal)

    • +
    • HANSKEN-19076: Exposed API version through the ExtractionPluginClient

    • +
    • HANSKEN-18830: Added the Hansken AIO DebugExtractionPluginTool to the docs

    • +
    • HANSKEN-19065: Update link to extraction plugin examples (now hosted on Github)

    • +
    • HANSKEN-19064: Allow plugins to import local modules (Python)

    • +
    • HANSKEN-17675: Enable writing streaming data from Python

    • +
    • HANSKEN-18982: Improve error messages for client-side exceptions caught by gRPC (also for deferred plugins)

    • +
    +
    +
    +

    Release-0.6.3

    +
      +
    • HANSKEN-18915: Update all project dependencies

    • +
    • HANSKEN-18907: Upgrade to antlr 4.9.3

    • +
    • HANSKEN-18883: Allow writing multiple datastreams to a trace concurrently

    • +
    • HANSKEN-18673: Improve error messages for client-side exceptions caught by gRPC

    • +
    • HANSKEN-18517: Improve Python documentation for creating nested traces

    • +
    • HANSKEN-18400: Building docs with tox uses docutils 0.18.1

    • +
    • HANSKEN-17556: Enables writing to traces/child traces out of order

    • +
    +
    +
    +

    Release-0.6.2

    +
      +
    • HANSKEN-17692: [EXPERIMENTAL] Add Python support for previews, and extend test-framework to support them as well

    • +
    • HANSKEN-17742: Raise FileNotFoundError instead of logging an error when the plugin’s file does not exist

    • +
    • HANSKEN-17786: Update grpc dependencies to 1.48.2 to fix CVE-2022-3509

    • +
    • HANSKEN-17636: Improve explanation on “Match on specific datastream type”

    • +
    • HANSKEN-17672: Add a nice JB cartoon to the SDK docs landing page

    • +
    • HANSKEN-17502: Fix org.hansken.plugin-info.id label for java plugins

    • +
    • HANSKEN-17460: Update Flits to 3.7.1

    • +
    +
    +
    +

    Release-0.6.1

    +
      +
    • HANSKEN-17265: Added a parameter to build_plugin.py to extend the docker command for proxy settings

    • +
    • HANSKEN-17264: Remove PortUtil and expose listening ports

    • +
    • HANSKEN-17276: Move external getting started to the SDK documentation

    • +
    • HANSKEN-17274: Fix broken external links to Hansken website

    • +
    • HANSKEN-17278: Add url and license to SDK Python package info

    • +
    • HANSKEN-17203: Publish new SDK releases to maven central (Java)

    • +
    • HANSKEN-17277: Rearrange code snippets documentation

    • +
    • HANSKEN-17273: Update Checkstyle

    • +
    • HANSKEN-17214: Fix issues from static code analysis

    • +
    +
    +
    +

    Release-0.6.0

    +
      +
    • HANSKEN-17196: Downgrade API compatability level to 0.5.0

    • +
    • HANSKEN-17194: Update project dependencies to latest versions

    • +
    • HANSKEN-16781: Remove the need for plugin=self and moved id to 1st arg when creating a PluginInfo in Python SDK

    • +
    • HANSKEN-17191: Add quicklinks to the documentation index

    • +
    • HANSKEN-16756: Read extraction plugin version from plugin mavens project.version

    • +
    • HANSKEN-16705: Improve apis for declaring plugin resources and querying the data context at runtime

    • +
    • HANSKEN-17151: Store Plugin info in plugin image labels for Python plugins

    • +
    • HANSKEN-16753: Store Plugin info in plugin image labels for Java plugins

    • +
    • HANSKEN-17178: Updated Python tracelet documentation to contain a working example

    • +
    +
    +
    +

    Release-0.5.1

    +
      +
    • HANSKEN-17141: Fixed $data.type=... matcher when using run_with_hanskenpy (Python)

    • +
    • HANSKEN-16908: Added gRPC health service for Python Extraction Plugins

    • +
    • HANSKEN-17138: Avoid multiple plugins running on the same hostname:port (Python)

    • +
    • HANSKEN-14755: Use Python test framework wrapper with manually started plugins

    • +
    • HANSKEN-16905: Added gRPC health service for Java Extraction Plugins

    • +
    • HANSKEN-16901: Exclude old guava version to be able to run RemoteExtractionPluginFlits from Intellij

    • +
    • HANSKEN-16900: TestTraceSearcher will now return searched traces in natural sorted order of their file names

    • +
    • HANSKEN-16725: Improve tracelet api in Python SDK

    • +
    • HANSKEN-16764: Corrected ‘Adding data to traces’ code snippets

    • +
    • HANSKEN-16704: Use Python’s dataclasses where applicable

    • +
    • HANSKEN-17064: Improve runtime packing type checks to allow Sequence / Mapping compatible values

    • +
    +
    +
    +

    Release-0.5.0

    +
      +
    • HANSKEN-16638: Improve tracelet api in Java SDK

    • +
    • HANSKEN-16576: Support vector data type in Python SDK

    • +
    • HANSKEN-16707: Update build dependencies, build and test for Python 3.10

    • +
    • HANSKEN-16575: Support vector data type in Java SDK

    • +
    • HANSKEN-16574: Support vector data type in common SDK

    • +
    +
    +
    +

    Release-0.4.14

    +
      +
    • HANSKEN-16632: Fix execution of meta-extraction plugins with hansken.py runner which failed with an ‘expected $data in matcher’ error

    • +
    • HANSKEN-16634: Allow forward compatibility with Hansken by introducing an GRPC API version

    • +
    • HANSKEN-16489: Let build pipeline publish Java artifacts to community

    • +
    • HANSKEN-16558: Serve SDK test framework errors in a more developer-friendly way

    • +
    • HANSKEN-16489: Removed incompatibility warning for All In One with Hansken.py

    • +
    • HANSKEN-16403: Fixed running markdownlint with tox -e markdownlint

    • +
    • HANSKEN-16268: Added * value support to the HQL-Lite term matcher, improved documentation by using HQL default property:value instead of property=value

    • +
    • HANSKEN-16258: Fixed Jenkins build

    • +
    • HANSKEN-16257: Fixed docker stop command in test framework

    • +
    +
    +
    +

    Release-0.4.13

    +
      +
    • HANSKEN-16229: Fixed SDK documentation not correctly zipped

    • +
    • HANSKEN-16095: Documentation: added Test framework data-stream type note

    • +
    • HANSKEN-15961: Redundant plugin errors in the client set to log level debug

    • +
    • HANSKEN-16111: Updated the testframework to skip search traces when scanning input files

    • +
    • HANSKEN-16128: Updated the testframework to disallow overwriting properties, similar to Hansken

    • +
    • HANSKEN-16191: Fixed Jenkins build

      +
        +
      • commit id could not be retrieved

      • +
      • curl didn’t work due to a bad proxy

      • +
      +
    • +
    • HANSKEN-16116: Updated FLITS dependency to 3.5.2

    • +
    • HANSKEN-16105: Seeking beyond EOF for Python throws an exception

    • +
    • HANSKEN-16160: Updated remaining JUnit 4 tests to JUnit 5

    • +
    • HANSKEN-16118: Trace ids are now optional when writing automated tests using Flits

    • +
    • HANSKEN-16012: Fixed trace types were not correctly determined from property names (Python)

    • +
    • HANSKEN-16238: Changed default log level of extraction plugin server. Added command line option to increase it.

    • +
    +
    +
    +

    Release-0.4.12

    +
      +
    • HANSKEN-15857: Document HQL-lite for programmers manual

    • +
    • HANSKEN-16139: Run markdownlint in Jenkins instead of Docker

    • +
    • HANSKEN-16115: Updated log4j to version 2.16.0 due CVE-2021-44228

    • +
    • HANSKEN-15651: Added documentation on test files

    • +
    • HANSKEN-16001: Improved Python exceptions for better readability

    • +
    • HANSKEN-16044: Fixed documentation being unstashed to wrong directory on Jenkins

    • +
    • HANSKEN-14586: Documentation: added code snippets for adding a Datastream

    • +
    • HANSKEN-16038: Hansken.py: fix deferred tools

    • +
    • HANSKEN-15653: Added documentation on use with Hansken.py

    • +
    • HANSKEN-15801: Change build agent in Jenkins file

    • +
    • HANSKEN-16090: Fix for documentation build (m2r2 requires mistune < 2.0.0)

    • +
    • HANSKEN-15771: Document trace properties that mismatch the trace model

    • +
    +
    +
    +

    Release-0.4.11

    +
      +
    • HANSKEN-16048: Fix documentation was not released because the documentation zip was located in docs/_build/docs

    • +
    +
    +
    +

    Release-0.4.10

    +
      +
    • HANSKEN-16037: Repair release

    • +
    +
    +
    +

    Release-0.4.9

    +
      +
    • HANSKEN-15858: Add a link to the Extraction Plugin SDK API Javadocs

    • +
    • HANSKEN-15656: Documentation: expanded FAQ

    • +
    • HANSKEN-15993: Added isVerboseLoggingEnabled() method to ExtractionPluginFlits to enable verbose logging if desired

    • +
    • HANSKEN-15801: Change build agent in Jenkins file.

    • +
    • HANSKEN-15766: Documentation: Mention the Getting Started guide on gitlab

    • +
    • HANSKEN-15765: Added documentation on the ‘Anatomy of a plugin’

    • +
    • HANSKEN-15772: Added documentation on tracelets

    • +
    • HANSKEN-15770: Added debug documentation (Java and Python)

    • +
    • HANSKEN-15773: Added documentation linter (markdownlint)

    • +
    • HANSKEN-15964: Added –verbose option to Python test_plugin runner

    • +
    • HANSKEN-15913: Use traceUid instead of traceId to read data

    • +
    +
    +
    +

    Release-0.4.8

    +
      +
    • HANSKEN-15668: Bugfix: prevent search from crashing plugin if results contain traces from different images

    • +
    +
    +
    +

    Release-0.4.7

    +
      +
    • HANSKEN-15871: Fix for RpcUnixTime & RpcZonedDateTime that were parsed incorrectly in Python

    • +
    • HANSKEN-15745: Document naming convention and added convienience method id(domain, category, name) to the PluginInfoBuilder

    • +
    • HANSKEN-15790: Change dependency pinning policy

    • +
    • HANSKEN-15790: Fix typing issues discovered by upgrading mypy-protobuf

    • +
    • HANSKEN-15650: Added documentation on general concepts

    • +
    • HANSKEN-15743: Fix Test framework should not limit input files to 2G

    • +
    • HANSKEN-15846: Improved hansken.py matcher, instead of $data.type all $data matchers are supported

    • +
    +
    +
    +

    Release-0.4.6

    +
      +
    • HANSKEN-15711: Changed PluginResources cpu/memory values to floats

    • +
    • HANSKEN-15683: Changed the trace enrichment order to ensure transformations are handled before properties

    • +
    • HANSKEN-15589: Extend PluginInfo with the ability to specify plugin resources (Python)

    • +
    • HANSKEN-15588: Renamed PluginInfo pluginResources() to resources() (Java)

    • +
    • HANSKEN-15588: Extend PluginInfo with the ability to specify plugin resources (Java)

    • +
    +
    +
    +

    Release-0.4.5

    +

    deprecated release

    +
    +
    +

    Release-0.4.4

    +

    deprecated release

    +
    +
    +

    Release-0.4.3

    +
      +
    • HANSKEN-15641: Changed PluginId to use forward-slashes instead of backward-slashes

    • +
    • HANSKEN-15607: Explicitly fail deferred extraction plugins when building PluginInfo if the number of provided iterations is invalid

    • +
    +
    +
    +

    Release-0.4.2

    +
      +
    • HANSKEN-15632: Changed PluginInfo.license field to optional, for backwards compatibility

    • +
    +
    +
    +

    Release-0.4.1

    +

    deprecated release

    +
    +
    +

    Release-0.4.0

    +
      +
    • HANSKEN-15542: Extended Python PluginInfo with a license name and id consisting of domain, category and name

    • +
    • HANSKEN-15466: Extended Java PluginInfo with a license name and id consisting of domain, category and name

    • +
    • HANSKEN-15572: Include path as a property to trace type in TraceToJson

    • +
    • HANSKEN-15034: Add deferred tools to documentation

    • +
    • HANSKEN-15541: Publish SDK documentation as maven artifact

    • +
    • HANSKEN-15562: Fix test framework does not deserialize intrinsic properties

    • +
    • HANSKEN-15365: Create a FLITS test for deferred extraction plugin

    • +
    +
    +
    +

    Release-0.3.0

    +
      +
    • HANSKEN-15527: Add api changelogs for version 0.3.0

    • +
    • HANSKEN-15393: Rename Transformation to DataTransformation and RangedTransformation to RangedDataTransformation

    • +
    • HANSKEN-15391: Add support for ranged transformations (Java only)

    • +
    • HANSKEN-15390: Add proto definitions for ranged transformations

    • +
    • HANSKEN-15392: Add support for ranged transformations (Python)

    • +
    +
    +
    +

    Release-0.2.0

    +
      +
    • HANSKEN-15520: Add dedicated page for SDK API changes per language

    • +
    • HANSKEN-15515: Move Author and MaturityLevel to PluginInfo module (Python)

    • +
    • HANSKEN-15514: Refactor ExtractionContext to DataContext (Java and Python)

    • +
    • HANSKEN-15512: Move some internals from the EP python API to runtime module

    • +
    • HANSKEN-15511: Include API documentation in SDK dev docs

    • +
    • HANSKEN-15505: Cleanup SDK: remove unused position and unrequired datatype

    • +
    • HANSKEN-15491: Add compatibility check of remote plugin with current SDK version

    • +
    • HANSKEN-15502: Update TestRandomAccessData to accept dataType parameter

    • +
    • HANSKEN-15495: Make getData() lazy and replace getAllData() with getDataTypes()

    • +
    • HANSKEN-15498: Fixed isort configuration (Python)

    • +
    • HANSKEN-15029: Limit gRPC search request count

    • +
    • HANSKEN-15274: Add Python API for deferred extraction plugins

    • +
    • HANSKEN-15035: Allow python deferred plugins to run through hansken.py.

    • +
    • HANSKEN-15288: Add a new Trace subclass for search result Traces

    • +
    • HANSKEN-15042: Research and implement requesting data through GRPC for search traces

    • +
    • HANSKEN-15139: Allow deferred extraction plugins to process traces

    • +
    • HANSKEN-15015: Add option to create deferred extraction plugins using sdk

    • +
    +
    +
    +

    Release-0.1.8

    +
      +
    • HANSKEN-15236: Read initial chunk of data along with an RPC start request (Python)

    • +
    • HANSKEN-15338: Add setting of tracelets

    • +
    • HANSKEN-15370: Fixed ArrayOutOfBoundsException when there are bytes left when prefilling the cache

    • +
    • HANSKEN-15353: Added testframework exception result validation without or on partial message(startsWith, containsInOrder)

    • +
    • HANSKEN-15231: Added caffeine block cache implementation for Java RandomAccessData

    • +
    • HANSKEN-15276: Added support for Heterogeneous Maps

    • +
    +
    +
    +

    Release-0.1.7

    +
      +
    • HANSKEN-15282: Change the way reading data in the python sdk works. More BufferedReader functions are supported, including seeking

    • +
    +
    +
    +

    Release-0.1.6

    +
      +
    • HANSKEN-15294: Make Java SDK available to the Hansken community

    • +
    • HANSKEN-15233: Send initial chunk of data along with the start message (Java only)

    • +
    • HANSKEN-15232: Added RandomAccessData cache mechanism with fixed size of 1 MB to speed up large file reads

    • +
    • HANSKEN-15193: Improve client-side error message when server-side throws an exception

    • +
    • HANSKEN-15237: Added logging before and after processing a trace

    • +
    • HANSKEN-15187: Bugfix: Fixed flits traces with nested map properties were being parsed incorrectly

    • +
    • HANSKEN-15189: Added default log4j logging when no logging is configured

    • +
    +
    +
    +

    Release-0.1.5

    +
      +
    • HANSKEN-15192: Added Superpom for Java extraction plugins

    • +
    • HANSKEN-15186: Fixed matcher $data.mimeType does not work

    • +
    +
    +
    +

    Release-0.1.4

    +
      +
    • HANSKEN-14820: Bugfix: “Received a message from server, but processing of the trace has not been started yet”

    • +
    • HANSKEN-15059: Set up skeleton documentation for Extraction Plugin devs

    • +
    • HANSKEN-15048: Allow ‘workers’ as an optional argument when starting an ExtractionPluginServer

    • +
    +
    +
    +

    Release-0.1.3

    +
      +
    • HANSKEN-14787: Allow extraction plugins to be routed by HEADER by a proxy/loadbalancer

    • +
    +
    +
    +

    Release-0.1.2

    +
      +
    • HANSKEN-14923: Make SDK work on Windows

    • +
    +
    +
    +

    Release-0.1.1

    +
      +
    • HANSKEN-14867: Expanded HQL matcher to support Long & List (intrinsic)properties

    • +
    +
    +
    +

    Release-0.1.0

    +
      +
    • HANSKEN-14879: Allow SDK releases to be published on PyPI

    • +
    • HANSKEN-14738: Shade NFI internal projects into the SDK testframework jar

    • +
    • HANSKEN-14841: Bugfix where RpcStringMap wasn’t being unpacked properly in Python, which was discovered during a flits test.

    • +
    • HANSKEN-14703: Let Python plugins exit gracefully on SIGTERM

    • +
    • HANSKEN-14844: SDK: move serve from test_framework to runtime

    • +
    • HANSKEN-14793: Add ExtractionPluginBuilder.add_data method in python API

    • +
    • HANSKEN-14777: Add an extra check to ignore and log unsupported types during RpcStart gRPC serialization.

    • +
    • HANSKEN-14739: License: Distribute Extraction Plugin SDK under the Apache License 2.0

    • +
    • HANSKEN-14763: Bugfix where some python plugins were not loaded correctly when using serve or test-plugin commands

    • +
    • HANSKEN-14737: Move serve.py from plugin examples to SDK

    • +
    • HANSKEN-14720: Add option to use with when using the trace.open method in python

    • +
    • HANSKEN-14582: Add option to write data using the python api

    • +
    • HANSKEN-14660: Move _test.py files from plugin examples repo to SDK repo

    • +
    • HANSKEN-14618: Add validation for unexpected extra data streams to test framework

    • +
    • HANSKEN-14704: Fix shading of the runtime super pom

    • +
    • HANSKEN-14619: Allow propagation of IOException in plugin new child callback

    • +
    • HANSKEN-14632: Add Java gRPC support for writing raw data streams on a trace

    • +
    • HANSKEN-14591: Split into three modules in the SDK

    • +
    • HANSKEN-14580: Add proto message definitions for raw data stream writing

    • +
    • HANSKEN-14635: Trace format which containes name/id can now be deserialized by testframework

    • +
    • HANSKEN-14131: Added ‘verbose’ logging for test-framework HQL matching

    • +
    • HANSKEN-14130: Updated StandaloneTestRunner to expose more errors & exceptions

    • +
    • HANSKEN-13784: Add meta support to test-framework

    • +
    • HANSKEN-14581: Extend Trace API with raw data writing capabilities

    • +
    • HANSKEN-14547: Deploy Java sources JAR for improved client debugging

    • +
    • HANSKEN-14531: Fix Python release. Python needs only one build step, which is either a snapshot or a release build. The separate Python release step was removed and merged with the first Python build step. Repository paths were corrected for the release version.

    • +
    • HANSKEN-14531: Fix python release - The python release is no longer a separate step in the build pipeline, since there is no actual difference between a snapshot and a release, apart from the version numbering scheme and the test-framework is downloaded from a repository location depending on the release parameter (see comments in Jenkinsfile)

    • +
    • HANSKEN-14161: Add Python test-framework wrapper around Java test-framework and add test-framework.tgz to whl

    • +
    • HANSKEN-14234: Restructure build pipeline to build and release Java first

    • +
    • HANSKEN-13799: Extraction Plugin: support meta extraction

    • +
    • HANSKEN-14286: Create adapter from RandomAccessData to InputStream

    • +
    • HANSKEN-14314: Don’t send child name when sending enrichment message

    • +
    • HANSKEN-14318: Flush cached children before flushing root in case of error with python gRPC server

    • +
    • HANSKEN-13414: Generate shaded jar for runtime that shades Guava, Protobuf, gRPC, and Netty (fix)

    • +
    • HANSKEN-14283: Allow passing a configuration of retry policy for the extraction plugin client

    • +
    • HANSKEN-14234: Restructure build pipeline to build and release Java first

    • +
    • HANSKEN-13414: Generate shaded jar for runtime that shades Guava, Protobuf, gRPC, and Netty

    • +
    • HANSKEN-14234: Restructure build pipeline to build and release Java first

    • +
    • HANSKEN-14135: Improve testing Python plugins in integration step and test reading large chunks

    • +
    • HANSKEN-14134: Fix releasing python plugins

    • +
    • HANSKEN-14128: Validate gRPC message limit for Python server instances

    • +
    • HANSKEN-14122: Fix missing comma in dependencies which broke the release

    • +
    • HANSKEN-14092: The type and total size of the data currently being processed can now be retrieved from an extractioncontext object passed to the process function

    • +
    • HANSKEN-13668: Added support for lists of longs, Hansken maps and LatLong to Java and Python API

    • +
    • HANSKEN-14104: Set Python gRPC limit to 64 MB(including message overhead)

    • +
    • HANSKEN-14079: Add logging to the SDK

    • +
    • HANSKEN-14010: Add support for serializing datetime in python API

    • +
    • HANSKEN-14083: Fix releasing python sdk

    • +
    • HANSKEN-14035: Add static type checks to python project

    • +
    • HANSKEN-14030: Allow test framework to be executed standalone for non-java extraction plugins

    • +
    • HANSKEN-14073: Support gRPC extraction plugins in test framework

    • +
    • HANSKEN-14074: Add support for serialization of Maps.

    • +
    • Hansken-14090: Use new Hansken python-api children call for creating nested children

    • +
    • HANSKEN-13774: Add support for creating children in python API

    • +
    • HANSKEN-13776: Add error handling to the Python based server and send error messages to the client

    • +
    • HANSKEN-14060: Remove mapping-interface from python extraction for API consistency

    • +
    • HANSKEN-13773: Update trace properties in Python API

    • +
    • HANSKEN-14044: Make sure python testing code is linted as well, enforce single quotes

    • +
    • HANSKEN-13772: Expose trace properties in Python API

    • +
    • HANSKEN-13775: Python - added trace.open() functionality to read from data streams

    • +
    • HANSKEN-14031: Split Trace interfaces (hansken.py trace vs external plugin trace)

    • +
    • HANSKEN-14037: Make sure pytest is always used for python tests

    • +
    • HANSKEN-14011: Implement unpack for trace

    • +
    • HANSKEN-14009: Implement pack for trace and trace enrichment

    • +
    • HANSKEN-14008: Move generated hql-lite parsers to different package (conflicts with hql package)

    • +
    • HANSKEN-13777: Added utility to run Python Extraction Plugin implementations with Hansken.py

    • +
    • HANSKEN-13771: Implement Extraction Plugin Info for Python plugins

    • +
    • HANSKEN-13966: Give socketproxy disconnect some time to disconnect (fixes flaky unit test)

    • +
    • HANSKEN-13810: Add extraction plugin python server code

    • +
    • HANSKEN-13676: Added support for ZonedDateTime over gRPC

    • +
    • HANSKEN-13922: Add webpage url to PluginInfo

    • +
    • HANSKEN-13676: Changed the way of creating child Traces to using a consumer.

    • +
    • HANSKEN-13655: Added server/client disconnect tests and implemented initial handling server-side

    • +
    • HANSKEN-13809: Added missing gRPC exception handles of process()

    • +
    • HANSKEN-13801: Made HQL-Lite matchers immutable

    • +
    • HANSKEN-13761: Seperated HQL-Lite type matcher implementation

    • +
    • HANSKEN-13756: Added HQL-Lite datastream matchers

    • +
    • HANSKEN-13800: (Temporarily) remove meta from Extraction Plugin API

    • +
    • HANSKEN-13798: Propagate exception on failure of START serialization

    • +
    • HANSKEN-13706: Create basic test framework implementation

    • +
    • HANSKEN-13769: Make jenkins run tests and a linter for python

    • +
    • HANSKEN-13705: Add support for creating child traces over gRPC

    • +
    • HANSKEN-13713: Make (partial) extraction plugin errors visible for clients

    • +
    • HANSKEN-13709: Send partial result when an external plugin errors out

    • +
    • HANSKEN-13733: Add script to generate gRPC Python files

    • +
    • HANSKEN-13660: Copied the Hql definition from Hansken to enable the HQL-Lite implementation

    • +
    • HANSKEN-13656: Test and handle invalid protocol messages

    • +
    • HANSKEN-13663: Add matcher interface to PluginInfo

    • +
    • HANSKEN-13714: Add IOException to ExtractionPlugin.process() interface

    • +
    • HANSKEN-13658: test(s) for non-grpc connection with a grpc server

    • +
    • HANSKEN-13650: Add basic support for writing trace information over gRPC

    • +
    • HANSKEN-13648: Add basic support for reading trace information over gRPC

    • +
    • HANSKEN-13651: Default implementations for RandomAccessData interface

    • +
    • HANSKEN-13643: Add basic support for reading trace information over gRPC

    • +
    • HANSKEN-13643: Add basic support for reading from trace data over gRPC

    • +
    • HANSKEN-13581: Plugin-info client/server implementations

    • +
    • HANSKEN-13580: Add gRPC server and client to serve an Extraction Plugin as a service

    • +
    • HANSKEN-13579: Created initial gRPC implementation messages

    • +
    • HANSKEN-13577: Be able to create releases of the SDK

    • +
    • HANSKEN-13578: Created plugin API

    • +
    • HANSKEN-13560: Create initial gRPC definitions

    • +
    • HANSKEN-13554: Initial repository

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/contact.html b/0.9.16/contact.html new file mode 100644 index 0000000..fa1cbdd --- /dev/null +++ b/0.9.16/contact.html @@ -0,0 +1,133 @@ + + + + + + + + + Contact — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Contact

    +

    Please get in touch with us:

    +
      +
    • if you have questions about the SDK,

    • +
    • have found a bug,

    • +
    • have a feature request,

    • +
    • see other opportunity to improve,

    • +
    • want to contribute,

    • +
    • +
    +

    Chat with us on Discord. You can find members of the extraction plugin SDK development team +in the Hansken Community server, in the extraction-plugins channel. This is a Hansken community-private server. If you +don’t have access to the Hansken Community server, please contact your Hansken business owner. He or she can invite you +to the Hansken Community server. If you don’t know who to contact, feel free to fill in +the contact form for further questions/contact.

    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts.html b/0.9.16/dev/concepts.html new file mode 100644 index 0000000..ba7d01e --- /dev/null +++ b/0.9.16/dev/concepts.html @@ -0,0 +1,148 @@ + + + + + + + + + General concepts — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/all_in_one_debugging.html b/0.9.16/dev/concepts/all_in_one_debugging.html new file mode 100644 index 0000000..b566a60 --- /dev/null +++ b/0.9.16/dev/concepts/all_in_one_debugging.html @@ -0,0 +1,194 @@ + + + + + + + + + Debugging locally with Hansken All in One (AIO) — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Debugging locally with Hansken All in One (AIO)

    +
    +

    Note

    +

    this feature is available from Hansken 46.4.0

    +
    +
    +

    Warning

    +

    DeferredExtractionPlugin are currently NOT supported

    +
    +

    It is also possible to debug an Extraction Plugin with a locally running Hansken AIO. This requires a few steps:

    +
      +
    1. Start your plugin in your IDE (default port 8999)

      +1_debug_start_plugin_in_ide.png +
    2. +
    3. Set some breakpoint(s)

      +2_debug_set_breakpoints.png +
    4. +
    5. Prepare an extraction in the AIO with advanced options

      +3_debug_prepare_extraction.png +
    6. +
    7. Enable the DebugExtractionPluginTool for this extraction

      +4_debug_enable_debug_tool.png +
    8. +
    9. Start extraction, and happy debugging!

    10. +
    +
    +

    Tips/notes

    +
      +
    • You can only debug 1 plugin at a time

      +
        +
      • +

        Note

        +

        If you are debugging MyPlugin, and it is also visible in the tools list, then you need to disable it, and only enable the DebugExtractionPluginTool

        +
        +
      • +
      +
    • +
    • Test your plugin with a small image. Otherwise, it might take long before you reach your breakpoint.

    • +
    • Be careful when using this debugger with APPEND extractions:

      +
        +
      • Similar to other tools/plugins, the DebugExtractionPluginTool will only run once per trace

      • +
      • So if you need to re-run your debug session, then we advise you to re-extract (INDEX) your project instead

      • +
      +
    • +
    • Hansken runs multiple instances of every Tool, so the same breakpoint can be hit multiple times concurrently by +different instances

      + +
    • +
    • Only restart your plugin before starting an extraction. Restarting your plugin during an extraction can +produce +undefined behaviour.

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/anatomy_of_a_plugin.html b/0.9.16/dev/concepts/anatomy_of_a_plugin.html new file mode 100644 index 0000000..69f76d4 --- /dev/null +++ b/0.9.16/dev/concepts/anatomy_of_a_plugin.html @@ -0,0 +1,217 @@ + + + + + + + + + Anatomy of a plugin — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Anatomy of a plugin

    +

    This page describes the general anatomy of a plugin, and its (simplified) execution in Hansken.

    +
    +

    The plugin itself

    +

    Each plugin must implement two methods:

    +
      +
    • pluginInfo(): This method returns information about the plugin.

    • +
    • process(): This method performs the extraction task of the plugin.

    • +
    +

    Let’s dive a bit deeper into these methods in the next sections!

    +
    +

    The method pluginInfo()

    +

    The pluginInfo() method returns a PluginInfo object. Hansken needs this object to be able to know the capabilities +of the plugin, and to show the plugin in the list of tools. The most important fields that must be set on PluginInfo +are the following:

    +
    +
    id | The identifier of the plugin. This will be used as a unique name for the plugin Hansken. |
    +
    description | A description of the plugin that is shown in Hansken. |
    +
    author | The author of the plugin that is shown in Hansken. |
    +
    license | The type of license of the plugin that is shown in Hansken. |
    +
    matcher | This matcher is used by Hansken to determine which Traces are sent to the Plugin during extraction. |
    +
    +
    +
    +

    The method process()

    +

    During extraction, Hansken calls the process() method for every matching trace. The matcher attribute of +the PluginInfo is very important as it determines which traces will be sent to the process method.

    +

    Although the plugin developer is free to program whatever seems useful, the following tasks are typically performed +within the process() method:

    +
      +
    • Creating child-traces

    • +
    • Reading trace properties

    • +
    • Adding trace properties

    • +
    • Reading the data that the Trace represents

    • +
    • Writing data on a Trace

    • +
    +

    Depending on the type of plugin that is implemented, different functionality is available in the process() method. +See Plugin Types for more details.

    +
    +
    +
    +

    The execution in Hansken

    +

    This describes the process of running a plugin from the perspective of Hansken. The perspective of the user is described +in Hansken Extraction Plugins.

    +
    +

    Plugin discovery

    +

    Hansken manages a list of tools that can be used in extractions. The available plugins must be added to this list so +that the user can select them. To accomplish this, Hansken scans the Docker registry for docker images that are plugins. +Each image is started up, and a call is done to its pluginInfo() method. If the call resulted in a valid PluginInfo +object, the Extraction Plugin is added to the list of tools visible to users. After the PluginInfo is retrieved, the +docker image is shutdown again.

    +
    +
    +

    Starting an extraction

    +

    Hansken checks if any plugins are selected by the user that started the extraction. For each selected plugin, at least +one docker image will be started. See Kubernetes autoscaling for more details on expanding +the number of instances for each plugin.

    +
    +
    +

    Extracting

    +

    During an extraction, Hansken will iteratively loop through all selected tools, including Extraction Plugins. For each +trace that matches on a tool, Hansken will call its process method. For Extraction Plugins, this means that +the process method is called via the gRPC protocol. The trace to be processed is sent over gRPC to the plugin, and any +other communication between Hansken and the Extraction Plugin (like created properties and child traces, search requests +and written data) are done using gRPC.

    +
    +
    +

    Finishing an extraction

    +

    At the end of an extraction, Hansken will stop all associated plugins.

    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/data_transformations.html b/0.9.16/dev/concepts/data_transformations.html new file mode 100644 index 0000000..5b30402 --- /dev/null +++ b/0.9.16/dev/concepts/data_transformations.html @@ -0,0 +1,157 @@ + + + + + + + + + Data Transformations — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Data Transformations

    +

    Extraction Plugins can create new data-streams on a Trace through data transformations. Data +transformations describe how data can be obtained from a source. Data transformations are preferred over storing blobs +because they take less space. This is because they only describe the data instead of specifying the actual data.

    +

    The following figure shows how Hansken visualizes data transformations:

    +datatransformations.png +

    Note that transformations can be applied on transformations. The SDK only supports range transformations at the moment, +while this image also shows some transformations that are currently available in Hansken but not in the SDK.

    +

    An example case is an extraction plugin that processes an archive file. The plugin creates a child trace per entry in +the archive file. Each child trace will have a data stream that is a transformation that marks the start and length of +the entry in the original archive data. By just describing the data instead of specifying the actual data, a lot of +space is saved.

    +

    Although Hansken supports various transformations, the Extraction Plugins SDK for now only supports ranged data +transformations. Ranged data transformations define data as a list of ranges, each range with an offset and length in a +bytearray.

    +
    +

    See also

    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/extraction_plugins.html b/0.9.16/dev/concepts/extraction_plugins.html new file mode 100644 index 0000000..b411bef --- /dev/null +++ b/0.9.16/dev/concepts/extraction_plugins.html @@ -0,0 +1,197 @@ + + + + + + + + + Hansken Extraction Plugins — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Hansken Extraction Plugins

    +

    Hansken Extraction Plugins enable Hansken users to add their own extraction tools to Hansken.

    +

    To use an Extraction Plugin in Hansken, the following steps have to be done:

    +
      +
    1. Build the plugin

    2. +
    3. Upload the plugin to Hansken

    4. +
    5. Refresh the Hansken tools list

    6. +
    7. Start an extraction with the plugin enabled

    8. +
    +
    +

    Building a plugin

    +

    Hansken Extraction Plugins can be built in Java or Python by implementing an interface. Which interface you choose +depends on the type of plugin you choose to make, see Plugin Types. For more information on coding +your own plugin, see the Extraction Plugin Examples.

    +

    The plugin can then be tested using the Test Framework. This way you make sure everything works as +expected before taking further steps.

    +
    +
    +

    Package the plugin

    +

    To upload a plugin into Hansken, a docker image for this plugin must be uploaded to the docker registry. First, the +plugin container image must be packaged. +A plugin is packaged into an OCI image (also known as Docker image).

    + +
    +
    +

    Upload the plugin to Hansken

    +

    Hansken finds the plugins by scanning a docker registry. It will try to load all docker images with a certain prefix as +Extraction Plugins. The settings for this are defined in Hansken properties:

    +
      +
    • registry.extraction.plugins.registry.uri defines the registry

    • +
    • registry.extraction.plugins.registry.prefix defines the prefix plugins must have

    • +
    +

    When the image is packaged locally, it needs to be pushed (uploaded) to the docker registry. These commands provide an +outline of how to do this:

    +
      +
    • docker login <docker-registry> (make sure you are logged in to the registry)

    • +
    • docker push <docker-registry><prefix><pluginname> (push the plugin docker image to the registry)

    • +
    +
    +

    Note

    +

    For more information about uploading plugins and running them in Hansken, see the ‘Using extraction plugins in +Hansken’ chapter of the Hansken User Guide.

    +
    +
    +
    +

    Refresh the Hansken tools list

    +

    Hansken checks which plugins are available at startup. The list of available plugins can also be refreshed by calling +the following endpoint: <hansken-domain>/gatekeeper/tools?refresh=true

    +

    This can be invoked via an internet browser.

    +
    +
    +

    Start an extraction with the plugin enabled

    +

    If everything went well, the list of available tools in Hansken should now feature your plugin. To run the plugin in an +extraction, be sure to select its checkbox in the extraction tools dialog.

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/hql_lite.html b/0.9.16/dev/concepts/hql_lite.html new file mode 100644 index 0000000..46dee20 --- /dev/null +++ b/0.9.16/dev/concepts/hql_lite.html @@ -0,0 +1,575 @@ + + + + + + + + + HQL-Lite — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    HQL-Lite

    +
    +

    Overview

    +

    HQL-Lite is a query language derived from Hanskens full HQL human. HQL stands for Hansken Query Language and can be +used to search or match traces. Since not all elements of full HQL can be used in the context of an extraction, +extraction plugins use HQL-Lite, a lightweight version of HQL. This document describes the usage of HQL-Lite in the +context of extraction plugins.

    +
    +
    +

    How does Hansken work?

    +
      +
    • Let’s say we have a Hansken image hansken_image1 with 10 pdf files, and 5 jpegs.

    • +
    • And our Hansken contains 2 tools:

      +
        +
      • PdfPlugin

      • +
      • JpegTool

      • +
      +
    • +
    +
    +

    Note

    +

    All plugins are Hansken tools, but not all Hansken tools are plugins. Some tools are included in Hansken core.

    +
    +

    Let’s look at a (simplified) pseudocode example of the inner workings of Hansken:

    +
    for each trace in new_traces {
    +    for each datastream in trace {
    +        for each tool in hansken_tools {
    +            if tool.can_this_tool_process_the_provided_trace(trace, datastream) {
    +                tool.process_the_trace(trace, datastream)
    +            }
    +        }
    +    }
    +}
    +
    +
    +

    So in this example we know the following:

    +
      +
    • new_traces has

      +
        +
      • 10 pdf files

      • +
      • 5 jpeg files

      • +
      +
    • +
    • hansken_tools contains:

      +
        +
      • PdfPlugin

      • +
      • JpegTool

      • +
      +
    • +
    +

    So the question here is, how do we prevent that traces are not processed by incompatible tools?

    +

    The answer is the tool.can_this_tool_process_the_provided_trace() part of the pseudocode.

    +
    +

    What does can_this_tool_process_the_provided_trace() do?

    +

    Hansken actually contains many more tools/plugins than these 2, and instead of 15 files/traces, we usually deal with +millions.

    +
    +

    Note

    +

    If each trace has 1 extra second of overhead, 1 million traces would take 11.5 days of extra CPU time

    +
    +
    +

    Matchers to the rescue

    +

    To reduce the unnecessary overhead of processing all traces (even the ones the tool cannot actually process), Hansken +implements the concept of a matcher for each tool. This matcher basically checks the trace for “matching +conditions”, that would allow the tool to process it.

    +

    Sometimes these matching conditions can be as simple as a specific filename or extension, but are often more +elaborate in the sense that they check multiple factors that require some intimate knowledge of Hansken.

    +
    +
    +
    +
    +

    What is HQL-Lite?

    +

    HQL-Lite is a language based on HQL (Hansken Query Language) that allows plugin developers to write matchers for +Hansken Extraction Plugins. It could be said that HQL-Lite contains a subset of HQL features, plus some HQL-Lite unique +features that are only interesting for matchers.

    +
    +

    Note

    +

    Please note that even though the HQL-Lite query is part of the plugin, it is compiled and stored in Hansken during +startup to achieve performance.

    +
    +
    +

    Why not just use HQL for plugins?

    +

    HQL was designed to search for traces stored in the Elasticsearch database. As such, some of its features are tightly +coupled to the Elasticsearch implementation, making it difficult to re-implement them for plugins.

    +

    Also, even though HQL is more complex than the requirements for matching in plugins, a couple of minor features that +are absolutely necessary for matching are not implemented in HQL, as they don’t make much sense from a search point of +view. This is because HQL was designed to be used with finished extractions with all the traces stored in the +database, while HQL-Lite was designed for active extractions.

    +
    +
    +

    HQL-Lite syntax

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Matcher

    Syntax

    remarks

    All

    ""

    an empty string translates to match for all traces

    And

    foo:1 AND bar:2

    the case-sensitive AND operator behaves like a logical AND of 2 conditions

    Not

    NOT foo or -foo

    the case-sensitive NOT or - negates the expression that follows

    Range

    foo>1 or 1<=foo<10

    a numbered-range check with a min or/and max range(s)

    Or

    foo:1 OR bar:2

    the case-sensitive OR operator behaves like a logical OR of 2 conditions

    Data

    $data.foo:1

    see $data section below

    DataType

    $data.type:raw

    this query matches against the type of the current datastream

    Types

    type:email

    this query checks if the trace contains a certain trace type as defined in the Hansken trace model

    +

    There are also a couple of general guidelines that apply to all matchers:

    +
      +
    • Equals/not equals:

      +
        +
      • : or = : The most basic of left equals right statements. note that = is also valid.

      • +
      • != : The opposite of equals, not equals. Note that !: is NOT supported.

      • +
      +
    • +
    • Wildcards:

      +
        +
      • ? : Match against any single character. E.g. foo:r?w will match against raw, row but not against rowing.

      • +
      • * : Match against any chars. E.g. foo:r* will match against r, ra, raw, raaaaaw but not against aw.

      • +
      +
    • +
    • Exact match: By surrounding a value with quotes, we tell the parser that it is a single value. This is especially +helpful for values that might contain separators. E.g. foo:'hello hql-lite'.

    • +
    • CSV: Currently only the type query supports multiple values to check against. E.g. type:email,chatMessage will only +return true if both types exist for this trace.

    • +
    • () grouping: You can group statements by putting brackets around them. E.g. foo:1 AND (bar:2 OR bla:3) which +translates to foo:1 plus one of the statements in the brackets.

    • +
    • Escaping \"\.\t\r\n:=><!()~/,[]{}: Some characters are used internally by HQL-Lite, and need to be escaped if they +are used in the value side of the key-value pair. These values can be escaped by adding prepending \\ to the +character(s). Example: foo:foo bar should be foo:foo\\ bar, foo.bar:foo:bar should be foo.bar:foo\\:bar +…etc.

      +
        +
      • The only exceptions to this rule are unix paths:

        +
          +
        • Acceptable paths:

          +
            +
          • foo:/

          • +
          • foo:bar/baz

          • +
          • foo:/bar/baz

          • +
          • foo:'/bar/baz/he llo'

          • +
          • foo:*bar/baz*

          • +
          +
        • +
        • Unacceptable paths:

          +
            +
          • foo:/bar/ -> this is the regex matcher, which is unsupported in HQL-lite

          • +
          • foo:c:\ -> should be foo:c\:\\, both the colon and the slash need to be escaped

          • +
          • foo:'c:\' -> should be foo:'c:\\', the slash still needs to be escaped

            +
              +
            • +

              Note

              +

              the backslash is the universal escape character, so it always needs to be escaped.

              +
              +
            • +
            +
          • +
          +
        • +
        +
      • +
      +
    • +
    +
    +

    $data matchers

    +

    In Hansken, a trace can have multiple datastreams. The exact content of said datastreams is +discussed elsewhere, but the basic idea is that a trace can have multiple representations. For example, a trace might +have a raw datastream, but after we identify that the raw bytes contain a text file, we might add a separate +datastream text.

    +
    +

    Note

    +

    The process() method of each plugin is called for each datastream of each trace. This is explained +in How does Hansken work? . Subsequently, you might have the same property for a +different datastream. For example: you might have a data.raw.size and a data.text.size property. The reason you +might have the same property multiple times, is because it could have a different meaning.

    +
    +

    For example:

    +
      +
    • data.raw.size: is the size in bytes

    • +
    • data.text.size: is the number of bytes in the text representation of the raw stream

    • +
    +

    If we want to check if either of these properties is not empty by using a $data matcher, we do:

    +
    $data.size>0
    +
    +
    +
    +
    When is it useful to use a $data matcher?
    +

    For example, there is a simple plugin called LetterCountPlugin, that counts the letters in text based datastreams.

    +

    So to match on these text based datastreams, we have 2 choices:

    +
      +
    • List all the possibilities

      +
        +
      • Which is too tedious, and not very flexible when new types are supported

      • +
      +
    • +
    • Match on a common property

      +
        +
      • More compact, but sometimes difficult to find a common property

      • +
      +
    • +
    +

    In this case we might match on mimeType, which we know is text/plain or text/x-log for 2 of types we want to match:

    +
    $data.mimeType=text\\/*
    +
    +
    +

    This will match the following:

    +
      +
    • data.text.mimeType=text\\/plain

    • +
    • data.text.mimeType=text\\/not\\ plain

    • +
    • data.pdf.mimeType=text\\/encoded

    • +
    • data.foo.mimeType=text\\/bar

    • +
    +

    But will not match any of the following:

    +
      +
    • data.text.mimeType=txt

    • +
    • data.text.mimeType=pdf

    • +
    • data.text.mime=text\\/plain

    • +
    • data.foo.bar=text\\/plain

    • +
    +
    +
    +
    +
    +
    +

    How to write a matcher?

    +

    The functional requirements for writing a matcher can be summarized in the following:

    +
      +
    1. What does my plugin expect as input?

    2. +
    3. How can I describe that input with the information Hansken provides?

    4. +
    +
    +

    PdfPlugin example

    +

    Let’s say we just finished writing a PdfPlugin. This is a simple plugin that checks if pdf files contain the +word the.

    +

    So let’s go over our checklist:

    +
    +

    What does my plugin expect as input?

    +

    PDF files.

    +
    +
    +

    How can I describe that input with the information Hansken provides?

    +

    Hansken consumes and produces Traces. To that effect, we can only match on trace properties that are +available in Hansken.

    +
    +
    Match on extension
    +

    The easiest way would be to only allow traces with the .pdf extension. Looking at the Hansken trace model (or a +Hansken extraction), we can see that there’s a property file +which contains a property extension.

    +

    So what would that look like in HQL-lite? Something like

    +
    file.extension=pdf
    +
    +
    +
    +

    Warning

    +

    This of course only works if the file has the correct extension (note that matchers are case-sensitive).

    +
    +

    So what do we do, if we also want to match pdf files that are (un)intentionally misnamed?

    +
    +
    +
    Match on mime-type
    +

    Looking at Wikipedia, we see that pdf has a couple of mime-types. In return looking at our extraction and the +trace-model, we see both at data.raw.mimeType, with a further explanation in the Hansken trace model that +the raw portion of the property is the data type of the datastream.

    +

    If we don’t know which datastream has the mimeType property beforehand, we could use the broad-scoped $data. matcher +to look at every datastream.

    +

    So our matcher becomes:

    +
    file.extension=pdf OR
    +(
    +  $data.mimeType=application\\/pdf OR
    +  $data.mimeType=application\\/x-pdf
    +)
    +
    +
    +
    +
    +
    Match on data size
    +

    Some pdf files can be huge, meaning that parsing them will need a lot of resources. Could we add a data size check to +the matcher? According to the Hansken trace model data has a property size (similar to mimeType) that we +could use for this.

    +
    +

    Note

    +

    This is also a good way to check if a file is empty or not.

    +
    +

    Let’s say our cutoff limit is 1 MB, meaning our matcher becomes:

    +
    0 < $data.size < 1000000 AND
    +(
    +  file.extension=pdf OR
    +  (
    +    $data.mimeType=application\\/pdf OR
    +    $data.mimeType=application\\/x-pdf
    +  )
    +)
    +
    +
    +
    +
    +
    Match if ‘property is set’
    +

    It is not uncommon to have some overlap between tools/plugins. For example:

    +
      +
    • PdfPlugin: a plugin that only supports pdf documents

    • +
    • DocumentPlugin: this plugin supports a lot of document types, including pdf.

    • +
    +

    So how would we prevent our plugin from processing a trace that has already been processed by the DocumentPlugin?

    +

    The easiest solution would be to check if a certain property has already been set. Meaning, that if both plugins set +the foo.bar property, we check if said property has already been set.

    +

    So we only process the trace if foo.bar is empty, meaning our matcher becomes:

    +
    foo.bar!=* AND
    +0 < $data.size < 1000000 AND
    +(
    +  file.extension=pdf OR
    +  (
    +    $data.mimeType=application\\/pdf OR
    +    $data.mimeType=application\\/x-pdf
    +  )
    +)
    +
    +
    +
    +
    +
    Match on excluding a certain path
    +

    It is also not uncommon to exclude certain paths from your plugin. These paths might contain invalid or encrypted files, +for example.

    +

    So let’s say we want to exclude all files under in the /tmp/virus path. How do we go about it?

    +

    Again, we check our extraction/Hansken trace model, and we see that file.path looks promising.

    +

    So excluding /tmp/virus would look something like:

    +
    -file.path=/tmp/virus* AND
    +foo.bar!=* AND
    +0 < $data.size < 1000000 AND
    +(
    +  file.extension=pdf OR
    +  (
    +    $data.mimeType=application\\/pdf OR
    +    $data.mimeType=application\\/x-pdf
    +  )
    +)
    +
    +
    +
    +
    +
    Match on specific datastream type, an anti-pattern
    +
    +

    Warning

    +

    Matching on specific datastream types is an anti-pattern! It is not recommended to match on a datastream +type. Instead one should match on other datastream properties, such as fileType, mimeType or mimeClass. +The reason for this is explained in the paragraph below.

    +
    +

    Using a matcher that is too loose or too tight can yield unexpected results. Usually one will match on properties +of a datastream like fileType, mimeType or mimeClass as these are reliable properties that have been added by +Hansken tools. Matching on a specific datastream says nothing about the type of file. For example a PDF file may be +available in a raw as well as in a decrypted datastream. By matching on the datastream type one may exclude traces +that were not intended to be excluded. +Contrarily, note that matching on a datastream type may include more traces than you expected as well. For example, +someone may think “Plugin A puts data on the plain datastream, so I’ll match on the plain datastream with Plugin B”, +forgetting that plain may be used by other tools as well. In other words, there may be traces with that datastream +type that you did not know of, potentially crashing your plugin. See Data streams for more information.

    +

    Now that you know why it is an anti-pattern, lets explain how it would be done (for those edge cases where it’s needed): +Lets say we want our PdfPlugin to ONLY process raw datastreams. +The best way to do this would be to match +on $data.type:raw. Note that $data.type matches against the type of the current datastream, so in this case it +matches only when the current datastream is of type raw.

    +

    An incorrect way to do it would be to replace $data. matcher(s) with data.raw.. This means the matcher +will match whenever a trace has this datastream type, even if the current datastream type is different. +Remember that the process method of an extraction plugin is always called once for each datastream on each trace. +For example, lets say a trace has two datastreams, raw and text. The matcher would match for both the datastreams +because the trace has a raw datastream (even though the current datastream type may be text). This results in the +process method being called twice (for raw and for text), which may lead to other bugs if the developer doesn’t +know this. For example, the second time the plugin may be trying to overwrite data on a trace which is prohibited.

    +

    So, using $data.type, our matcher would look like:

    +
    $data.type:raw AND
    +-file.path=/tmp/virus* AND
    +foo.bar!=* AND
    +0 < $data.size < 1000000 AND
    +(
    +  file.extension=pdf OR
    +  (
    +    $data.mimeType=application\\/pdf OR
    +    $data.mimeType=application\\/x-pdf
    +  )
    +)
    +
    +
    +
    +
    +
    +
    +
    +

    How precise should a matcher be?

    +

    In practice, only you as the plugin dev can answer this question.

    +

    Know that from the point of view of Hansken, we only care that the plugin:

    +
      +
    • Should not crash: If a matcher does not compile, then your plugin will not be available in Hansken. Tip: be sure +to test your plugin with the test framework.

    • +
    • Should not be slow: Matching is designed to be extremely fast, but of course, if you make it too complex it can +take longer than we want. In the example above, we calculated that 1 second extra for 1 million traces is 11 days of +extra CPU time. Unlike processing, matching is done for every trace, in every extraction iteration, so be careful!

    • +
    • Should match on the bare minimum: Don’t go too far by matching 50 different criteria before allowing a trace to be +processed. Note that a lot of (if not all) of these criteria depend on properties set by other tools, and you don’t +really have any control on how these tools work.

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/isolation.html b/0.9.16/dev/concepts/isolation.html new file mode 100644 index 0000000..62416b7 --- /dev/null +++ b/0.9.16/dev/concepts/isolation.html @@ -0,0 +1,164 @@ + + + + + + + + + Plugin isolation — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Plugin isolation

    +

    Extraction plugins allows arbitrary code to be executed during a Hansken extraction. This code is executed inside the +Hansken cluster. Extraction plugins are subjected +to Hanskens design principles +such as security, privacy and transparency. To ensure that plugins are compliant to these principles, each plugin will +be executed in isolation. This page describes the isolation measures that are in place.

    +
    +

    User isolation

    +

    The following user restrictions are implied on the plugin:

    +
      +
    • The plugin can not run as root.

    • +
    • Instead, the plugin will run as user 1000

    • +
    • and with group 2000

    • +
    • and with fsgroup 3000

    • +
    +
    +
    +

    System calls

    +

    Plugins are only allowed to call a limited set of (Linux) system calls. This ensures that a plugin can be executed in a +secure manner within the Hansken platform.

    +

    Hansken uses Kubernetes to run extraction plugins. The Kubernetes RuntimeDefault secure computing mode (seccomp) is +enabled to provide a sane default of available system calls.

    +
    +
    +

    Network isolation

    +

    Plugins are not allowed to communicate over the network.

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/kubernetes_autoscaling.html b/0.9.16/dev/concepts/kubernetes_autoscaling.html new file mode 100644 index 0000000..864dc11 --- /dev/null +++ b/0.9.16/dev/concepts/kubernetes_autoscaling.html @@ -0,0 +1,162 @@ + + + + + + + + + Kubernetes, Autoscaling, Resourcemanagement — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Kubernetes, Autoscaling, Resourcemanagement

    +

    Extraction Plugins can be run in a Kubernetes cluster. This can be the same cluster Hansken run on, or another external +cluster. For each plugin, a pod is created by Hansken. Each plugin will have 12 threads by default to process traces +separately within one pod.

    +
    +

    Autoscaling

    +

    Hansken will create a Horizontal Pod Autoscaler (HPA) for each pod. HPA’s manage the number of replica’s of a pod +based on metrics. The Extraction Plugins SDK provides two metrics to be set in the PluginInfo:

    +
      +
    • Observed CPU utilization

    • +
    • Observed memory usage

    • +
    +

    For more info on how to set these metrics follow these links:

    + +

    If a pod reaches the CPU or memory usage provided with the PluginInfo, the HPA will increase the number of replicas for +that plugin. Scaling down is done automatically. The maximum number of replicas per pod is specified within Hansken +properties and can be adapted by an operator (needs restart).

    +
    +
    +

    Finding the right settings

    +

    This depends on the kubernetes cluster settings, the nodes it runs on, and of course the plugin itself. Monitor the +number of replica’s and resource metrics while an extraction is running and adapt accordingly.

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/plugin_naming_convention.html b/0.9.16/dev/concepts/plugin_naming_convention.html new file mode 100644 index 0000000..c4d121e --- /dev/null +++ b/0.9.16/dev/concepts/plugin_naming_convention.html @@ -0,0 +1,233 @@ + + + + + + + + + Plugin naming convention — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Plugin naming convention

    +
    +

    Plugin identifier

    +

    Each extraction plugin has a unique identifier. The identifier consists of three fields. These three fields combined +form the plugin name.

    +

    The three fields of a plugin identifier are: domain, category, and name. The fields are described in more detail +below.

    +

    domain +The domain name of the organisation where the plugin is created. If an organisation has multiple domain names, the +shortest name is preferred over the longer domain names. Examples: nfi.nl, politie.nl, fiod.nl, hansken.org.

    +

    category +A type of action that the plugin performs. The category is a free text field, but the following table gives some +recommendations.

    + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Category

    Description

    extract

    The plugin parses a clear data structure

    carve

    The plugin parses data fragments to reassemble traces in the absence of filesystem metadata

    classify

    The plugin categorizes a plugin based on its content, e.g. detecting money on traces of type picture

    digest

    The plugin digests data to compute a hash

    ocr

    The plugin applies ocr (optical character recognition) to read text on pictures or scanned documents

    match

    The plugin matches a trace against a database, and reports whether there was hit or miss, e.g. matching a trace to a well known files database

    +

    name +The name of the plugin, or in the classic sense, a description detailing what the plugin processes. Note that the name +can contain (forward) slashes.

    +
    +
    +

    Examples

    +

    The following table shows a list of plugin identifiers. The last column of the table shows the derived full plugin name. +The derived full plugin name will be shown in Hansken.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Domain

    Category

    Name

    Derived plugin name

    Explanation

    hansken.org

    extract

    archive

    hansken.org/extract/archive

    A plugin created by the Hansken development team that extracts traces from an arbitrary archive format

    nfi.nl

    extract

    archive/zip

    nfi.nl/extract/archive/zip

    A plugin created by an NFI team that extracts traces from a specific archive format: zip

    politie.nl

    extract

    archive/zip

    politie.nl/extract/archive/zip

    The same as the previous example, but now the plugin is created by a different organisation: politie.nl

    hansken.org

    carve

    archive/zip

    hansken.org/carve/archive/zip

    A plugin that carves data to detect a specific archive format: zip

    hansken.org

    digest

    sha256

    hansken.org/digest/sha256

    A plugin that digests data to compute a sha256 hash

    hansken.org

    ocr

    tesseract

    hansken.org/ocr/tesseract

    A plugin that performs ocr using tesseract

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/plugin_types.html b/0.9.16/dev/concepts/plugin_types.html new file mode 100644 index 0000000..22e2b10 --- /dev/null +++ b/0.9.16/dev/concepts/plugin_types.html @@ -0,0 +1,215 @@ + + + + + + + + + Extraction plugin types — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Extraction plugin types

    +

    Currently four types of Hansken Extraction Plugins are supported:

    +
      +
    • Standard Extraction Plugins

    • +
    • Meta Extraction Plugins

    • +
    • Deferred Extraction Plugins

    • +
    • Deferred Meta Extraction Plugins (Python only)

    • +
    +
    +

    Standard Extraction Plugins

    +

    Standard Extraction Plugins provide enough functionality for most cases. This includes:

    +
      +
    • Processing traces

    • +
    • Creating child-traces

    • +
    • Reading trace properties

    • +
    • Adding trace properties

    • +
    • Reading data

    • +
    • Writing data

    • +
    • Writing data transformations

    • +
    +
    +
    +

    Meta Extraction Plugins

    +

    Meta Extraction Plugins can only process and produce trace properties without the need (or possibility) for processing +actual trace data. This includes:

    +
      +
    • Processing traces

    • +
    • Creating child-traces

    • +
    • Reading trace properties

    • +
    • Adding trace properties

    • +
    +
    +
    +

    Deferred Extraction Plugins

    +

    These plugins have two additional features that are not included with Standard Extraction Plugins:

    +
      +
    • a developer can choose to defer their execution

    • +
    • information about other traces can be obtained while processing the current extraction trace. Code examples can be +found here: Java, Python.

    • +
    +

    Deferring execution +A single Hansken image extraction consists of multiple iterations. Within every iteration, every Hansken tool and +plugin is executed on matching traces, which produces new traces or modifies existing traces. If a tool can be executed +another time because of these additions or modifications, another iteration is started.

    +

    A regular plugin is executed in the same iteration a trace is matched. Deferred plugins are executed in a different +iteration; they are always deferred for at least one iteration. This is very useful when searching for traces, because +you are certain the deferred plugin is executed after all other tools performed their modifications.

    +

    Sometimes, executing your plugin in the next iteration is not enough; it needs to be executed in a different iteration. +This is why the SDK allows setting a deferredIterations parameter in the plugin info. After the plugin matches with a +trace, it will be executed after deferredIterations. The execution can currently be deferred by a maximum of 20 +iterations and the default is 1.

    +

    Searching for traces +This type of plugin can perform a search to look for extracted traces in the current image (default) or +project (optional). This search is performed using a provided HQL query. +A maximum of 50 traces is returned for a given search request.

    +
    +

    Warning

    +

    Please note that HQL-Lite specific syntax such as the Data or DataType matchers is NOT supported.

    +
    +
    +
    +

    Deferred Meta Extraction Plugins

    +

    These plugins have two additional features that are not included with standard Extraction Plugins:

    +
      +
    • a developer can choose to defer their execution

    • +
    • information about other traces can be obtained while processing the current extraction trace. Code example can be +found here: Python.

    • +
    +

    Deferred Meta Extraction Plugins can only process and produce trace properties without the need (or possibility) for processing +actual trace data. This includes:

    +
      +
    • Processing traces

    • +
    • Creating child-traces

    • +
    • Reading trace properties

    • +
    • Adding trace properties

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/test_framework.html b/0.9.16/dev/concepts/test_framework.html new file mode 100644 index 0000000..d896065 --- /dev/null +++ b/0.9.16/dev/concepts/test_framework.html @@ -0,0 +1,428 @@ + + + + + + + + + Test framework — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Test framework

    +

    The SDK provides the FLITS Test Framework for integration testing. This allows us to test/validate the plugin input +and output without having a running Hansken instance.

    +

    To use the test framework, three components are required:

    +
      +
    1. A running server instance of an extraction plugin. See section How to test your plugin.

    2. +
    3. Input test data

    4. +
    5. Results (expected output)

    6. +
    +
    +

    Creating test data

    +

    The test data is independent of which programming language is used for the plugin (Java or Python). This section +describes the setup of the test data, while the sections thereafter will link to the language specific documentation.

    +
    +

    Basic test data directory structure

    +

    Example test data directory structure with an inputs and results directory:

    +
    tests/
    +├── inputs
    +│   ├── example1.raw
    +│   ├── example1.text
    +│   ├── example1.trace
    +│   ├── example2.raw
    +│   └── example2.trace
    +└── results
    +    ├── example1.raw.PluginName.trace
    +    ├── example1.text.PluginName.trace
    +    └── example2.raw.PluginName.trace
    +
    +
    +

    The inputs folder contains all traces that will be processed during the test. These ‘input traces’ are defined in +files with the ‘.trace’ extension, using JSON. This JSON structure is explained in section +Trace format. Each trace may have various data-streams. The data for each trace +is put into separate files for each data-stream. The data-stream files need to have the same name as their corresponding +trace file but differ in extension. They can have any extension, for example ‘raw’, ‘text’ or ‘jpeg’. Note that one +input trace will always have one ‘.trace’ file, and can have none, one or many data files. Also note that if the +plugin doesn’t match on any of the input files and there are no result files yet, the test will succeed.

    +
    +

    Note

    +

    The test-framework uses the extension of the input test file(s) _(other than __.trace__)_ as type of the +current data-stream.

    +
    +

    The expected results (which are also traces) are stored in a separate results folder next to the inputs folder. The +file names in the results folder correspond to the file names in the inputs folder. Note that the name of the plugin +is added between the file basename and the file extension. This can be useful if one maintains a single test input and +output test datasets for multiple extraction plugins.

    +
    +

    Note

    +

    It is possible to let the test framework regenerate the results files automatically. See the +Java and Python sections on testing on how to do this. If no files are +being generated, check if the plugin matcher is actually matching the input files.

    +
    +

    The test runner will invoke the extraction plugin for each input trace. The test runner collects the plugin output and +compares it against the trace defined in the results folder. If there is a mismatch, the test runner will fail with an +exit code 1. If all tests pass the test runner will finish with exit code 0.

    +

    Given the files in the example above, the test runner will invoke the extraction plugin three times:

    + + + + + + + + + + + + + + + + + +

    Input

    Result

    example1.trace with data stream example1.raw

    example1.raw.PluginName.trace

    example1.trace with data stream example1.text

    example1.text.PluginName.trace

    example2.trace with data stream example2.text

    example2.raw.PluginName.trace

    +
    +
    +

    Test data structure for deferred extraction plugins

    +

    Deferred extration plugins have the unique ability to search traces with a query. +The input test data should be extended to contain the results of searches done by deferred extraction plugins. These +search traces are stored in separate folders that follow the naming format ‘{deferred trace name}/searchtraces/’. Below +is an example test data directory structure for a deferred extraction plugin that searches for +a deferredExampleSearch.trace:

    +
    tests/
    +├── inputs
    +│   ├── deferredExample.trace
    +│   ├── deferredExample.raw
    +│   ├── deferredExample/
    +│   │   ├── searchtraces/
    +│   │   │   ├── deferredExampleSearch.trace
    +└── results
    +    └── deferredExample.raw.DeferredPluginName.trace
    +
    +
    +
    +

    Warning

    +

    The plugin will try to match on all traces in the input folder, including traces used for search results ( +of deferred extraction plugins). This means that it is impossible to search on traces that match the same deferred +extraction plugin, as it would create an infinite loop.

    +
    +

    Given the files in the example above, the test runner will invoke the extraction plugin one time:

    + + + + + + + + + + + +

    Input

    Result

    deferredExample.trace with data stream deferredExample.raw

    deferredExample.raw.DeferredPluginName.trace

    +
    +

    Warning

    +

    The search query should be written in HQL, as that is how Hansken will interpret it. However, the test +framework interprets the query using its HQL-lite interpreter. Therefore, not all queries will be supported.

    +
    +
    +
    +

    Trace format

    +

    Input and result traces both stored in a JSON structure. There is however a slight difference between the two: The +result trace may store additional values that are purely there for testing purposes. The input format will first be +discussed, followed by the result format.

    +
    +

    Input trace JSON format

    +

    Input traces start with a trace key, which contains a mapping of properties. The property names are split in a +dictionary structure. The example below shows a serialized trace with six properties: data.raw.mimeClass and the five +data types that are currently supported by the test-framework.

    +

    The data key defines the data-streams of the trace. When adding a data-stream make sure you also +add the corresponding input data file, as described above.

    +
    {
    +  "trace": {
    +    "data": {
    +      "raw": {
    +        "mimeClass": "text"
    +      }
    +    },
    +    "supported data types": {
    +      "Boolean": true,
    +      "Integer": 1,
    +      "Double": 0.1,
    +      "String": "a string",
    +      "StringList": [
    +        "a",
    +        "b",
    +        "c",
    +        "d"
    +      ]
    +    }
    +  }
    +}
    +
    +
    +
    +

    Warning

    +

    The extraction plugin SDK and the test framework have no knowledge of the +trace model. This means that when properties are used that don’t +comply with the trace model, this will not cause the test to fail, but it will fail when running your plugin in Hansken.

    +
    +
    +
    +

    Result trace JSON format

    +

    The result traces have the same format as the input traces, namely a trace key which contains the full input trace +with all its properties. However, the result traces may have two additional keys children and data (which are +explained in-depth below). These are added for testing purposes. If the plugin adds child traces +or writes data transformations to Hansken, this would normally not reflect on the JSON of the +trace. However, the test framework adds these to the result JSON structure to be able to test them.

    +

    Consequently, result traces are stored in a JSON structure that may consist of up to three parts, namely the always +present trace and the occasional children and data:

    +
      +
    • trace: The key trace contains a mapping of its properties, in exactly the same way as is done for input traces.

    • +
    • children: :ref:Child traces <child traces> that have been created by the plugin during the test are stored under a +reserved field children, which is a list of traces. The example trace below contains a child trace with a property +name.

    • +
    • data: Data transformations that have been created by the plugin during the test are +stored under a reserved field data. For each data-stream type there is a descriptor field describing the data +transformation in a JSON format. The example trace has a ranged data transformation for the raw data-stream. Note that +this data is entirely different from the data key that may be present inside the trace!

    • +
    +
    {
    +  "trace": {
    +    "data": {
    +      "raw": {
    +        "mimeClass": "text"
    +      }
    +    },
    +    "supported data types": {
    +      "Boolean": true,
    +      "Integer": 1,
    +      "Double": 0.1,
    +      "String": "a string",
    +      "List": [
    +        "a",
    +        "b",
    +        "c",
    +        "d"
    +      ]
    +    }
    +  },
    +  "children": [
    +    {
    +      "trace": {
    +        "name": "child trace 1"
    +      }
    +    }
    +  ],
    +  "data": {
    +    "raw": {
    +      "descriptor": "[{\"ranges\":[{\"length\":79,\"offset\":0}]}]"
    +    }
    +  }
    +}
    +
    +
    +
    +
    +
    +

    Testing exceptions

    +

    Some scenarios may throw exceptions and this can be part of your tests too. For example, an input file that has the +wrong format can be part of your integration tests. When an exception occurs during the test, it will be written to the +result file. This can be deliberately used to test exceptions. However, it is often impractical to match against a full +exception. For example, the row numbers in the exception are very much prone to change due to circumstances irrelevant +to the case being tested. Therefore, the testframework provides some options to match only on those parts of result +files that are relevant to the test.

    +

    The following sections will explain these partial result matchers using the following example exception:

    +
    {
    +  "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException",
    +  "message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris faucibus varius sodales."
    +}
    +
    +
    +
    +

    Leaving out the message

    +

    It is possible to leave of the message of the exception, which will still result in a valid result:

    +
    {
    +  "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException"
    +}
    +
    +
    +
    +
    +

    The startsWith partial result matcher

    +

    The startsWith partial result matcher requires a string as a parameter. The result will be valid if the actual result +starts with this string.

    +
    {
    +  "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException",
    +  "message.startsWith": "Lorem ipsum dolor sit amet, "
    +}
    +
    +
    +
    +
    +

    The containsInOrder partial result matcher

    +

    The containsInOrder partial result matcher requires a list of strings as a parameter. The result will be valid if +every string in the list can be found in that same order in the actual result.

    +
    {
    +  "class": "org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginException",
    +  "message.containsInOrder": [
    +    "Lorem ipsum dolor sit amet,",
    +    "consectetur adipiscing elit.",
    +    "Mauris faucibus varius sodales."
    +  ]
    +}
    +
    +
    +
    +
    +
    +
    +

    How to test your plugin

    +

    Running an integration test for an extraction plugin depends on the language in which the extraction plugin is built.

    +
    +

    Java

    +

    The Test Framework itself is built in Java. When building extraction plugins with Java, it can be incorporated in your +unit tests, as shown in Using the Test Framework in Java.

    +
    +
    +

    Python

    +

    The Python SDK also uses the Java based Test Framework. This is done by providing a wrapper to make calls to an included +Test Framework ‘jar’ file. See Advanced use of the Test Framework in Python for documentation +and examples on how to use FLITS for testing your Python plugin.

    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/concepts/traces.html b/0.9.16/dev/concepts/traces.html new file mode 100644 index 0000000..304bc9a --- /dev/null +++ b/0.9.16/dev/concepts/traces.html @@ -0,0 +1,340 @@ + + + + + + + + + Traces & Trace model — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Traces & Trace model

    +
    +

    Traces

    +

    Traces are structured data objects produced by tools/plugins during an extraction. A trace represents a piece of +information found in an evidence file.

    +

    The following figure shows the main elements of a trace. Each element is described in more detail in the following +paragraphs.

    +trace.svg +
    +

    Types and Properties

    +

    A trace has properties that describe the information of it by means of a property value. Trace properties are grouped by +a trace type. A trace can have multiple types.

    +

    All types and properties that can be set are defined in the Hansken trace model.

    +

    An example of a type is document, which could have the properties application and createdOn. The trace will have a +type document, and can the following properties with values:

    +
    document.application: Libre Office
    +document.createdOn: 2021-09-18 20:00:00
    +
    +
    +
    +
    +

    Intrinsic properties

    +

    A trace has several intrinsic properties. These are properties that are not related to a trace type. The intrinsic +properties available to extraction plugins are:

    +
      +
    • id: a unique identifier of the trace, generated when a trace is created

    • +
    • name: a name given to a trace when it is created

    • +
    • path: a logical path of the trace, of which the elements are the names of traces from the root trace until this +trace

    • +
    +
    +
    +

    Data streams

    +

    Typically, a trace represents a piece of data found in an evidence file. This data is part of the trace and available as +a data stream. A trace can have multiple data streams. Each data stream has a type. Data streams can also have +properties that apply to the data stream itself. The data stream properties are modeled as properties of the trace, in +the following pattern: +data.<datastreamtype>.propertyname (where <datastreamtype> is substituted by the actual type of the data stream).

    +

    The set of data stream types and data stream properties is fixed. All allowed types and properties are defined in the +Hansken trace model (see data).

    +

    An important data stream property is the fileType property. This property contains a textual description of the +detected file type for the data stream. An example of a fileType is ‘Adobe Pdf’. The fileType is a good candidate +to use in a extraction plugin ‘matcher’. This fileType is detected by Hansken using file type heuristics, which are +primarily based on the data stream bytes itself, and secondarily on other metadata such as a file extension. +(N.B. The fileType is detected in Hansken by the extraction tool FireFli.) For more information on how datastream +properties can be used for matching, see here.

    +

    Note that not all traces have data streams. In these cases it is a trace of meta-data derived from another trace.

    +

    Usually, each trace with data has a data stream of type raw. This data stream contains the bytes of the traces as they +were found when the trace was created. In some occasions, the raw data can be represented in a different form before it +can be processed further, for example if the data can be decoded or decrypted. Hansken tools and plugins can decode +the raw data stream to a standard UTF-8 data stream, or can decrypt the data if a decryption key is present. Hansken +tools and extraction plugins can store the new data at the new trace in a new data stream. This new data stream has a +different type than the raw type.

    +

    Examples in code can be found here:

    +
      +
    • Adding a Datastream Java

    • +
    • Adding a Datastream Python

    • +
    +
    +
    +

    Child traces

    +

    A trace can have child traces. For example, a trace of type archive can have children, where each child is a trace +that represents an entry in the archive.

    +

    With an extraction plugin it is possible to create child traces for a trace that is being processed. New properties, +data streams, and other child traces can be set on the new child traces. When a child trace is created, the plugin +should provide a name for the child trace. The id of the child trace is generated, in the following +form: parenttraceid-childnumber. For example, if the parent has an id 0-0-0-0-0:0-9, the first child gets the +id 0-0-0-0-0:0-9-1, the second child gets the id 0-0-0-0-0:0-9-2, and so on.

    +

    Note that a trace does not have (direct) access to its parent trace.

    +
    +
    +

    Trace property types

    +

    The SDK supports the following property types for traces:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Java

    Python

    binary

    byte[]

    bytes / bytearray

    boolean

    boolean

    bool

    integer

    int / long

    int

    real

    float / double

    float

    string

    String

    str

    date & time

    Date

    datetime

    list

    List

    list / tuple

    mapping

    Map

    dict

    location

    LatLong

    GeographicLocation

    vector

    Vector

    Vector

    tracelet

    see Tracelets below

    see Tracelets below

    +

    Both location and vector types are available from the SDK, Java package org.hansken.plugin.extraction.api or Python module hansken.util.

    +
    +

    Vector

    +

    A vector is a data type that can be used to store points in n-dimensional space as an array of floating point values. +Once indexed, the vectors can then be used in a gui or other client to search for traces that have a nearby vectors. +For example, it is possible to use a neural network that provides embeddings of human faces as vectors. Once indexed, +the vectors can then be used to find pictures with similar faces. To do this, the search rest api can be used to +sort by the euclidean- or manhattan distance, or cosine similarity to a given vector.

    +
    +
    +

    Tracelets

    +

    A Tracelet is a bundle of property values that belong to a single type. It is a property on a trace that can have +multiple properties itself, making it a list of key/value pairs. The API doesn’t specify the cardinality, but the +implementation is limited to cardinality ‘Few’. In Hansken these are called FVT’s (Few Valued Types).

    +
    +

    Note

    +

    MVT’s (Many Valued Types) are currently not supported in the SDK and will be added in a future release.

    +
    +

    An example of a tracelet is the prediction property, which describes a category or class a trace belongs to. It is +possible for a trace to have multiple predictions. Therefore prediction is a tracelet. Other examples of +tracelets are identity and collection.

    +

    Examples in code can be found here:

    +
      +
    • Adding tracelets in Java

    • +
    • Adding tracelets in Python

    • +
    +
    +
    +
    +
    +

    Hansken trace model

    +

    All traces in Hansken are based on a specific version of the trace model, and must comply to that version of the trace +model. This is a nested data structure composed of origins, categories, types and properties.

    +

    All non-inrinsic trace properties are optional and are grouped by type. These types are defined under the trace +model section ‘categories’. Every category has a list of allowed types. When a trace is identified as being a +document, it will get this set of predefined document properties. Trace types can have different origins. The +possible origins are defined in the trace model section ‘origins’. An example of this is the processed types that are +always generated by the system during an extraction.

    +

    The details of the current trace model can be retrieved using the /tracemodel +REST call on the Gatekeeper endpoint of Hansken, or check the Hansken Documentation on the trace model.

    +
    +

    Trace model and the extraction plugin SDK

    +
    +

    Warning

    +

    The extraction plugin SDK has no knowledge of the trace model

    +
    +

    The Extraction Plugins SDK has no knowledge of the trace model at this time. It is however possible to create new traces +with plugins. If any newly created Traces don’t comply to the model, Hansken will not accept them and mark the plugin +execution as failed. The Extraction Plugins SDK and the provided Test Framework don’t check this. +Please make sure to use the right naming when creating new Traces, as provided by the trace model.

    +

    If an erroneous trace property is set, Hansken will show an error. The error can be found in the Hansken Expert UI +interface by double-clicking on the trace. Then the trace details screen will be opened and the error will be displayed +as follows:

    +../../_images/toolrun_error.png +

    This error describes that a property does not exist in the trace model. To get more information about the error, the +extraction log can be viewed. In the extraction log you have to search +for java.lang.IllegalArgumentException: no such type to find out which property is not supported by the trace model.

    +

    In the example extraction log below, the property this_property_does_not_exist could not be found 681 times.

    +
    Cumulative warnings, based on the message without numbers, uuids and trace objects. Only showing full message for first warning of this type.
    +      Count | Key                                                   | Message
    +        681 | org.hansken.ep.shade.io.grpc.StatusRuntimeException   | CANCELLED: Cancelled by client with StreamObserver.onError(); org.hansken.ep.shade.io.grpc.StatusRuntimeException: ABORTED: java.lang.IllegalArgumentException: no such type: this_property_does_not_exist
    +          7 | java.lang.IllegalStateException                       | call was cancelled
    +          1 | org.hansken.ep.shade.io.grpc.StatusRuntimeException   | UNAVAILABLE: HTTP/2 error code: NO_ERROR Received Rst Stream
    +
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/examples.html b/0.9.16/dev/examples.html new file mode 100644 index 0000000..de2719c --- /dev/null +++ b/0.9.16/dev/examples.html @@ -0,0 +1,122 @@ + + + + + + + + + Examples — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Examples

    +

    Extraction Plugin Examples in both Java and Python can be found in the +Hansken Extraction Plugin Examples Repository +hosted on Github.

    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/faq.html b/0.9.16/dev/faq.html new file mode 100644 index 0000000..9c0c08e --- /dev/null +++ b/0.9.16/dev/faq.html @@ -0,0 +1,191 @@ + + + + + + + + + Frequently Asked Questions — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Frequently Asked Questions

    +
    +

    How can I access Hansken developer community

    +

    You will first need git access to the Hansken developer community. Here you can find started guides and examples. If you +have no access yet, you can get access by following the next steps:

    +
      +
    1. Sign up at git.eminjenv.nl

    2. +
    3. After you have created your account, you should request access to the ” +Hansken Community” group . Do this by contacting your organisations Hansken business owner. If you don’t know who to +contact as your business owner, please read the Contact page.

    4. +
    +
    +
    +

    Why use Extraction Plugins?

    +

    Extraction plugins enable you to run your own extraction code in Hansken.

    +
      +
    • Your plugin runs during extraction

    • +
    • Extraction plugins are faster than Hansken.py

    • +
    • Multiple programming languages are supported

    • +
    • Scalability: Extraction plugins can be scaled flexibly on a kubernetes cluster

    • +
    +
    +
    +

    What programming languages are supported?

    +

    The SDK contains an API and tools to write a Hansken extraction plugin in Java or Python. The Java API can be used to +develop extraction plugins in JVM-compatible languages, such as Scala and Kotlin.

    +
    +
    +

    Will you support language foobar?

    +

    Probably not. It takes time and effort to create a proper SDK. If you think there is a good use case to support +language foobar, and there is gRPC support, feel free to contact us. We can discuss the options to add support for +Hansken extraction plugins with foobar.

    +

    Under the hood, extraction plugins use gRPC to communicate with Hansken. In theory, all programming languages that have +a gRPC implementation can be used to write Hansken extraction plugins.

    +
    +
    +

    Can I reuse or modify the Extraction Plugins SDK?

    +

    The SDK is distributed under the Apache 2.0 License, see the LICENSE file in the SDK for more details.

    +
    +
    +

    Can I use a plugin that someone else wrote?

    +

    Yes, at your own risk. The Hansken Team does not take responsibility for code written by third parties in the form of +Extraction Plugins.

    +
    + +
    +

    How safe are Extraction Plugins?

    +

    We are doing everything to make sure Extraction Plugins are as safe as possible, however note that the Extraction Plugin +SDK is still in beta. Use it at your own risk. For more information on security see Isolation.

    +
    +
    +

    Can my Extraction Plugin be embedded into Hansken for performance reasons?

    +

    Embedding an Extraction Plugin into Hansken requires access to the Hansken source code. If you have access to the source +code then please ../contact us for assistance. Please note that embedded Extraction Plugins are not officially +supported.

    +

    If you do not have access to the Hansken source code, then please contact your own Business Owner, and ask them to +contact the Hansken Team.

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/introduction.html b/0.9.16/dev/introduction.html new file mode 100644 index 0000000..0203a2b --- /dev/null +++ b/0.9.16/dev/introduction.html @@ -0,0 +1,171 @@ + + + + + + + + + Introduction — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Introduction

    +

    The Extraction Plugin Software Development Kit can be used to develop a Hansken +extraction plugin.

    +

    Hansken is designed to give access to and insight in digital data and traces originating from seized and demanded +digital material. One aspect of the Hansken platform is the extraction engine (extraction framework). The extraction +engine contains digital forensics knowledge, which is used to find traces in digital material. With extraction plugins +case investigators can add new digital forensics knowledge to the extraction framework. In this way, Hansken is enabled +to understand new digital formats, and thus is able to find new types of traces in the seized and demanded material.

    +

    Examples of digital forensics knowledge that can be added to Hansken with extraction plugins:

    +
      +
    • new file formats (e.g. a new crypto currency wallet)

    • +
    • combine traces to find new information (e.g. use a windows registry entry required to read a file from disk)

    • +
    • apply algorithms on traces (e.g. speech to text from audio files)

    • +
    +

    The primary goals of this SDK are:

    +
      +
    • to make it as easy as possible to add new digital forensics knowledge to Hansken.

    • +
    • be able to share digital forensics knowledge with other Hansken community members

    • +
    +
    +

    Software Development Kit (SDK)

    +

    In order to create extraction plugins, the Hansken project maintains an Extraction Plugin Software Development Kit +(SDK).

    +

    This SDK contains the following elements:

    +
      +
    • Java API and tooling, to be able to write an extraction plugin with the Java +programming language

    • +
    • Python API and tooling, to be able to write an extraction plugin with Python +programming language

    • +
    • Test framework, to be able to test extraction plugins before they are used production

    • +
    • Documentation for plugin developers to help understand the SDK and all its facets (this documentation)

    • +
    • Examples

    • +
    +
    +
    +

    Development steps of a plugin

    +

    To create a plugin, the plugin developer could follow the following steps. Detailed information per step will be added +later to the documentation.

    +
      +
    1. Create a new empty plugin

    2. +
    3. Implement the plugin logic

    4. +
    5. Verify the plugin using the test framework, using reference data (test data) and +expected output

    6. +
    7. Test the plugin in Hansken

    8. +
    9. Use the plugin in an actual case

    10. +
    11. Share the plugin with the Hansken community, so other case investigations can benefit from the plugin as well ( +optional, but encouraged)

    12. +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java.html b/0.9.16/dev/java.html new file mode 100644 index 0000000..77d1e09 --- /dev/null +++ b/0.9.16/dev/java.html @@ -0,0 +1,140 @@ + + + + + + + + + Java — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/api_changelog.html b/0.9.16/dev/java/api_changelog.html new file mode 100644 index 0000000..34a77f3 --- /dev/null +++ b/0.9.16/dev/java/api_changelog.html @@ -0,0 +1,449 @@ + + + + + + + + + Java API Changelog — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Java API Changelog

    +

    This document summarizes all important API changes in the Extraction Plugin API. This document only shows changes that +are important to plugin developers. For a full list of changes per version, please refer to the general +changelog.

    +
    +

    0.9.13

    +
      +
    • This release introduces a new parameter bulkMode to the PluginInfo. This can be used for +lightweight plugins which have to process a lot of data (either a lot of traces or a small +number of traces with large data streams). These plugins will run inside the worker pod for streaming extractions, +and will therefore be able to process data more efficiently.

    • +
    +
    +
    +

    0.9.11

    +
      +
    • This release allows the user to search for more than 50 traces using the TraceSearcher in deferred extraction plugins.

    • +
    +
    +
    +

    0.9.10

    +
      +
    • This release introduces the deferred meta extraction plugin. This plugin type can defer their execution and +processes a trace only with its metadata, without processing its data and accesses traces using the searcher. +This makes it possible to use deferred plugins in combination with traces without data. +Note: Hansken will support these types of plugins from v47.34.0.

    • +
    • This release introduces new parameters for the TraceSearcher, start and sort. +This allows the searcher can get a certain range of traces in a specific order. +Note: Hansken will support these types of plugins from v47.34.0.

    • +
    +
    +
    +

    0.9.5

    +
      +
    • The internal (de)serialization of some types has changed. Please update the extraction plugin sdk to match the one used in Hansken.

    • +
    +
    +
    +

    0.8.0

    +
      +
    • The trace property imageId is renamed to image. This is to be in line with the Hansken REST API and Python API. +When updating your plugin, please update your calls trace.get("imageId") to trace.get("image").

    • +
    • #774 +By default, deferred extraction plugin searches are now scoped to the image +of the trace that is currently being processed. Optionally, a project-wide +search can be done by passing an optional scope argument.

      +
      @Override
      +public void process(final Trace trace, final ExtractionContext context, final TraceSearcher searcher) {
      +    // only search for traces inside the same image as the trace that is being processed
      +    final SearchResult result = searcher.search("file.extension=asc", 10);
      +    final SearchResult result = searcher.search("file.extension=asc", 10, TraceSearcher.SearchScope.IMAGE);
      +
      +    // search for all traces inside the same project as the trace that is being processed
      +    final SearchResult result = searcher.search("file.extension=asc", 10, TraceSearcher.SearchScope.PROJECT);
      +}
      +
      +
      +
    • +
    • Support trace properties of type List<Integer>, List<Double>, and List<Float>. +This enables you to write multiple offsets and confidence scores in tracelets of type prediction.

      +

      For example:

      +
      trace.addTracelet("prediction", tracelet -> {
      +    tracelet.set("modelName", "my_cat_detector");
      +    tracelet.set("modelVersion", "0.0.BETA");
      +    tracelet.set("type", "classification");
      +    tracelet.set("label", "cat");
      +
      +    tracelet.set("offset", 3.0);
      +    tracelet.set("confidence", 0.4);
      +
      +    tracelet.set("offsets", List.of(0.0, 3.0, 6.0, 9.0));
      +    tracelet.set("confidences", List.of(0.1, 0.4, 0.03, 0.09));
      +})
      +
      +
      +
    • +
    +
    +
    +

    0.7.0

    +
      +
    • Escaping the / character in matchers is optional. +This simplifies and aims for better HQL and HQL-Lite compatability. +See for more information and examples the HQL-Lite syntax documentation.

      +

      Examples:

      +
        +
      • file.path:\\/Users\\/*\\/AppData -> file.path:/Users/*/AppData

      • +
      • registryEntry.key:\\/Software\\/Dropbox\\/ks*\\/Client-p -> registryEntry.key:/Software/Dropbox/ks*/Client-p

      • +
      +
    • +
    • Hansken returns file.path properties as a String property, instead of a List<String>. +Example: trace.get("file.path") now returns "/dev/null", this was ["dev", "null"].

    • +
    +
    +
    +

    0.6.3

    +
      +
    • A plugin can now write multiple data streams to a single trace concurrently, +e.g. write both decrypted and ocr at the same time. See the “Adding data to a trace” code snippets for +general examples on adding data to a trace.

    • +
    +
    +
    +

    0.6.1

    +
      +
    • The JAVA SDK is now distributed through maven central instead of the Hansken community.

    • +
    +
    +
    +

    0.6.0

    +
    +

    Warning

    +

    It is highly recommended to upgrade your plugin to this new version. +See the migration steps below.

    +
    +
      +
    • Extraction plugin container images are now labeled with PluginInfo. This +allows Hansken to efficiently load extraction plugins.

    • +
    • By default, extraction plugin version is managed in the plugin’s pom.xml. +The .pluginVersion(..) can be removed from the PluginInfo builder.

    • +
    • Migration steps from earlier versions – for plugins that use the Java +extraction plugin SuperPOM:

      +
        +
      1. Update the SDK version in your pom.xml

      2. +
      3. If you come from a version prior to 0.4.0, or if you use a plugin name +instead of a plugin id in your pluginInfo(), switch to the plugin id style +(read instructions for version 0.4.0)

      4. +
      5. Set your plugin version in your project’s pom.xml, and remove the +following from your PluginInfo.Builder:

        +
        .pluginVersion(...)
        +
        +
        +
      6. +
      7. Update your build scripts to build your plugin (Docker) container image. +You should build your plugin container image with the following command:

        +
        mvn package docker:build`
        +
        +
        +

        This will generate a plugin image:

        +
          +
        • The extraction plugin is added to your local image registry +(docker images),

        • +
        • The image name is extraction-plugin/PLUGINID, e.g. +extraction-plugin/nfi.nl/extract/chat/whatsapp,

        • +
        • The image is tagged with two tags: latest, and your plugin version.

        • +
        +

        Nb. If Docker is not available in your environment, podman can be used +as an alternative. See packaging for more +details.

        +
      8. +
      +
    • +
    +
    +
    +

    0.5.0

    +
      +
    • Add new tracelet api Trace.addTracelet(type, consumer). +It can be used like this:

      +
      trace.addTracelet("prediction", tracelet -> tracelet
      +     .set("type", "classification")
      +     .set("label", "label")
      +     .set("confidence", 0.8f)
      +     .set("embedding", Vector.of(1,2,3))
      +     .set("modelName", "yolo")
      +     .set("modelVersion", "2.0"));
      +
      +
      +
    • +
    • Deprecate Trace.addTracelet(Trace)

    • +
    • Support vector data type in trace properties.

    • +
    +
    +
    +

    0.4.13

    +
      +
    • When writing input search traces for tests, it is no longer required to explicitly set an id property. +These are automatically generated when executing tests.

    • +
    +
    +
    +

    0.4.7

    +
      +
    • A new convenience method id(String, String, String) is added to the PluginInfo builder. This removes some +boilerplate code when setting the pluginId. More details on the plugin naming conventions can be found at the +Plugin naming convention section.

      +
      PluginInfo.builderFor(this)
      +          .id("nfi.nl", "extract", "TestPlugin") // new style
      +          .id(new PluginId("nfi.nl", "extract", "TestPlugin")) // old style, but also works
      +          ...
      +
      +
      +
    • +
    +
    +
    +

    0.4.6

    +
      +
    • It is now possible to specify maximum system resources in the PluginInfo. To run a plugin with 0.5 cpu (= 0.5 +vCPU/Core/hyperthread) and 1 gb memory, for example, the following configuration can be added to PluginInfo:

      +
      PluginInfo.builderFor(this)
      +    ...
      +    .pluginResources(PluginResources.builder()
      +        .maximumCpu(0.5f)
      +        .maximumMemory(1000)
      +        .build())
      +    .build();
      +
      +
      +
    • +
    +
    +
    +

    0.4.0

    +
      +
    • Extraction Plugins are now identified with a PluginInfo.PluginId containing a domain, category and name. The +method PluginInfo.name(pluginName) has been replaced by PluginInfo.id(new PluginId(domain, category, name). More +details on the plugin naming conventions can be found at the Plugin naming convention section.

    • +
    • PluginInfo.name() is now deprecated (but will still work for backwards compatibility).

    • +
    • A new license field PluginInfo.license has also been added in this release.

    • +
    • The following example creates a PluginInfo for a plugin with the name TestPlugin, licensed under +the Apache License 2.0 license:

      +
      PluginInfo.builderFor(this)
      +          .id(new PluginId("nfi.nl", "extract", "TestPlugin")) // id.domain: nfi.nl, id.category: extract, id.name: TestPlugin
      +          // .name("TestPlugin") // no longer supported
      +          .pluginVersion("0.4.1")
      +          .author(Author.builder()...build())
      +          .description("A plugin for testing.")
      +          .maturityLevel(MaturityLevel.PROOF_OF_CONCEPT)
      +          .hqlMatcher("*")
      +          .webpageUrl("https://www.hansken.org")
      +          .license("Apache License 2.0")
      +          .build();
      +
      +
      +
    • +
    +
    +
    +

    0.3.0

    +
      +
    • Extraction Plugins can now create new datastreams on a Trace through data transformations. Data transformations +describe how data can be obtained from a source.

      +

      An example case is an extraction plugin that processes an archive file. The plugin creates a child trace per entry in +the archive file. Each child trace will have a datastream that is a transformation that marks the start and length of +the entry in the original archive data. By just describing the data instead of specifying the actual data, a lot of +space is saved.

      +

      Although Hansken supports various transformations, the Extraction Plugins SDK for now only supports ranged data +transformations. Ranged data transformations define data as a list of ranges, each range with an offset and length in +a bytearray.

      +

      The following example sets a new datastream with dataType html on a trace, by setting a ranged data transformation:

      +
      trace.setData("html", RangedDataTransformation.builder().addRange(offset, length).build());
      +
      +
      +

      The following example creates a child trace and sets a new datastream with dataType raw on it, by setting a ranged +data transformation with two ranges:

      +
      trace.newChild(format("lineNumber %d", lineNumber), child -> {
      +    child.setData("raw", RangedDataTransformation.builder()
      +      .addRange(10, 20)
      +      .addRange(50, 30)
      +      .build());
      +});
      +
      +
      +

      More detailed documentation will follow in an upcoming SDK release.

      +
    • +
    +
    +
    +

    0.2.0

    +
    +

    Warning

    +

    This is an API breaking change. Plugins created with an earlier version of the extraction plugin SDK are +not compatible with Hansken that uses 0.2.0 or later.

    +
    +
      +
    • Introduced a new extraction plugin type DeferredExtractioPlugin. Deferred Extraction plugins can be run at a +different extraction stage. This type of plugin also allows accessing other traces using the searcher.

    • +
    • The class ExtractionContext has been renamed to DataContext. The new name DataContext represents the class +contents better. Plugins have to update matching import statements and the type in ExtractionPlugin.process() +implementation in the same way. This change has no functional side effects.

      +

      Old:

      +
      import org.hansken.plugin.extraction.api.ExtractionContext;
      +
      +@Override
      +
      +public void process(final Trace trace, final ExtractionContext context) throws IOException {
      +
      +}
      +
      +
      +

      New:

      +
      import org.hansken.plugin.extraction.api.DataContext;
      +
      +@Override
      +public void process(final Trace trace, final DataContext dataContext) throws IOException {
      +
      +}
      +
      +
      +
    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/debugging.html b/0.9.16/dev/java/debugging.html new file mode 100644 index 0000000..d08411e --- /dev/null +++ b/0.9.16/dev/java/debugging.html @@ -0,0 +1,271 @@ + + + + + + + + + How to debug an Extraction Plugin — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    How to debug an Extraction Plugin

    +

    Debugging is the art of removing bugs — hopefully quickly.

    +
    +

    Locally

    +

    To debug a plugin locally, it is recommended to start the plugin via the IDE by running the integration test. This has +the advantage that breakpoints can easily be put in the code instead of printing log statements, for example.

    +
    +

    Logging

    +

    The logging of the extraction plugin is displayed in the console.

    +
    +
    +
    +

    Locally with Docker

    +

    Debugging an extraction plugin via docker is a bit trickier. Java has the advantage that remote debugging is already +baked in.

    +

    Using Java Remote Debug with Docker containers requires 3 distinct steps:

    +
      +
    1. Build a Docker image

    2. +
    3. Run the Docker image with specific Java tool options

    4. +
    5. Setting breakpoints in your code

    6. +
    +
    +

    Build a Docker image

    +

    If the Docker image is not built, run the following command to build the Docker image:

    +
    mvn package docker:build
    +
    +
    +
    +
    +

    Run the Docker image with specific Java tool options

    +

    In Java, the remote debug functionality is not enabled by default. To enable the remote debug functionality, the +following environments variable must be set in the Docker container:

    +
    JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
    +
    +
    +

    This environment variable allows the debugger to connect to the debuggee (application being debugged). To start the +Docker image with the JAVA_TOOL_OPTIONS environment variable, the following command can be used:

    +
    docker run -p 5005:5005 -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" your_extraction_plugin_name
    +
    +
    +

    The next step is to attach the debugger to the debuggee. +For Intellij, the instructions are clearly described on the following +page: Tutorial: Remote debug

    +
    +
    +

    Setting breakpoints in the code

    +

    The last step is to add breakpoints in the code.

    +
    +
    +

    Logging in Docker

    +

    The logging of the extraction plugin is displayed in the console after running the docker run command. In addition, +the logging is also displayed in the IntelliJ console while debugging.

    +
    +
    +
    +

    Kubernetes

    +

    In kubernetes it is currently not possible to debug via Java Remote Debug because:

    +
      +
    • no debug ports are published;

    • +
    • the container was not started with the environment variable JAVA_TOOL_OPTIONS so debugging is not enabled.

    • +
    +
    +

    Logging in Kubernetes

    +

    If there is authorization to the kubernetes cluster, the logging can be viewed with the following command:

    +
    kubectl logs -f hansken-extraction-plugins/your_extraction_plugin_pod
    +
    +
    +
    +
    +
    +

    Debug HQL

    +

    An HQL query can be debugged by overriding the isVerboseLoggingEnabled() method of the ExtractionPluginFlits class. +The example below shows an example of an embedded FLITS test with verbose logging enabled.

    +
    public class TestPluginFlitsIT extends EmbeddedExtractionPluginFlits {
    +
    +    @Override
    +    public Path testPath() {
    +        return srcPath("integration/inputs/plugin");
    +    }
    +
    +    @Override
    +    public Path resultPath() {
    +        return srcPath("integration/results/embedded/plugin");
    +    }
    +
    +    @Override
    +    protected ExtractionPlugin pluginToTest() {
    +        return new TestPlugin();
    +    }
    +
    +    @Override
    +    public boolean regenerate() {
    +        return true;
    +    }
    +
    +    @Override
    +    protected boolean isVerboseLoggingEnabled() {
    +        return true;
    +    }
    +}
    +
    +
    +

    The following output will then be displayed in the console:

    +
    HQL match found for:
    +$data.type=jpg
    +With trace:
    +dataType=jpg
    +types={file, data}
    +properties={data.raw.mimeType=image/jpg, path=/test-input-trace, file.name=image.jpg, name=test-input-trace, id=0}
    +
    +
    +

    If the HQL query contains an error, it will be shown in the generated test results. An example of an invalid query +is $data.mimeType=image/jpg (slash not escaped). This query will produce an error like the one shown below.

    +
    {
    +  "class": "org.hansken.plugin.extraction.hql_lite.lang.ParseException",
    +  "message": "HqlLiteHumanQueryParser: line 1:20 token recognition error at: '/jpg'"
    +}
    +
    +
    +
    +

    Note

    +

    The error is only shown in the generated trace, so to find out the ParseException override +the regenerate() method from Flits and then let this method return true.

    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/javadoc.html b/0.9.16/dev/java/javadoc.html new file mode 100644 index 0000000..09a4bf4 --- /dev/null +++ b/0.9.16/dev/java/javadoc.html @@ -0,0 +1,130 @@ + + + + + + + + + Javadoc — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Javadoc

    +

    Visit the Javadoc of the Extraction Plugins SDK API.

    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/packaging.html b/0.9.16/dev/java/packaging.html new file mode 100644 index 0000000..ccb9e4e --- /dev/null +++ b/0.9.16/dev/java/packaging.html @@ -0,0 +1,160 @@ + + + + + + + + + Packaging — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Packaging

    +

    Extraction plugins are packaged as OCI images (also known as Docker images). +The OCI images are labeled with the PluginInfo. +To automate packaging of a Java plugin and labeling the OCI image, the Extraction Plugin SuperPom has been configured to automate this for you.

    +

    If your project uses the Extraction Plugin SuperPom (see Prerequisites), Packaging an extraction plugin is handled by Maven. +To package your plugin into a container image, the following command can be used:

    +
    mvn package docker:build
    +
    +
    +

    This will generate a plugin image:

    +
      +
    • The extraction plugin is added to your local image registry +(docker images),

    • +
    • The image name is extraction-plugin/PLUGINID, e.g. +extraction-plugin/nfi.nl/extract/chat/whatsapp,

    • +
    • The image is labeled with two tags: latest, and your plugin version.

    • +
    +

    It is possible to apply extra arguments to the docker command as described here. +For example, to specify a proxy, use the following command:

    +
    mvn package docker:build -Ddocker.buildArg.https_proxy=https://proxy:8001
    +
    +
    +

    Once your plugin is packaged, it can be published or ‘uploaded’ to Hansken. +See “Upload the plugin to Hansken” for instructions.

    +

    Note: if your build environment does not have Docker available, you can use +podman as an alternative. Install podman on your machine +or build agent, and run the following commands before invoking the +mvn package docker:build command:

    +
    podman system service --time=0 unix:/run/user/$(id -u)/podman/podman.sock &
    +export DOCKER_HOST="unix:/run/user/$(id -u)/podman/podman.sock"
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/prerequisites.html b/0.9.16/dev/java/prerequisites.html new file mode 100644 index 0000000..fbe212d --- /dev/null +++ b/0.9.16/dev/java/prerequisites.html @@ -0,0 +1,171 @@ + + + + + + + + + Prerequisites — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Prerequisites

    +

    Required software:

    +
      +
    • Java 11 or higher

    • +
    • Docker for packaging and publishing plugins +(or use a Docker alternative such as podman)

    • +
    • Maven (recommended, build automation tool)

    • +
    +

    Required dependencies:

    +
      +
    • All required project dependencies to build extraction plugins are published on the public Maven Central, under org.hansken.plugin.extraction:plugin-super-pom. +For maven based extraction plugins, the following pom.xml snippet can be used as basis of a plugin:

      +
      <?xml version="1.0" encoding="UTF-8"?>
      +<project xmlns="http://maven.apache.org/POM/4.0.0"
      +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      +    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      +    <modelVersion>4.0.0</modelVersion>
      +
      +    <parent>
      +        <groupId>org.hansken.plugin.extraction</groupId>
      +        <artifactId>plugin-super-pom</artifactId>
      +        <version>SET_THE_SDK_VERSION_HERE</version>
      +    </parent>
      +
      +    <artifactId>CHOOSE_YOUR_ARTIFACTID_HERE</artifactId>
      +    <version>SET_THE_PLUGIN_VERSION_HERE</version>
      +
      +    <licenses>
      +        <license>
      +            <name>The Apache Software License, Version 2.0</name>
      +            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
      +            <distribution>repo</distribution>
      +        </license>
      +    </licenses>
      +
      +    <properties>
      +        <mainClass>SET_THE_PLUGIN_MAIN_CLASS_HERE</mainClass>
      +    </properties>
      +</project>
      +
      +
      +
    • +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/snippets.html b/0.9.16/dev/java/snippets.html new file mode 100644 index 0000000..d5fa7ae --- /dev/null +++ b/0.9.16/dev/java/snippets.html @@ -0,0 +1,390 @@ + + + + + + + + + Java code snippets — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Java code snippets

    +

    This page contains Java code snippets for common patterns that will be used when writing a plugin.

    +
    +

    RandomAccessData as InputStream

    +

    In Java, InputStream is a common type to pass data to another class or method. The SDK provides a simple utility to +use a RandomAccessData as InputStream.

    +

    Add the following import to your code:

    +
    import org.hansken.plugin.extraction.core.data.RandomAccessDatas;
    +
    +
    +

    Next we can create an InputStream from the RandomAccessData as shown in the following snippet. Note that the +InputStream is created using a try-with-resources-statement. This ensures that the InputStream is correctly closed +when the InputStream is no longer required.

    +
    RandomAccessData traceData=...;
    +    try(InputStream asInputStream=RandomAccessDatas.asInputStream(traceData)){
    +    // use the InputStream here
    +    }
    +
    +
    +

    Notes:

    +
      +
    • the created InputStream is not thread-safe,

    • +
    • the created InputStream changes state in the provided RandomAccessData +(e.g. when data is read, the position updated in both the InputStream and +the RandomAccessData instances),

    • +
    • for more details on the implementation of the InputStream, refer to the RandomAccessDataInputStream JavaDoc.

    • +
    +
    +
    +

    Adding tracelets

    +

    In the following Java example, a “classification” tracelet is added to a trace. The tracelet consists +of a list of four properties, namely “class”, “confidence”, “modelName” and “modelVersion”.

    +
    trace.addTracelet("prediction", tracelet -> tracelet
    +     .set("type", "classification")
    +     .set("class", "telephone")
    +     .set("label", "label")
    +     .set("confidence", 0.8f)
    +     .set("embedding", Vector.of(1,2,3))
    +     .set("modelName", "yolo")
    +     .set("modelVersion", "2.0"));
    +
    +
    +

    or

    +
    trace.addTracelet(new Tracelet("prediction", List.of(
    +    new TraceletProperty("prediction.type","classification"),
    +    new TraceletProperty("prediction.class","telephone"),
    +    new TraceletProperty("prediction.label","label"),
    +    new TraceletProperty("prediction.confidence",0.8f))),
    +    new TraceletProperty("prediction.embedding", Vector.of(1,2,3)),
    +    new TraceletProperty("prediction.modelName","yolo"),
    +    new TraceletProperty("prediction.modelVersion","2.0"));
    +
    +
    +
    +
    +

    Adding data to a trace

    +

    Traces can have data attached to them. See Data streams for more information. +The following two snippets demonstrate how to add data to a trace.

    +

    It is currently not possible to verify that a specific data stream is already set or not.

    +
    +

    Data Transformations

    +

    The most efficient way to add data to a trace is using data transformations. +See Data Transformations for more details.

    +

    The following example sets a new data stream with dataType html on a trace, by setting a ranged data transformation:

    +
    trace.setData("html", RangedDataTransformation.builder().addRange(offset, length).build());
    +
    +
    +

    The following example creates a child trace and sets a new datastream with dataType raw on it, by setting a ranged +data transformation with two ranges:

    +
    trace.newChild(format("lineNumber %d", lineNumber), child -> {
    +    child.setData("raw", RangedDataTransformation.builder()
    +                  .addRange(10, 20)
    +                  .addRange(50, 30)
    +                  .build());
    +});
    +
    +
    +
    +
    +

    Blobs

    +

    It is not always possible to create a transormation for the data that has to be +added to a trace. For example the data is a result of a computation, and not +a direct subset of another data stream..

    +

    The following examples show how to creates a new data stream of dataType raw on a trace.

    +

    In case all data is stored in a byte[], we can add the byte array to the data stream with:

    +
    final byte[] rawBytes = {.....};
    +trace.setData("raw", writer -> writer.write(rawBytes));
    +
    +
    +

    Alternatively, if the data is available in an InputStream the data can be added with:

    +
    final InputStream inputStream = ...;
    +trace.setData("raw", inputStream);
    +
    +
    +
    +
    +
    +

    Specifying system resources

    +

    In the PluginInfo you can specify maximum system resource metrics for a plugin. These are used for scaling the +number of pods as described here. To run a plugin with 0.5 cpu (= +0.5 vCPU/Core/hyperthread), 1 gb memory and 10 (concurrent) cpu workers (threads), for example, the following configuration can be added to PluginInfo:

    +
    PluginInfo.builderFor(this)
    +    ...
    +    .pluginResources(PluginResources.builder()
    +        .maximumCpu(0.5f)
    +        .maximumMemory(1000)
    +        .maximumWorkers(10)
    +        .build())
    +    .build();
    +
    +
    +
    +
    +

    Deferred Extraction Plugins

    +

    Using a deferred plugin requires inheriting the DeferredExtractionPlugin base class. This allows access to +a TraceSearcher object in the process function to search for traces.

    +
    public class ExampleDeferred extends DeferredExtractionPlugin {
    +    @Override
    +    public PluginInfo pluginInfo();
    +
    +    @Override
    +    public void process(final Trace trace, final ExtractionContext context, final TraceSearcher searcher) {
    +        final SearchResult result = searcher.search("file.extension=asc", 10);
    +    }
    +}
    +
    +
    +

    The search method accepts three arguments;

    +
      +
    1. a HQL query (note: this is the traditional HQL query, and not the matchers HQL-lite variant),

    2. +
    3. the maximum number of traces the return (currently hard-limited to a maximum of 50 traces),

    4. +
    5. (optional) a scope, which can be either TraceSearcher.SearchScope.IMAGE (default), or TraceSearcher.SearchScope.PROJECT. +When set to IMAGE, the searcher will only search for traces within the same image as the trace that is being processed.

    6. +
    +

    The traces contained in the SearchResult are returned as a stream.

    +
    final Stream<Trace> stream = result.getTraces();
    +stream.limit(5);
    +
    +
    +
    +
    +

    Bulk Mode

    +

    The PluginInfo contains a parameter bulkMode. This can be used for lightweight plugins which have to process a lot +of data (either a lot of traces with data or a small number of traces with large data streams). For streaming +extractions, these plugins will run inside the worker pod, and will therefore be able to process data more efficiently.

    +

    WARNING: The plugin should be lightweight. This means that it should not use a lot of resources like CPU or memory, +because this will limit the resources of the worker pod, and therefore Hansken will not be able to start enough workers +to do extractions.

    +

    Creating a plugin with bulk mode enabled can be done by setting the parameter in PluginInfo as follows:

    +
    PluginInfo.builderFor(this)
    +    ...
    +    .bulkMode()
    +    .build();
    +
    +
    +
    +
    +

    Logging

    +

    The logging is provided by Log4j 2 with a SLF4J binding. The Log4j 2 SLF4J binding allows applications coded to the +SLF4J API to use Log4j 2 as the implementation.

    +
    +

    Usage

    +

    Here is an example illustrating how to log something with SLF4J. It begins by getting a logger with the name “LOG”. This +logger is in turn used to log the message I'm logging a variable 1234!.

    +
    import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +
    +public class Example {
    +    private static final Logger LOG = LoggerFactory.getLogger(Example.class);
    +
    +    public void example() {
    +        final int aNumber = 1234;
    +        // logs to console: I'm logging a variable 1234!
    +        LOG.info("I'm logging a variable {}!", aNumber);
    +    }
    +}
    +
    +
    +
    +
    +

    Customize logging

    +

    It’s easy to change the logging format with a file called log4j2.xml. If desired, this file must be in the resources +folder, for example src/main/resources/log4j2.xml

    +
    <?xml version="1.0" encoding="UTF-8"?>
    +<configuration>
    +    <appenders>
    +        <console name="stdout" target="SYSTEM_OUT">
    +            <patternLayout
    +                    pattern="%-5p|%d{yyyy-MM-dd HH:mm:ss}|%-20.20t|%-32.32c{1}|%m%n"/>
    +        </console>
    +    </appenders>
    +    <loggers>
    +        <root level="info">
    +            <appenderRef ref="stdout"/>
    +        </root>
    +    </loggers>
    +</configuration>
    +
    +
    +
    +

    Warning

    +

    Be careful with logging sensitive information.

    +
    +
    +

    Note

    +

    More information about customizing the logging can be found here.

    +
    +
    +

    Note

    +

    The default logger is pre-configured to log INFO to STDOUT (see the configuration above)

    +
    +
    +

    Note

    +

    Log4j 2 supports various logging formats, including xml, yaml, json, properties, etc. +Currently, only the xml format is supported.

    +
    +
    +

    Note

    +

    Contact your Hansken administrator for more information on where to find logs for your Hansken environment.

    +
    +
    +
    +
    +

    [EXPERIMENTAL FEATURE] Adding previews to a trace

    +
    +

    Warning

    +

    This is an experimental feature, which might change or get removed in future releases.

    +
    +

    Example:

    +
    public class ExamplePlugin extends ExtractionPlugin {
    +  @Override
    +  public PluginInfo pluginInfo();
    +
    +  @Override
    +  public void process(final Trace trace, final DataContext context) {
    +    final byte[] previewData;
    +    // set the preview data for the image/png MIME-type
    +    trace.set("preview.image/png", previewData);
    +    trace.set("preview.image/png", previewData);
    +  }
    +}
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/java/testing.html b/0.9.16/dev/java/testing.html new file mode 100644 index 0000000..9b14e69 --- /dev/null +++ b/0.9.16/dev/java/testing.html @@ -0,0 +1,287 @@ + + + + + + + + + Using the Test Framework in Java — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Using the Test Framework in Java

    +

    This section assumes you use the same setup as is used in the +Extraction Plugin Examples.

    +
    +

    Prerequisites

    +

    Java Plugins can use the plugin-super-pom as maven parent, which makes sure the +FLITS Test Framework is included in the build.

    +
    <parent>
    +    <groupId>org.hansken.plugin.extraction</groupId>
    +    <artifactId>plugin-super-pom</artifactId>
    +    <version>0.4.3</version>
    +</parent>
    +
    +
    +
    +
    +

    Embedded Testing versus Remote Testing

    +

    There are ways of integration testing a plugin with the Test Framework:

    +
      +
    • Embedded testing: Here the plugin is run directly from a JUnit test without using the gRPC layer.

    • +
    • Remote testing: Here the test will start an ExtractionPluginServer that will serve the plugin. All communication +is between server and plugin is done using gRPC.

    • +
    +

    See below for an example of each way of testing. +The Extraction Plugin Examples contains many +more examples.

    +
    +

    Embedded Testing example

    +

    Embedded tests can be run as a unit test.

    +
    import static nl.minvenj.nfi.flits.util.FlitsUtil.srcPath;
    +
    +import java.nio.file.Path;
    +
    +import org.hansken.plugin.extraction.api.ExtractionPlugin;
    +import org.hansken.plugin.extraction.test.EmbeddedExtractionPluginFlits;
    +
    +/**
    + * An integration test for MyPlugin.
    + */
    +class MyPluginIT extends EmbeddedExtractionPluginFlits {
    +
    +    @Override
    +    protected ExtractionPlugin pluginToTest() {
    +        // MyPlugin is a class implementing the ExtractionPlugin interface,
    +        // with pluginInfo() and process() methods.
    +        return new MyPlugin();
    +    }
    +
    +    @Override
    +    public Path testPath() {
    +        // Provide the folder containing input files. For examples, see
    +        // https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples.
    +        return srcPath("integration/inputs");
    +    }
    +
    +    @Override
    +    public Path resultPath() {
    +        // Provide the folder containing result files. For examples, see
    +        // https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples.
    +        return srcPath("integration/results");
    +    }
    +
    +    @Override
    +    public boolean regenerate() {
    +        // Returning false means the test will fail if the result files don't
    +        // match the outcome of the=++ test. Returning true means the test create
    +        // new result files .
    +        return false;
    +    }
    +}
    +
    +
    +
    +
    +

    Remote Testing example

    +

    Note that the following example serves the plugin by using ExtractionServer.

    +
    import static nl.minvenj.nfi.flits.util.FlitsUtil.srcPath;
    +
    +import java.nio.file.Path;
    +
    +import org.hansken.plugin.extraction.runtime.grpc.client.ExtractionPluginClient;
    +import org.hansken.plugin.extraction.runtime.grpc.server.ExtractionPluginServer;
    +import org.hansken.plugin.extraction.test.plugins.DataTransformationsPlugin;
    +import org.junit.jupiter.api.AfterAll;
    +import org.junit.jupiter.api.BeforeAll;
    +
    +public class RemoteTransformationPluginFlitsIT extends RemoteExtractionPluginFlits {
    +
    +    private static ExtractionPluginServer _server;
    +    private static ExtractionPluginClient _client;
    +
    +    @BeforeAll
    +    public static void init() throws Exception {
    +        final int port = 8999;
    +
    +        // Serve MyPlugin.
    +        // MyPlugin is a class implementing the ExtractionPlugin interface, with PluginInfo and Process methods.
    +        _server = ExtractionPluginServer.serve(port, MyPlugin::new);
    +
    +        // Create an ExtractionPluginClient
    +        _client = new ExtractionPluginClient("localhost", _server.getListeningPort());
    +    }
    +
    +    @AfterAll
    +    public static void destruct() {
    +        // At the end of the test, make sure the server and client are closed.
    +        if (_server != null) {
    +            _server.close();
    +        }
    +        if (_client != null) {
    +            _client.close();
    +        }
    +    }
    +
    +    @Override
    +    public Path testPath() {
    +        // Provide the folder containing input files. For examples, see https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples.
    +        return srcPath("integration/inputs");
    +    }
    +
    +    @Override
    +    public Path resultPath() {
    +        // Provide the folder containing result files. For examples, see https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples.
    +        return srcPath("integration/results");
    +    }
    +
    +    @Override
    +    protected ExtractionPluginClient pluginToTest() {
    +        // For Remote testing, the test won't talk directly to the plugin, but to the client.
    +        // The client will use gRPC to communicate with the served plugin.
    +        return _client;
    +    }
    +
    +    @Override
    +    public boolean regenerate() {
    +        // Returning false means the test will fail if the result files don't match the outcome of the test.
    +        // Returning true means the test create new result files.
    +        return false;
    +    }
    +}
    +
    +
    +
    +

    Note

    +

    Note that with a RemoteTransformationPluginFlitsIT it is possible to start a docker image of a plugin and +run remote tests against it using your own testdata. To do this, simply remove all _server code and manually start +your plugin in a docker container. Then run the test against the docker container by setting the correct url and +port, presumably new ExtractionPluginClient("localhost", 8999).

    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python.html b/0.9.16/dev/python.html new file mode 100644 index 0000000..b90df5d --- /dev/null +++ b/0.9.16/dev/python.html @@ -0,0 +1,158 @@ + + + + + + + + + Python — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.data_context.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.data_context.html new file mode 100644 index 0000000..db82b07 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.data_context.html @@ -0,0 +1,176 @@ + + + + + + + + + hansken_extraction_plugin.api.data_context — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.data_context

    +

    This module contains the definition of the DataContext.

    +

    Classes

    + + + + + + +

    DataContext(data_type, data_size)

    This class contains the data context of a plugin that is processing a trace.

    +
    +
    +class DataContext(data_type: str, data_size: int)[source]
    +

    Bases: object

    +

    This class contains the data context of a plugin that is processing a trace.

    +
    +
    +data_type: str
    +

    the named data type that is being processed

    +
    + +
    +
    +data_size: int
    +

    the size / total length of the data stream that is being processed

    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.html new file mode 100644 index 0000000..7185a58 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.extraction_plugin.html @@ -0,0 +1,279 @@ + + + + + + + + + hansken_extraction_plugin.api.extraction_plugin — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.extraction_plugin

    +

    This module contains the different types of Extraction Plugins.

    +

    The types of Extraction Plugins differ in their process functions.

    +

    Classes

    + + + + + + + + + + + + + + + + + + +

    BaseExtractionPlugin()

    All Extraction Plugins are derived from this class.

    DeferredExtractionPlugin()

    Extraction Plugin that can be run at a different extraction stage.

    DeferredMetaExtractionPlugin()

    Extraction Plugin that can be postponed to a later extraction iteration.

    ExtractionPlugin()

    Default extraction plugin, that processes a trace and one of its datastreams.

    MetaExtractionPlugin()

    Extraction Plugin that processes a trace only with its metadata, without processing its data.

    +
    +
    +class BaseExtractionPlugin[source]
    +

    Bases: ABC

    +

    All Extraction Plugins are derived from this class.

    +
    +
    +abstract plugin_info() PluginInfo[source]
    +

    Return information about this extraction plugin.

    +
    + +
    +
    +property transformers: List[Transformer]
    +

    Dynamically retrieves the transformer methods that were decorated with @transform.

    +

    Note: This method will retrieve transformers for superclasses as well.

    +
    + +
    + +
    +
    +class ExtractionPlugin[source]
    +

    Bases: BaseExtractionPlugin

    +

    Default extraction plugin, that processes a trace and one of its datastreams.

    +
    +
    +abstract process(trace: ExtractionTrace, data_context: DataContext)[source]
    +

    Process a given trace.

    +

    This method is called for every trace that is processed by this tool.

    +
    +
    Parameters:
    +
      +
    • trace – Trace that is being processed

    • +
    • data_context – Data data_context describing the data stream that is being processed

    • +
    +
    +
    +
    + +
    + +
    +
    +class MetaExtractionPlugin[source]
    +

    Bases: BaseExtractionPlugin

    +

    Extraction Plugin that processes a trace only with its metadata, without processing its data.

    +
    +
    +abstract process(trace: MetaExtractionTrace)[source]
    +

    Process a given trace.

    +

    This method is called for every trace that is processed by this tool.

    +
    +
    Parameters:
    +

    trace – Trace that is being processed

    +
    +
    +
    + +
    + +
    +
    +class DeferredExtractionPlugin[source]
    +

    Bases: BaseExtractionPlugin

    +

    Extraction Plugin that can be run at a different extraction stage.

    +

    This type of plugin also allows accessing other traces using the searcher.

    +
    +
    +abstract process(trace: ExtractionTrace, data_context: DataContext, searcher: TraceSearcher)[source]
    +

    Process a given trace.

    +

    This method is called for every trace that is processed by this tool.

    +
    +
    Parameters:
    +
      +
    • trace – Trace that is being processed

    • +
    • data_context – Data data_context describing the data stream that is being processed

    • +
    • searcher – TraceSearcher that can be used to obtain more traces

    • +
    +
    +
    +
    + +
    + +
    +
    +class DeferredMetaExtractionPlugin[source]
    +

    Bases: BaseExtractionPlugin

    +

    Extraction Plugin that can be postponed to a later extraction iteration.

    +

    This type of plugin processes a trace only with its metadata, +without processing its data and accesses traces using the searcher.

    +
    +
    +abstract process(trace: MetaExtractionTrace, searcher: TraceSearcher)[source]
    +

    Process a given trace.

    +

    This method is called for every trace that is processed by this tool.

    +
    +
    Parameters:
    +
      +
    • trace – Trace that is being processed

    • +
    • searcher – TraceSearcher that can be used to obtain more traces

    • +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.extraction_trace.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.extraction_trace.html new file mode 100644 index 0000000..a9f9d49 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.extraction_trace.html @@ -0,0 +1,468 @@ + + + + + + + + + hansken_extraction_plugin.api.extraction_trace — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.extraction_trace

    +

    This module contains the different Trace apis.

    +
    +
    Note that there are a couple of different traces:
      +
    • The ExtractionTrace and MetaExtractionTrace, which are offered to the process function.

    • +
    • ExtractionTraceBuilder, which is a trace that can be built; it does not exist in hansken yet, but it is added after +building.

    • +
    • SearchTrace, which represents an immutable trace which is returned after searching for traces.

    • +
    +
    +
    +

    Classes

    + + + + + + + + + + + + + + + + + + +

    ExtractionTrace()

    Trace offered to be processed.

    ExtractionTraceBuilder()

    ExtractionTrace that can be build.

    MetaExtractionTrace()

    MetaExtractionTraces contain only metadata.

    SearchTrace()

    SearchTraces represent traces returned when searching for traces.

    Trace()

    All trace classes should be able to return values.

    +
    +
    +class ExtractionTraceBuilder[source]
    +

    Bases: ABC

    +

    ExtractionTrace that can be build.

    +

    Represents child traces.

    +
    +
    +abstract update(key_or_updates: Mapping | str | None = None, value: Any | None = None, data: Mapping[str, bytes] | None = None) ExtractionTraceBuilder[source]
    +

    Update or add metadata properties for this .ExtractionTraceBuilder.

    +

    Can be used to update the name of the Trace represented by this builder, +if not already set.

    +
    +
    Parameters:
    +
      +
    • key_or_updates – either a str (the metadata property to be +updated) or a mapping supplying both keys and values to be updated

    • +
    • value – the value to update metadata property key to (used +only when key_or_updates is a str, an exception will be thrown +if key_or_updates is a mapping)

    • +
    • data – a dict mapping data type / stream name to bytes to be +added to the trace

    • +
    +
    +
    Returns:
    +

    this .ExtractionTraceBuilder

    +
    +
    +
    + +
    +
    +abstract add_tracelet(tracelet: Tracelet | str, value: Mapping[str, Any] | None = None) ExtractionTraceBuilder[source]
    +

    Add a .Tracelet to this .ExtractionTraceBuilder.

    +
    +
    Parameters:
    +
      +
    • tracelet – the Tracelet or tracelet type (supplied as a str) to add

    • +
    • value – the tracelet properties to add (only applicable when tracelet is a str)

    • +
    +
    +
    Returns:
    +

    this .ExtractionTraceBuilder

    +
    +
    +
    + +
    +
    +abstract add_transformation(data_type: str, transformation: Transformation) ExtractionTraceBuilder[source]
    +

    Update or add transformations for this .ExtractionTraceBuilder.

    +
    +
    Parameters:
    +
      +
    • data_type – data type of the Transformation

    • +
    • transformation – the Transformation to add

    • +
    +
    +
    Returns:
    +

    this .ExtractionTraceBuilder

    +
    +
    +
    + +
    +
    +abstract child_builder(name: str | None = None) ExtractionTraceBuilder[source]
    +

    Create a new .TraceBuilder to build a child trace to the trace to be represented by this builder.

    +
    +

    Note

    +

    Traces should be created and built in depth first order, +parent before child (pre-order).

    +
    +
    +
    Returns:
    +

    a .TraceBuilder set up to save a new trace as the child +trace of this builder

    +
    +
    +
    + +
    +
    +add_data(stream: str, data: bytes) ExtractionTraceBuilder[source]
    +

    Add data to this trace as a named stream.

    +
    +
    Parameters:
    +
      +
    • stream – name of the data stream to be added

    • +
    • data – data to be attached

    • +
    +
    +
    Returns:
    +

    this .ExtractionTraceBuilder

    +
    +
    +
    + +
    +
    +abstract open(data_type: str | None = None, offset: int = 0, size: int | None = None, mode: Literal['rb', 'wb', 'w', 'wt'] = 'rb', encoding='utf-8', buffer_size: int | None = None) BufferedReader | BufferedWriter | TextIOBase[source]
    +

    Open a data stream to read or write data from or to the .ExtractionTrace.

    +
    +
    Parameters:
    +
      +
    • data_type – the data type of the datastream, ‘raw’ by default

    • +
    • offset – byte offset to start the stream on when reading

    • +
    • size – the number of bytes to make available when reading

    • +
    • mode – ‘rb’ for reading, ‘wb’ for writing

    • +
    • encoding – encoding for writing text, used to convert str values to bytes, only valid for modes ‘w’ and ‘wt’

    • +
    • buffer_size – buffer size for reading (cache read back/ahead) or writing (cache for flush) data

    • +
    +
    +
    Returns:
    +

    a file-like object to read or write bytes from the named stream

    +
    +
    +
    + +
    +
    +abstract build() str[source]
    +

    Save the trace being built by this builder to remote.

    +
    +

    Note

    +

    Building more than once will result in an error being raised.

    +
    +
    +
    Returns:
    +

    the new trace’ id

    +
    +
    +
    + +
    + +
    +
    +class Trace[source]
    +

    Bases: ABC

    +

    All trace classes should be able to return values.

    +
    +
    +abstract get(key: str, default: Any | None = None) Any[source]
    +

    Return metadata properties for this .ExtractionTrace.

    +
    +
    Parameters:
    +
      +
    • key – the metadata property to be retrieved

    • +
    • default – value returned if property is not set

    • +
    +
    +
    Returns:
    +

    the value of the requested metadata property

    +
    +
    +
    + +
    + +
    +
    +class SearchTrace[source]
    +

    Bases: Trace

    +

    SearchTraces represent traces returned when searching for traces.

    +
    +
    +abstract open(stream: str = 'raw', offset: int = 0, size: int | None = None, buffer_size: int | None = None) BufferedReader[source]
    +

    Open a data stream of the data that is being processed.

    +
    +
    Parameters:
    +
      +
    • stream – data stream of trace to open. defaults to raw. other examples are html, text, etc.

    • +
    • offset – byte offset to start the stream on

    • +
    • size – the number of bytes to make available

    • +
    • buffer_size – buffer size for reading data

    • +
    +
    +
    Returns:
    +

    a file-like object to read bytes from the named stream

    +
    +
    +
    + +
    + +
    +
    +class MetaExtractionTrace[source]
    +

    Bases: Trace

    +

    MetaExtractionTraces contain only metadata.

    +

    This class represents traces during the extraction of an extraction plugin without a data stream.

    +
    +
    +abstract update(key_or_updates: Mapping | str | None = None, value: Any | None = None, data: Mapping[str, bytes] | None = None) None[source]
    +

    Update or add metadata properties for this .ExtractionTrace.

    +
    +
    Parameters:
    +
      +
    • key_or_updates – either a str (the metadata property to be +updated) or a mapping supplying both keys and values to be updated

    • +
    • value – the value to update metadata property key to (used +only when key_or_updates is a str, an exception will be thrown +if key_or_updates is a mapping)

    • +
    • data – a dict mapping data type / stream name to bytes to be +added to the trace

    • +
    +
    +
    +
    + +
    +
    +abstract add_tracelet(tracelet: Tracelet | str, value: Mapping[str, Any] | None = None) None[source]
    +

    Add a .Tracelet to this .MetaExtractionTrace.

    +
    +
    Parameters:
    +
      +
    • tracelet – the Tracelet or tracelet type to add

    • +
    • value – the tracelet properties to add (only applicable when tracelet is a tracelet type)

    • +
    +
    +
    +
    + +
    +
    +abstract add_transformation(data_type: str, transformation: Transformation) None[source]
    +

    Update or add transformations for this .ExtractionTraceBuilder.

    +
    +
    Parameters:
    +
      +
    • data_type – data type of the Transformation

    • +
    • transformation – the Transformation to add

    • +
    +
    +
    +
    + +
    +
    +abstract child_builder(name: str | None = None) ExtractionTraceBuilder[source]
    +

    Create a .TraceBuilder to build a trace to be saved as a child of this .Trace.

    +

    A new trace will only be added to the index once explicitly saved (e.g. +through .TraceBuilder.build).

    +
    +

    Note

    +

    Traces should be created and built in depth first order, +parent before child (pre-order).

    +
    +
    +
    Parameters:
    +

    name – the name for the trace being built

    +
    +
    Returns:
    +

    a .TraceBuilder set up to create a child trace of this .MetaExtractionTrace

    +
    +
    +
    + +
    + +
    +
    +class ExtractionTrace[source]
    +

    Bases: MetaExtractionTrace

    +

    Trace offered to be processed.

    +
    +
    +abstract open(data_type: str | None = None, offset: int = 0, size: int | None = None, mode: Literal['rb', 'wb', 'w', 'wt'] = 'rb', encoding='utf-8', buffer_size: int | None = None) BufferedReader | BufferedWriter | TextIOBase[source]
    +

    Open a data stream to read or write data from or to the .ExtractionTrace.

    +
    +
    Parameters:
    +
      +
    • data_type – the data type of the datastream, ‘raw’ by default

    • +
    • offset – byte offset to start the stream on when reading

    • +
    • size – the number of bytes to make available when reading

    • +
    • mode – ‘rb’ for reading, ‘wb’ for writing

    • +
    • encoding – encoding for writing text, used to convert str values to bytes, only valid for modes ‘w’ and ‘wt’

    • +
    • buffer_size – buffer size for reading (cache read back/ahead) or writing (cache for flush) data

    • +
    +
    +
    Returns:
    +

    a file-like object to read or write bytes from the named stream

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.html new file mode 100644 index 0000000..b43268e --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.html @@ -0,0 +1,184 @@ + + + + + + + + + hansken_extraction_plugin.api — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api

    +

    This package contains the apis of the different classes used by extraction plugins.

    +

    Implementations can be found in the runtime module.

    +

    Modules

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    hansken_extraction_plugin.api.data_context

    This module contains the definition of the DataContext.

    hansken_extraction_plugin.api.extraction_plugin

    This module contains the different types of Extraction Plugins.

    hansken_extraction_plugin.api.extraction_trace

    This module contains the different Trace apis.

    hansken_extraction_plugin.api.plugin_info

    This module contains all definitions to describe metadata of a plugin, a.k.a.

    hansken_extraction_plugin.api.search_result

    This module contains a representation of a search result.

    hansken_extraction_plugin.api.search_sort_option

    This module defines the sort options for a search within Hansken.

    hansken_extraction_plugin.api.trace_searcher

    This module contains the definition of a trace searcher.

    hansken_extraction_plugin.api.tracelet

    This module contains the definition of a Tracelet.

    hansken_extraction_plugin.api.transformation

    This module contains the definition of a Transformation.

    hansken_extraction_plugin.api.transformer

    This module contains the Transformer class that holds the function reference of the transformer.

    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.plugin_info.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.plugin_info.html new file mode 100644 index 0000000..be9beb0 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.plugin_info.html @@ -0,0 +1,377 @@ + + + + + + + + + hansken_extraction_plugin.api.plugin_info — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.plugin_info

    +

    This module contains all definitions to describe metadata of a plugin, a.k.a. PluginInfo.

    +

    Classes

    + + + + + + + + + + + + + + + + + + + + + +

    Author(name, email, organisation)

    The author of an Extraction Plugin.

    MaturityLevel(value)

    This class represents the maturity level of an extraction plugin.

    PluginId(domain, category, name)

    Identifier of a plugin, consisting of domain, category and name.

    PluginInfo(id, version, description, author, ...)

    This information is used by Hansken to identify and run the plugin.

    PluginResources([maximum_cpu, ...])

    PluginResources contains information about how many resources will be used for a plugin.

    TransformerLabel(method_name, parameters, ...)

    TransformerLabel contains information about a transformer method that a plugin provides.

    +
    +
    +class Author(name: str, email: str, organisation: str)[source]
    +

    Bases: object

    +

    The author of an Extraction Plugin.

    +

    This information can be retrieved by an end-user from Hansken.

    +
    +
    +name: str
    +
    + +
    +
    +email: str
    +
    + +
    +
    +organisation: str
    +
    + +
    + +
    +
    +class MaturityLevel(value)[source]
    +

    Bases: Enum

    +

    This class represents the maturity level of an extraction plugin.

    +
    +
    +PROOF_OF_CONCEPT = 0
    +
    + +
    +
    +READY_FOR_TEST = 1
    +
    + +
    +
    +PRODUCTION_READY = 2
    +
    + +
    + +
    +
    +class PluginId(domain: str, category: str, name: str)[source]
    +

    Bases: object

    +

    Identifier of a plugin, consisting of domain, category and name. Needs to be unique among all tools/plugins.

    +
    +
    +domain: str
    +
    + +
    +
    +category: str
    +
    + +
    +
    +name: str
    +
    + +
    + +
    +
    +class PluginResources(maximum_cpu: float | None = None, maximum_memory: int | None = None, maximum_workers: int | None = None)[source]
    +

    Bases: object

    +

    PluginResources contains information about how many resources will be used for a plugin.

    +
    +
    +maximum_cpu: float | None = None
    +

    CPU resources are measured in cpu units. One cpu is equivalent to 1 vCPU/Core for cloud providers and 1 hyperthread +on bare-metal Intel processors. Also, fractional requests are allowed. A plugin that asks 0.5 CPU uses half as +much CPU as one that asks for 1 CPU.

    +
    + +
    +
    +maximum_memory: int | None = None
    +

    Max usable memory for a plugin, measured in megabytes.

    +
    + +
    +
    +maximum_workers: int | None = None
    +

    The number of concurrent workers(i.e. traces that can be processed).

    +
    + +
    + +
    +
    +class TransformerLabel(method_name: str, parameters: Dict[str, str], return_type: str)[source]
    +

    Bases: object

    +

    TransformerLabel contains information about a transformer method that a plugin provides.

    +

    It is mainly used for storing the properties (name, arguments, return type) of a transformer in PluginInfo objects. +Unlike the Transformer class it does not contain the actual function reference to the transformer itself.

    +
    +
    +method_name: str
    +

    The parameters of the function where the key is the parameter name and the value is the type of the parameter.

    +
    + +
    +
    +parameters: Dict[str, str]
    +

    The return type of the parameter. See api.Transformer class for supported types.

    +
    + +
    +
    +return_type: str
    +
    + +
    + +
    +
    +class PluginInfo(id: ~hansken_extraction_plugin.api.plugin_info.PluginId, version: str, description: str, author: ~hansken_extraction_plugin.api.plugin_info.Author, maturity: ~hansken_extraction_plugin.api.plugin_info.MaturityLevel, matcher: str, webpage_url: str, license: str | None = None, deferred_iterations: int = 1, resources: ~hansken_extraction_plugin.api.plugin_info.PluginResources | None = None, bulk_mode: bool | None = None, transformers: ~typing.List[~hansken_extraction_plugin.api.plugin_info.TransformerLabel] = <factory>)[source]
    +

    Bases: object

    +

    This information is used by Hansken to identify and run the plugin.

    +

    Note that the build_plugin.py build script is used to build a plugin docker image with PluginInfo docker labels.

    +
    +
    +id: PluginId
    +

    a plugin’s unique identifier, see PluginId

    +
    + +
    +
    +version: str
    +

    version of the plugin

    +
    + +
    +
    +description: str
    +

    short description of the functionality of the plugin

    +
    + +
    +
    +author: Author
    +

    the plugin’s author, see Author

    +
    + +
    +
    +maturity: MaturityLevel
    +

    maturity level, see MaturityLevel

    +
    + +
    +
    +matcher: str
    +

    this matcher selects the traces offered to the plugin

    +
    + +
    +
    +webpage_url: str
    +

    plugin url

    +
    + +
    +
    +license: str | None = None
    +

    license of this plugin

    +
    + +
    +
    +deferred_iterations: int = 1
    +

    number of deferred iterations (1 to 20), nly for deferred plugins (optional)

    +
    + +
    +
    +resources: PluginResources | None = None
    +

    resources to be reserved for a plugin (optional)

    +
    + +
    +
    +bulk_mode: bool | None = None
    +

    Populated dynamically in pack.plugin_info by collecting all @transformer methods. Do not assign manually.

    +
    + +
    +
    +transformers: List[TransformerLabel]
    +
    + +
    +
    +static from_dict(data: dict)[source]
    +

    Create a PluginInfo object from a dictionary.

    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.search_result.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.search_result.html new file mode 100644 index 0000000..f4d74e1 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.search_result.html @@ -0,0 +1,225 @@ + + + + + + + + + hansken_extraction_plugin.api.search_result — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.search_result

    +

    This module contains a representation of a search result.

    +

    Classes

    + + + + + + +

    SearchResult()

    Class representing a stream of traces, returned when performing a search request.

    +
    +
    +class SearchResult[source]
    +

    Bases: ABC, Iterable

    +

    Class representing a stream of traces, returned when performing a search request.

    +

    This result can only be iterated once. Results can be retrieved in three ways:

    +

    Treating the result as an iterable:

    +
    for trace in result:
    +    print(trace.name)
    +
    +
    +

    Calling .take to process one or more batches of traces:

    +
    first_100 = result.take(100)
    +process_batch(first_100)
    +
    +
    +

    Calling .takeone to get a single trace:

    +
    first = result.takeone()
    +second = result.takeone()
    +
    +print(first.name, second.name)
    +
    +
    +
    +
    +abstract total_results() int[source]
    +

    Return the total number of hits.

    +
    +
    Returns:
    +

    Total number of hits

    +
    +
    +
    + +
    +
    +takeone() SearchTrace | None[source]
    +

    Return a single trace, if this stream is not exhausted.

    +
    +
    Returns:
    +

    A searchtrace, or None if no trace is available

    +
    +
    +
    + +
    +
    +take(num: int) List[SearchTrace][source]
    +

    Return a list containing at most num number of traces, or less if they are not available.

    +
    +
    Parameters:
    +

    num – Number of traces to take

    +
    +
    Returns:
    +

    List containing zero or more traces

    +
    +
    +
    + +
    +
    +close()[source]
    +

    Close this SearchResult if no more traces are to be retrieved.

    +

    Required to keep compatibility with hansken.py.

    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.search_sort_option.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.search_sort_option.html new file mode 100644 index 0000000..5f8e091 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.search_sort_option.html @@ -0,0 +1,214 @@ + + + + + + + + + hansken_extraction_plugin.api.search_sort_option — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.search_sort_option

    +

    This module defines the sort options for a search within Hansken.

    +

    Classes

    + + + + + + + + + +

    Direction(value)

    Enumeration for sorting directions.

    SearchSortOption([field, direction])

    Represents a search sort option consisting of a field and a direction.

    +
    +
    +class Direction(value)[source]
    +

    Bases: Enum

    +

    Enumeration for sorting directions.

    +
    +
    Attributes:

    ASCENDING: Sort in ascending order. +DESCENDING: Sort in descending order.

    +
    +
    +
    +
    +ASCENDING = 'ASCENDING'
    +
    + +
    +
    +DESCENDING = 'DESCENDING'
    +
    + +
    + +
    +
    +class SearchSortOption(field: str = 'uid', direction: Direction = Direction.ASCENDING)[source]
    +

    Bases: object

    +

    Represents a search sort option consisting of a field and a direction.

    +
    +
    Attributes:

    _field (str): The field to sort by. +_direction (Direction): The direction to sort in (ascending or descending).

    +
    +
    +
    +
    +field()[source]
    +

    Get the field to sort on.

    +
    +
    Returns:

    str: Returns the current field.

    +
    +
    +
    + +
    +
    +direction()[source]
    +

    Get the sorting direction.

    +
    +
    Returns:

    Direction: Returns the current direction.

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.trace_searcher.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.trace_searcher.html new file mode 100644 index 0000000..de904df --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.trace_searcher.html @@ -0,0 +1,206 @@ + + + + + + + + + hansken_extraction_plugin.api.trace_searcher — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.trace_searcher

    +

    This module contains the definition of a trace searcher.

    +

    Classes

    + + + + + + + + + +

    SearchScope(value)

    Scope to describe the search context for TraceSearcher.search calls.

    TraceSearcher()

    This class can be used to search for traces, using the search method.

    +
    +
    +class SearchScope(value)[source]
    +

    Bases: str, Enum

    +

    Scope to describe the search context for TraceSearcher.search calls.

    +
    +
    +image = 'image'
    +
    + +
    +
    +project = 'project'
    +
    + +
    + +
    +
    +class TraceSearcher[source]
    +

    Bases: object

    +

    This class can be used to search for traces, using the search method.

    +
    +
    +abstract search(query: str, count: int | None = None, scope: str | ~hansken_extraction_plugin.api.trace_searcher.SearchScope = SearchScope.image, start: int = 0, sort: list[~hansken_extraction_plugin.api.search_sort_option.SearchSortOption] = [<hansken_extraction_plugin.api.search_sort_option.SearchSortOption object>]) SearchResult[source]
    +

    Search for indexed traces in Hansken using provided query returning at most count results.

    +
    +
    Parameters:
    +
      +
    • query – HQL-query used for searching

    • +
    • start – Starting index of traces to return

    • +
    • count – Maximum number of traces to return

    • +
    • scope – Select search scope: ‘image’ to search only search for other traces within the image of the trace +that is being processed, or ‘project’ to search in the scope of the full project (either Scope- +enum value can be used, or the str-values directly).

    • +
    • sort – The fields and directions to sort on

    • +
    +
    +
    Returns:
    +

    SearchResult containing found traces

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.tracelet.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.tracelet.html new file mode 100644 index 0000000..7f1625f --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.tracelet.html @@ -0,0 +1,172 @@ + + + + + + + + + hansken_extraction_plugin.api.tracelet — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.tracelet

    +

    This module contains the definition of a Tracelet.

    +

    Classes

    + + + + + + +

    Tracelet(name, value)

    A tracelet contains the values of a single fvt (Few Valued Type).

    +
    +
    +class Tracelet(name: str, value: Mapping[str, Any])[source]
    +

    Bases: object

    +

    A tracelet contains the values of a single fvt (Few Valued Type).

    +

    A few valued type is a trace property type that is a collection of tracelets. A trace can contain multiple few +valued types containing one or more tracelets. For example, the trace.identity` type may look like this:

    +
    {emailAddress: 'interesting@notreally.com'},
    +{firstName: 'piet'},
    +{emailAddress: 'anotheremail@notreally.com'},
    +
    +
    +

    The trace.identity few valued types contains three different tracelets.

    +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.transformation.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.transformation.html new file mode 100644 index 0000000..1c65e43 --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.transformation.html @@ -0,0 +1,229 @@ + + + + + + + + + hansken_extraction_plugin.api.transformation — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.transformation

    +

    This module contains the definition of a Transformation.

    +

    Classes

    + + + + + + + + + + + + +

    Range(offset, length)

    A Range describes a range of bytes with a offset and length.

    RangedTransformation(ranges)

    A :class:RangedTransformation describes a data transformation consisting of a list of :class:Range.

    Transformation()

    A super class for data transformations.

    +
    +
    +class Transformation[source]
    +

    Bases: ABC

    +

    A super class for data transformations. Currently only :class:RangedTransformation is supported.

    +
    + +
    +
    +class Range(offset: int, length: int)[source]
    +

    Bases: object

    +

    A Range describes a range of bytes with a offset and length.

    +
    +
    +offset: int
    +

    the starting point of the data

    +
    + +
    +
    +length: int
    +

    the size of the data

    +
    + +
    + +
    +
    +class RangedTransformation(ranges: List[Range])[source]
    +

    Bases: Transformation

    +

    A :class:RangedTransformation describes a data transformation consisting of a list of :class:Range.

    +
    +
    +static builder()[source]
    +

    :return a Builder.

    +
    + +
    +
    +class Builder[source]
    +

    Bases: object

    +

    Helper class that implements a transformation builder.

    +
    +
    +add_range(offset: int, length: int) Builder[source]
    +

    Add a range to a ranged transformation by providing the range’s offset and length.

    +

    :param offset the offset of the data transformation +:param length the length of the data transformation +:return: this .RangedTransformation.Builder

    +
    + +
    +
    +build() RangedTransformation[source]
    +

    Return a RangedTransformation.

    +
    +
    Returns:
    +

    a :class:RangedTransformation

    +
    +
    +
    + +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api/hansken_extraction_plugin.api.transformer.html b/0.9.16/dev/python/api/hansken_extraction_plugin.api.transformer.html new file mode 100644 index 0000000..3ccff8d --- /dev/null +++ b/0.9.16/dev/python/api/hansken_extraction_plugin.api.transformer.html @@ -0,0 +1,180 @@ + + + + + + + + + hansken_extraction_plugin.api.transformer — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    hansken_extraction_plugin.api.transformer

    +

    This module contains the Transformer class that holds the function reference of the transformer.

    +

    Instances of this class are constructed by BaseExtractionPlugin when retrieving transformers dynamically. +It also validates whether the method to which @transformer is applied adheres to the requirements of a transformer.

    +

    Classes

    + + + + + + +

    Transformer(function)

    A transformer is an exposed method of a plugin that can be executed remotely outside extraction-time.

    +
    +
    +class Transformer(function)[source]
    +

    Bases: object

    +

    A transformer is an exposed method of a plugin that can be executed remotely outside extraction-time.

    +

    This allows for on-demand analysis during an investigation.

    +
    +
    +supported_primitives = {<class 'bool'>: 'boolean', <class 'bytes'>: 'binary', <class 'datetime.datetime'>: 'date', <class 'float'>: 'real', <class 'hansken.util.GeographicLocation'>: 'latLong', <class 'hansken.util.Vector'>: 'vector', <class 'int'>: 'integer', <class 'str'>: 'string', typing.Mapping: 'map', typing.Sequence: 'list'}
    +
    + +
    +
    +generate_label() TransformerLabel[source]
    +

    Generate a TransformerLabel given the transformer method. TransformerLabels are used in PluginInfo objects.

    +

    Unlike Transformers TransformerLabels can be serialized and sent to a client that wishes to call a transformer. +The specific Python types are converted to the generic types that are used in the Hansken trace model.

    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/api_changelog.html b/0.9.16/dev/python/api_changelog.html new file mode 100644 index 0000000..1357221 --- /dev/null +++ b/0.9.16/dev/python/api_changelog.html @@ -0,0 +1,678 @@ + + + + + + + + + Python API Changelog — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Python API Changelog

    +

    This document summarizes all important API changes in the Extraction Plugin API. This document only shows changes that +are important to plugin developers. For a full list of changes per version, please refer to the general +changelog.

    +
    +

    0.9.13

    +
      +
    • This release introduces a new parameter bulk_mode to the PluginInfo. This can be used for +lightweight plugins which have to process a lot of data (either a lot of traces or a small +number of traces with large data streams). These plugins will run inside the worker pod for streaming extractions, +and will therefore be able to process data more efficiently.

    • +
    +
    +
    +

    0.9.10

    +
      +
    • This release introduces new parameters for the trace_searcher, start and sort. +This allows the searcher can get a certain range of traces in a specific order. +Note: Hansken will support these types of plugins from v47.34.0.

    • +
    • This release allows the user to search for more than 50 traces using the GrpcTraceSearcher. By specifying a count +greater than 50, results will be retrieved in batches of 50 (or less) until the desired count is achieved. +Setting the count to None (or omitting it) allows the GrpcTraceSearcher to retrieve all available traces. +This functionality is implemented in a buffered manner and is defined within BatchedSearchResult, +which replaces the now-removed GrpcTraceResult. Note: the search results are still limited by Elasticsearch +so no more than 100.000 results can be obtained.

    • +
    +
    +
    +

    0.9.9

    +
      +
    • This release introduces the deferred meta extraction plugin. This plugin type can defer their execution and +processes a trace only with its metadata, without processing its data and accesses traces using the searcher. +This makes it possible to use deferred plugins in combination with traces without data. +Note: Hansken will support these types of plugins from v47.34.0.

    • +
    +
    +
    +

    0.9.5

    +
      +
    • The internal (de)serialization of some types has changed. Please update the extraction plugin sdk to match the one used in Hansken.

    • +
    +
    +
    +

    0.9.4

    +
      +
    • This release supports providing all types of transformer arguments when using the execute_transformer script.

    • +
    +
    +
    +

    0.9.2

    +
      +
    • This release introduces a simple flow-control mechanism that fixes connection RST errors that can occur when a +plugin produces traces too fast. Plugins built with this version are not backwards compatible.

    • +
    • Python plugins now support transformers, remote methods which can be executed using the Hansken REST API. More information can be found in the docs.

    • +
    • The build_plugin and label_plugin utilities prematurely shut down containers if the building and labeling process takes too long causing the process for slow containers to fail. If your plugin takes a long time to start, you may want to increase the timeout before the script stops trying to connect and aborts the process of building the plugin. This can be done using the new optional --timeout argument. The default is set to 30 seconds.

    • +
    • The optional image name argument of build_plugin is changed to a flag. Build scripts can be updated using --target-name DOCKER_IMAGE_NAME.

    • +
    +
    +
    +

    0.8.3

    +
      +
    • This release addresses important load balancing issues. Please use release 0.8.3 as a drop-in-replacement for releases 0.8.2 and 0.8.1.

    • +
    +
    +
    +

    0.8.2

    +
      +
    • ⚠️ This release is deprecated, please upgrade to 0.8.3

    • +
    • The build_plugin utility has been updated and the deprecation status has been removed. +As with label_plugin, build_plugin now no longer requires a full (virtual) environment +with all plugin dependencies and resources. This will greatly reduce build times for plugins with +big dependencies and/or large models.

      +

      The first argument of the command (a pointer to your plugin.py file) has been removed. +Please do not forget to remove the first argument of build_plugin in your tox.ini or other build tooling.

      +

      For usage read further in packaging.

      +
    • +
    • The default read-buffer of trace.open('rb') as been changed from 1 Megabyte to 6 Megabyte to reduce overhead while data reading.

    • +
    • The data stream writer of trace.open('wb') is now buffered as well. This means that multiple small writes will be flushed after every 6 Megabytes of data has been written (or when the writer is closed).

    • +
    • The read-buffer or write-buffer size can be overridden by the user, by passing the buffer_size= argument to trace.open():

      +
      with trace.open('rb', buffer_size=1024*1024):  # set a 1 Megabyte buffer size
      +    pass
      +
      +with trace.open('wb', buffer_size=1024*1024*12):  # set a 12 Megabyte buffer size
      +    pass
      +
      +with trace.open('wb', buffer_size=1):  # a buffer_size of 1 effectively disables the buffer:
      +    pass                               # each write will be flushed to Hansken directly
      +
      +
      +
    • +
    • It is now possible to write str values to trace.open(..). To do so, pass mode='w' as additional argument. +By default, it is assumed that the written text is ‘utf-8’ encoded. The default can be overwritten by using the 'encoding=' argument.

      +

      In a future Hansken update, Hansken will set the correct data-stream properties for your text stream (mimeType, mimeClass, and fileType).

      +

      Example use cases are:

      +
        +
      • write picture-to-text (OCR) data to a trace

      • +
      • write translations to a trace

      • +
      • write audio-to-text (audio transcriptions) to a trace

      • +
      • write the results of a JSON dump, e.g.: json.dump(['your', 'data'], text_writer)

      • +
      +

      Examples in code:

      +
      with trace.open(data_type='raw', mode='w', encoding='utf-8') as text_writer:
      +    text_writer.write('hello.world')  # write strings directly to it
      +    json.dump({'hello': 'world'}, text_writer)  # or pass the writer to json.dump
      +
      +
      +

      See also the python code snippet.

      +
    • +
    +
    +
    +

    0.8.1

    +
      +
    • ⚠️ This release is deprecated, please upgrade to 0.8.3

    • +
    +
    +
    +

    0.8.0

    +
      +
    • The trace property imageId is renamed to image. This is to be in line with the Hansken REST API and Python API. +When updating your plugin, please update your calls trace.get('imageId') to trace.get('image').

    • +
    • #774 +By default, deferred extraction plugin searches are now scoped to the image +of the trace that is currently being processed. Optionally, a project-wide +search can be done by passing an optional scope argument.

      +
      def process(trace, data_context, searcher):
      +    # only search for traces inside the same image as the trace that is being processed
      +    searcher.search('*')
      +    searcher.search('*', scope='image')  # explicit alternative, using a str
      +    searcher.search('*', scope=SearchScope.image)  # explicit alternative, using the SearchScope enum
      +
      +    # only search for traces inside the same image as the trace that is being processed
      +    searcher.search('*', scope='project')
      +    searcher.search('*', scope=SearchScope.project)
      +
      +
      +
    • +
    • Support trace properties of type list[float]. This enables you to write +multiple offsets and confidence scores in tracelets of type prediction.

      +

      For example:

      +
      trace.add_tracelet('prediction', {
      +    'modelName': 'my_cat_detector',
      +    'modelVersion': '0.0.BETA',
      +    'type': 'classification',
      +    'label': 'cat',
      +
      +    # the best score
      +    'offset': 3.0,
      +    'confidence': 0.4,
      +
      +    # all scores
      +    'offsets':     [0.0, 3.0, 6.0, 9.0],
      +    'confidences': [0.1, 0.4, 0.03, 0.09],
      +})
      +
      +
      +
    • +
    +
    +
    +

    0.7.3

    +
      +
    • This version introduces a new docker image build utility label_plugin. +This utility will eventually replace build_plugin. build_plugin is now deprecated.

      +

      label_plugin is a utility to add labels to an extraction plugin image. Labeling a plugin is required for +Hansken to detect extraction plugins in a plugin image registry.

      +

      To label a plugin, first build the plugin image with docker build; +for example by using one of the following commands:

      +
      docker build . -t my_plugin
      +docker build . -t my_plugin --build-arg https_proxy=http://your_proxy:8080
      +
      +
      +

      Next, run the label_plugin utility to label the build plugin container:

      +
      label_plugin my_plugin
      +
      +
      +

      The result of label_plugin is a plugin image that can be uploaded to Hansken.

      +

      label_plugin is preferred over build_plugin, as it does not require a full (virtual) environment +with all plugin dependencies and resources. This is especially preferred when the plugin uses (big) +data models or (external) dependencies.

      +

      For usage read further in packaging.

      +
    • +
    +
    +
    +

    0.7.0

    +
      +
    • Escaping the / character in matchers is optional. +This simplifies and aims for better HQL and HQL-Lite compatability. +See for more information and examples the HQL-Lite syntax documentation.

      +

      Examples:

      +
        +
      • Old: file.path:\/Users\/*\/AppData -> new: file.path:/Users/*/AppData

      • +
      • Old: file.path:\\/Users\\/*\\/AppData -> new: file.path:/Users/*/AppData

      • +
      • Old: registryEntry.key:\/Software\/Dropbox\/ks*\/Client-p -> new: registryEntry.key:/Software/Dropbox/ks*/Client-p

      • +
      +
    • +
    • Hansken returns file.path properties (outside the scope of matchers) as a String property, +instead of a list of strings. +Example: trace.get('file.path') now returns '/dev/null', this was ['dev', 'null'].

    • +
    • Improved plugin loading when using serve_plugin and build_plugin: +import statements now work for modules (python files) that are located the same directory structure of a plugin.

    • +
    • A plugin can now stream data to a trace using trace.open(mode='wb'). +This removes the limit on the size of data that could be written. +See also the python code snippet.

      +

      Example:

      +
      with trace.open(mode='wb') as writer:
      +    writer.write(b'a string')
      +    writer.write(bytes(another_string, 'utf-8'))
      +
      +
      +

      note: this does not work when using run_with_hanskenpy.

      +
    • +
    +
    +
    +

    0.6.1

    +
      +
    • The docker image build script build_plugin has been updated to allow for extension of the docker command. +This can be especially handy for specifying a proxy. You should build your plugin container image with the following +command:

      +
      build_plugin PLUGIN_FILE DOCKER_FILE_DIRECTORY [DOCKER_IMAGE_NAME] [DOCKER_ARGS]
      +
      +
      +
      +

      Warning

      +

      Note that the DOCKER_IMAGE_NAME argument no longer requires a -n parameter to be specified.

      +
      +

      For usage read further in packaging.

      +
    • +
    +
    +
    +

    0.6.0

    +
    +

    Warning

    +

    This is an API breaking change. +Upgrading your plugin to this version will require code changes. +Plugins built with previous versions of the SDK from 0.3.0 will still work with Hansken.

    +
    +
    +

    Warning

    +

    It is strongly recommended to upgrade your plugins to this new version because it significantly improves +the start-up time of Hansken. See the migration steps below.

    +
    +

    This release contains both build pipeline changes and API changes. +Please read all changes carefully.

    +
    +

    Build pipeline change

    +
      +
    • Extraction plugin container images are now labeled with PluginInfo. This +allows Hansken to efficiently load extraction plugins. +Migration steps from earlier versions:

      +
        +
      1. Update the SDK version in your setup.py / requirements.txt

      2. +
      3. If you come from a version prior to 0.4.0, or if you use a plugin name +instead of a plugin id in your pluginInfo(), switch to the plugin id style +(read instructions for version 0.4.0)

      4. +
      5. Update your build scripts to build your plugin (Docker) container image. +Be sure to have the Extraction Plugins SDK installed. +Then, you should build your plugin container image with the following command:

        +
        build_plugin PLUGIN_FILE DOCKER_FILE_DIRECTORY -n [DOCKER_IMAGE_NAME]
        +
        +
        +

        For example:

        +
        build_plugin plugin/chatplugin.py . -n extraction-plugins/chatplugin
        +
        +
        +

        This will generate a plugin image:

        +
          +
        • The extraction plugin is added to your local image registry (docker images),

        • +
        • Note that DOCKER_IMAGE_NAME is optional and will default to extraction-plugin/PLUGINID, e.g. +extraction-plugin/nfi.nl/extract/chat/whatsapp,

        • +
        • The image is tagged with two tags: latest, and your plugin version.

        • +
        +
      6. +
      +
    • +
    +
    +
    +

    API changes

    +
      +
    • The field plugin has been removed from PluginInfo.

    • +
    • The field pluginId should now be the first argument of PluginInfo (when using unnamed arguments).

      +

      Old (unnamed arguments):

      +
      def plugin_info(self):
      +    return PluginInfo(self, '1.0.0', 'description', author,
      +                      MaturityLevel.PROOF_OF_CONCEPT, '*, 'https://hansken.org',
      +                      PluginId(...), 'Apache License 2.0')
      +
      +
      +

      New (removed self, and moved PluginId(...) to first argument position):

      +
      def plugin_info(self):
      +    return PluginInfo(PluginId(...), '1.0.0', 'description',
      +                      author, MaturityLevel.PROOF_OF_CONCEPT,
      +                      '*', 'https://hansken.org', 'Apache License 2.0')
      +
      +
      +

      Old (named arguments):

      +
      def plugin_info(self):
      +    return PluginInfo(plugin=self,
      +                      version='1.0.0',
      +                      ...)
      +
      +
      +

      New (removed plugin=self):

      +
      def plugin_info(self):
      +    return PluginInfo(version='1.0.0',
      +                      ...)
      +
      +
      +
    • +
    • Plugin data_context.data_size is now a variable instead of a method:

      +

      Old:

      +
      def process(self, trace: ExtractionTrace, data_context: DataContext):
      +    size = data_context.data_size()
      +
      +
      +

      New:

      +
      def process(self, trace: ExtractionTrace, data_context: DataContext):
      +    size = data_context.data_size
      +
      +
      +
    • +
    • Simplify declaring required runtime resources in a plugin’s info.

      +

      Extraction plugin resources don’t use the builder pattern anymore.

      +

      Old:

      +
      return PluginInfo(
      +    ...,
      +    resources=PluginResources.builder().maximum_cpu(0.5).maximum_memory(1000).build())
      +)
      +
      +
      +

      New:

      +
      # no need for a builder, declare resources by direct instantiation
      +return PluginInfo(
      +    ...,
      +    resources=PluginResources(maximum_cpu=2.0, maximum_memory=2048)
      +)
      +# or, as before, specify just on resource
      +return PluginInfo(
      +    ...,
      +    resources=PluginResources(maximum_memory=4096)
      +)
      +
      +
      +
    • +
    +
    +
    +
    +

    0.5.1

    +
      +
    • Simplify tracelet properties by making the tracelet type prefix optional.

      +
      # using a Tracelet object
      +trace.add_tracelet(Tracelet("prediction", {
      +    "type": "example",
      +    "confidence": 0.8
      +}))
      +# or without a Tracelet object
      +trace.add_tracelet("identity", {"name": "John Doe", "status": "online"})
      +
      +
      +
    • +
    • Enabled manual plugin testing, as described on advanced use of the test framework in Python.

    • +
    +
    +
    +

    0.5.0

    +
      +
    • Support vector data type in trace properties.

      +
      embedding = Vector.from_sequence((width, height))
      +tracelet = Tracelet("prediction", {
      +    "prediction.type": "example-vector",
      +    "prediction.embedding": embedding
      +})
      +trace.add_tracelet(tracelet)
      +
      +
      +
    • +
    +
    +
    +

    0.4.13

    +
      +
    • When writing input search traces for tests, it is no longer required to explicitly set an id property. +These are automatically generated when executing tests.

    • +
    +
    +
    +

    0.4.7

    +
      +
    • More $data matchers are supported in Hansken.py plugin runner. Before this improvement it was only possible to match +on $data.type. Now it is also possible to match for example on $data.mimeType and $data.mimeClass. The $data +matcher should still be at the end of the query as before.

    • +
    +
    +
    +

    0.4.6

    +
      +
    • It is now possible to specify maximum system resources in the PluginInfo. To run a plugin with 0.5 cpu (= 0.5 +vCPU/Core/hyperthread) and 1 gb memory, for example, the following configuration can be added to PluginInfo:

      +
      plugin_info = PluginInfo(...,
      +                         resources=PluginResources.builder().maximum_cpu(0.5).maximum_memory(1000).build())
      +
      +
      +
    • +
    +
    +
    +

    0.4.0

    +
      +
    • Extraction Plugins are now identified with a PluginInfo.PluginId containing a domain, category and name. The +method PluginInfo.name(pluginName) has been replaced by PluginInfo.id(new PluginId(domain, category, name). More +details on the plugin naming conventions can be found at the Plugin naming convention section.

    • +
    • PluginInfo.name() is now deprecated (but will still work for backwards compatibility).

    • +
    • A new license field PluginInfo.license has also been added in this release.

    • +
    • The following example creates a PluginInfo for a plugin with the name TestPlugin, licensed under +the Apache License 2.0 license:

      +
      class TestPlugin(ExtractionPlugin):
      +    def plugin_info(self) -> PluginInfo:
      +        return PluginInfo(self,
      +                          version='1.0.0',
      +                          description='A plugin for testing.',
      +                          author=Author('The Externals', 'tester@holmes.nl', 'NFI'),
      +                          maturity=MaturityLevel.PROOF_OF_CONCEPT,
      +                          webpage_url='https://hansken.org',
      +                          matcher='file.extension=txt',
      +                          id=PluginId(domain='nfi.nl', category='test', name='TestPlugin'),
      +                          license='Apache License 2.0'
      +                          )
      +
      +
      +
    • +
    +
    +
    +

    0.3.0

    +
      +
    • Extraction Plugins can now create new datastreams on a Trace through data transformations. Data transformations +describe how data can be obtained from a source.

      +

      An example case is an extraction plugin that processes an archive file. The plugin creates a child trace per entry in +the archive file. Each child trace will have a datastream that is a transformation that marks the start and length of +the entry in the original archive data. By just describing the data instead of specifying the actual data, a lot of +space is saved.

      +

      Although Hansken supports various transformations, the Extraction Plugins SDK for now only supports ranged data +transformations. Ranged data transformations define data as a list of ranges, each range with an offset and length in +a bytearray.

      +

      The following example sets a new datastream with dataType html on a trace, by setting a ranged data transformation:

      +
      trace.add_transformation('html', RangedTransformation(Range(offset, length)))
      +
      +
      +

      The following example creates a child trace and sets a new datastream with dataType raw on it, by setting a ranged +data transformation with two ranges:

      +
      child = trace.child_builder('new trace')
      +child.add_transformation('raw', RangedTransformation.builder()
      +                                                    .add_range(10, 20)
      +                                                    .add_range(50, 30)
      +                                                    .build())
      +});
      +
      +
      +

      More detailed documentation will follow in an upcoming SDK release.

      +
    • +
    +
    +
    +

    0.2.0

    +
    +

    Warning

    +

    This is an API breaking change. +Plugins created with an earlier version of the extraction plugin +SDK are not compatible with Hansken that uses 0.2.0 or later.

    +
    +
      +
    • Introduced a new extraction plugin type api.extraction_plugin.DeferredExtractioPlugin. +Deferred Extraction plugins can be run at a different extraction stage. +This type of plugin also allows accessing other traces using the searcher.

    • +
    • The class api.extraction_context.ExtractionContext has been renamed to api.data_context.DataContext. +The new name DataContext represents the class contents better. +Plugins have to update matching import statements accordingly. +Plugins should also update the named argument context to data_context of the plugin process() method. +This change has no functional changes.

      +

      Old:

      +
      from hansken_extraction_plugin.api.extraction_context import ExtractionContext
      +
      +def process(self, trace, context):
      +  pass
      +
      +
      +

      New:

      +
      from hansken_extraction_plugin.api.data_context import DataContext
      +
      +def process(self, trace, data_context):
      +  pass
      +
      +
      +
    • +
    • Moved api.author.Author to api.plugin_info.Author, and moved api.maturity_level.MaturityLevel +to api.plugin_info.MaturityLevel +This is a more pythonic way of grouping of classes into modules. This change has no functional side effects.

      +

      Plugins have to update matching import statements accordingly.

      +

      Old:

      +
      from hansken_extraction_plugin.api.author import Author
      +from hansken_extraction_plugin.api.maturity_level import MaturityLevel
      +from hansken_extraction_plugin.api.plugin_info import PluginInfo
      +
      +
      +

      New:

      +
      from hansken_extraction_plugin.api.plugin_info import Author, MaturityLevel, PluginInfo
      +
      +
      +
    • +
    • Removed DataContext.get_first_bytes() from the public API.

    • +
    • Removed api.extraction_trace.validate_update_arguments(..) from the public API. This method is still invoked +implicitly when setting trace properties.

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/debugging.html b/0.9.16/dev/python/debugging.html new file mode 100644 index 0000000..0bf4737 --- /dev/null +++ b/0.9.16/dev/python/debugging.html @@ -0,0 +1,303 @@ + + + + + + + + + How to debug an Extraction Plugin — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    How to debug an Extraction Plugin

    +

    Debugging is the art of removing bugs — hopefully quickly.

    +
    +

    Locally

    +

    To debug a plugin locally, it is recommended to start the plugin via the IDE. This has the advantage that breakpoints +can easily be put in the code instead of printing log statements, for example. To start a plugin locally, a piece of +code must be added, see Testing for more information.

    +
    +

    Logging

    +

    The logging of the extraction plugin is displayed in the console.

    +
    +
    +
    +

    Locally with Docker

    +

    Debugging an extraction plugin via docker is a bit trickier. In order to debug in Python, a debugger must be added to +the extraction plugin. There are several debug modules for Python available, but one debug module that works well with +Visual Studio Code is debugpy. This package is developed by Microsoft +specifically for use in Visual Studio Code with Python.

    +
    +

    Note

    +

    debugpy implements the Debug Adapter Protocol (DAP), which is a standardised way for development tools to +communicate with debuggers.

    +
    +

    Using debugpy with Docker containers requires 4 distinct steps:

    +
      +
    1. Install debugpy

    2. +
    3. Configuring debugpy in Python

    4. +
    5. Build a docker image

    6. +
    7. Configuring the connection to the Docker container

    8. +
    9. Setting breakpoints in your code

    10. +
    +
    +

    Install debugpy

    +

    First, add debugpy to your setup.py.

    +
    from setuptools import setup
    +
    +setup(
    +    # ...
    +    install_requires=[
    +        "hansken-extraction-plugin==0.4.7",  # the plugin SDK
    +        "debugpy==1.5.1"
    +    ]
    +)
    +
    +
    +
    +
    +

    Configuring debugpy in Python

    +

    At the beginning of your script, import debugpy, and call debugpy.listen() to start the debug adapter, passing +a (host, port) tuple as the first argument. Use the debugpy.wait_for_client() function to block program execution +until the client is attached.

    +
    import debugpy
    +
    +debugpy.listen(("0.0.0.0", 5678))
    +debugpy.wait_for_client()  # blocks execution until client is attached
    +
    +# your extraction plugin code
    +
    +
    +
    +
    +

    Build a Docker image

    +

    If the Docker image is not built, first build the image as described +here.

    +
    +
    +

    Configuring the connection to the Docker container

    +

    debugpy is now set up to accept connections inside a Docker container. To connect to debugpy in the docker +container, port 5678 must be published. To make a port available to services outside of Docker, use the –publish or -p +flag. This creates a firewall rule which maps a container port to a port on the Docker host to the outside world.

    +

    To run the extraction plugin with the published port the following command can be used:

    +
    docker run -p 5678:5678 your_extraction_plugin_name
    +
    +
    +

    The next step is to configure Visual Studio Code. A launch.json file must be created in order for Visual Studio Code +to connect to the extraction plugin in Docker. This minimal launch.json example below tells the debugger to attach +to localhost on port 5678.

    +
    {
    +  "version": "0.2.0",
    +  "configurations": [
    +    {
    +      "name": "Python: Remote Attach",
    +      "type": "python",
    +      "request": "attach",
    +      "connect": {
    +        "host": "localhost",
    +        "port": 5678
    +      },
    +      "pathMappings": [
    +        {
    +          "localRoot": "${workspaceFolder}",
    +          "remoteRoot": "."
    +        }
    +      ]
    +    }
    +  ]
    +}
    +
    +
    +
    +
    +

    Setting breakpoints in the code

    +

    The last step is to add breakpoints in the code.

    +
    +
    +

    Logging in Docker

    +

    The logging of the extraction plugin is displayed in the console after running the docker run command. In addition, +the logging is also displayed in the Visual Studio Code console while debugging.

    +
    +
    +
    +

    Kubernetes

    +

    In kubernetes it is currently not possible to debug via debugpy because no debug ports are published.

    +
    +

    Logging in Kubernetes

    +

    If there is authorization to the kubernetes cluster, the logging can be viewed with the following command:

    +
    kubectl logs -f hansken-extraction-plugins/your_extraction_plugin_pod
    +
    +
    +
    +
    +
    +

    Debug HQL

    +

    An HQL query can be debugged by running the test framework with the --verbose option enabled. The found HQL matches +will then be displayed in the console. To test a plugin in python with the --verbose option enabled use the following +command:

    +
    test_plugin --standalone plugin/your_plugin.py --regenerate --verbose
    +
    +
    +

    The following output will then be displayed in the console:

    +
    HQL match found for:
    +$data.type=jpg
    +With trace:
    +dataType=jpg
    +types={file, data}
    +properties={data.raw.mimeType=image/jpg, path=/test-input-trace, file.name=image.jpg, name=test-input-trace, id=0}
    +
    +
    +

    If the HQL query contains an error, it will be shown in the generated test results. An example of an invalid query +is $data.mimeType=image/jpg (slash not escaped). This query will produce an error like the one shown below.

    +
    {
    +  "class": "org.hansken.plugin.extraction.hql_lite.lang.ParseException",
    +  "message": "HqlLiteHumanQueryParser: line 1:20 token recognition error at: '/jpg'"
    +}
    +
    +
    +
    +

    Note

    +

    The error is only shown in the generated trace, so to find out the ParseException run the test_plugin +command with the --regenerate option enabled.

    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/getting_started.html b/0.9.16/dev/python/getting_started.html new file mode 100644 index 0000000..ed2d6a7 --- /dev/null +++ b/0.9.16/dev/python/getting_started.html @@ -0,0 +1,323 @@ + + + + + + + + + Getting started — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Getting started

    +

    Set up a development environment: step by step.

    +

    The following section describes how to set up a fully working development environment for extraction plugins with Python. +This is written for those who are not comfortable setting up a working build environment. +This is optional; advanced users may choose a different development environment setup, and can skip this section completely.

    +

    If you fail to set up a development environment, feel free to ask for help at our Discord channel.

    +
    +

    Install required software on Ubuntu

    +

    In order to be able to develop Hansken Extraction Plugins in Python on Ubuntu, the following build tools need be installed on your system: python, pip, tox, Java, Docker.

    +
      +
    • Python, pip, tox, Java +To install, run the following commands in your terminal:

      +
      sudo apt update
      +sudo apt install python3.10 python3-pip tox default-jdk
      +
      +
      +

      You can check whether all versions are installed correctly by running the following commands (and validate the output):

      +
      python --version
      +# should return version 3.10.15 or higher
      +
      +pip3 --version
      +# should return version 20.0.2 or higher
      +
      +tox --version
      +# should return version 3.11.2 or higher
      +
      +java -version
      +# should return version 11.0.4 or higher
      +
      +
      +
    • +
    +

    If the above software is installed, you can continue with “Install Docker”, +or if you don’t want to install Docker, continue with “Install your IDE: Pycharm”.

    +
    +
    +

    Install required software on Windows

    +

    In order to be able to develop Hansken Extraction Plugins in Python on Windows, follow the next steps:

    +
      +
    • For verification of the installation of each program we will use commands on the command prompt. +This can be opened by clicking the Windows Start button and typing:

      +
      cmd
      +
      +
      +

      Then hit Enter . This will open the command prompt where you can enter the commands given in the following steps.

      +
    • +
    • Python 3.10 or higher & pip +Download the installer from python.org/Downloads (click the yellow “Download Python” button) +and run it to install Python and pip. +Pip is the standard package manager for Python. +It allows you to install and manage additional packages that are not part of the Python standard library, like the Extraction Plugins SDK.

      +

      Be sure to select the option “Add python to PATH”.

      +

      When the installation is complete, verify the installation by checking the Python and pip versions:

      +
      python --version
      +# should return your downloaded Python version (>3.10.4)
      +
      +pip3 --version
      +# should return 20.2.3 or higher
      +
      +
      +
    • +
    • tox +Tox is used to automate and standardize testing in Python. Use Pip to install Tox with this command:

      +
      pip install tox
      +
      +
      +

      Verify that Tox is installed by running:

      +
      tox --version
      +# should return 3.23.0 or higher
      +
      +
      +
    • +
    • Java JDK 11.0.4 (or higher) +Java JDK 11.0.4 or higher is needed to run the test framework of the Extraction Plugins SDK. +This enables you to test without actually deploying the plugin in Hansken. +Installing Java on Windows can be done in many different way, but for now we can not recommend one method. +Please have a look at Install the Microsoft Build of OpenJDK for more details.

      +
      java -version
      +# should return 11.0.4 or higher
      +
      +
      +

      N.b. Make sure to set the environment variable in case the installed JDK is not detected by the system. +You can follow the below-mentioned steps to set the environment variable:

      +
        +
      1. Click the Windows start button

      2. +
      3. Type “advanced system settings”

      4. +
      5. Hit enter

      6. +
      7. Now click on Environment Variables, select Path under System Variables section and click on Edit. We need to add the path of installed JDK to system Path.

      8. +
      9. Click on New Button and add the path to installed JDK bin which is C:javajava-11jdk-11.0.4bin in our case.

      10. +
      11. Press OK Button 3 times to close all the windows. This sets the JDK 11 on system environment variables to access the same from the console.

      12. +
      +
    • +
    +

    If the above software is installed, you can continue with “Install Docker”, +or if you don’t want to install Docker, continue with “Install your IDE: Pycharm”.

    +
    +
    +

    Install Docker (Ubuntu, Windows)

    +

    Installing Docker is a bit more complicated. The Docker website describes the installation instructions in detail. +Please follow the instructions on docs.docker.gom/get-docker/ to install docker.

    +
      +
    • To check you have Docker installed correctly, run

      +
      docker --version
      +# should return version 20.10.17 or higher
      +
      +
      +
    • +
    +

    Note: if you run Docker inside a managed network, you might also need to configure proxies and/or certificates. +Please contact your system administrator if you need help with this.

    +
    +
    +

    Set up your IDE: PyCharm

    +

    We recommend that you use an IDE to aid you in your development of Extraction Plugins. PyCharm is a good choice.

    + +
    +
    +

    Download an extraction plugin template (empty plugin)

    +

    You can download an extraction plugin template. +This is an empty plugin, from which you can rapidly start your plugin development.

    +
      +
    • The template is hosted on GitHub here. +You can download a zip with the template from here. The below screenshot shows where the download button is located:

      + +
    • +
    +
    +
    +

    Import the Extraction Plugins Skeleton in PyCharm

    +
      +
    • First unzip the skeleton plugin downloaded from the previous step.

    • +
    • Next, start PyCharm.

    • +
    • When PyCharm starts, choose “Open” and select the folder where you placed the Extraction Plugin Skeleton.

      + +
    • +
    • The following popup will appear, click OK .

      + +
    • +
    • The Extraction Plugins Skeleton is now loaded in PyCharm, which should look as follows:

      + +
    • +
    • Be sure to give the README.md a read when you are done with the Prerequisites.

    • +
    +
    +
    +

    Verify full setup

    +

    To verify that your system has been setup correctly, you can run the test suite in the Extraction Plugin Skeleton:

    +
      +
    • First, press alt-F12 at the same time to open a terminal in PyCharm in the project root folder.

    • +
    • To run the tests of the Skeleton, run this command in the terminal from the root folder:

      +
      tox
      +
      +
      +

      The first time running tox may take a few minutes! Please be patient 😊

      +

      Tox will install all required plugin dependencies, and start your tests. +N.b. The plugin template demonstrates how to build a plugin with tox. +Some plugin developers choose a different tool than tox.

      +
    • +
    • If your system has been set up correctly, the output should end with a summary like this:

      +
      py38: commands succeeded
      +congratulations :)
      +
      +
      +

      This means the setup is finished. You now have everything installed to start coding your own plugin!

      +
    • +
    +
    +
    +

    Next steps

    +

    Now that you have a working environment, you can start doing cool stuff. +Please have a look at the following pages for more information:

    +
      +
    • Packaging: how to package your plugin and use it in Hansken

    • +
    • Run plugins with Hansken.py: run your plugin on a case without uploading the plugin to Hansken, useful for quick prototyping

    • +
    • Transformers for on-demand execution: how to write a transformer to execute code on-demand outside extraction time.

    • +
    • Testing: how to write tests for your plugin

    • +
    • Debugging: if your plugin isn’t working as expected, you can debug it

    • +
    • Snippets: code snippets to demonstrate common plugin usage patterns

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/hanskenpy.html b/0.9.16/dev/python/hanskenpy.html new file mode 100644 index 0000000..bfd8a3a --- /dev/null +++ b/0.9.16/dev/python/hanskenpy.html @@ -0,0 +1,223 @@ + + + + + + + + + Run plugins with Hansken.py — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Run plugins with Hansken.py

    +

    Hansken.py is a Python client to Hansken’s REST API, developed and maintained by the Netherlands Forensic Institute.

    +

    With Hansken.py, you can run your Python plugin on a project on your Hansken installation that has already been +extracted. This way of running your plugin is useful during your plugin development. It is not required to upload your +plugin to Hansken and start an extraction, making the development cycle faster. However, please note that this is only +useful during the development stage of your plugin, as the execution of your plugin will be much slower compared to +running the plugin during a Hansken extraction.

    +
    +

    Note

    +

    The execution of your plugin will be much slower in Hansken.py compared to running the plugin during a Hansken +extraction.

    +
    +
    +

    How to run python extraction plugins standalone with Hansken.py

    +

    Running python extraction plugins standalone with Hansken.py is easy. It is just one command. This section explains how +to setup this command for your specific environment.

    +
    +

    Create a runner file

    +

    Create a file run_with_hansken.py in the root folder of your plugin. This will aid you in running the plugin with +hansken.py.

    +
    from hansken_extraction_plugin.runtime.extraction_plugin_runner import run_with_hanskenpy
    +
    +from plugin.my_plugin import MyPlugin
    +
    +if __name__ == '__main__':
    +    run_with_hanskenpy(MyPlugin)
    +
    +
    +
    +
    +

    Preparing for the command

    +

    Before you can enter the command that runs your extraction plugin with Hansken.py, you need to find three values:

    +
      +
    • HANSKEN_PROJECT_ID project id on which you want to run your plugin

    • +
    • YOUR_GATEKEEPER_URL the URL to the Hansken gatekeeper

    • +
    • YOUR_KEYSTORE_URL the URL to your keystore

    • +
    +

    The correct values of these variables can be found in the Expert UI. Go to the search-page of your project in the +ExpertUI. Next to the search-bar hit the button “Save query”.

    +hanskenpy_save_query.png +

    A new dialog shows up. At the bottom of this dialog, you will find your gatekeeper and keystore urls as well as the +project id.

    +hanskenpy_gatekeeper_keystore.png +
    +
    +

    Running your plugin with Hansken.py

    +

    Next, open a terminal in the project root folder of your plugin and enter the following command. It will run your +extraction plugin with Hansken.py in Hansken. Replace the three variables with their respective values.

    +
    python3 ./run_with_hanskenpy.py -v -l - HANSKEN_PROJECT_ID --endpoint YOUR_GATEKEEPER_URL --keystore YOUR_KEYSTORE_URL
    +
    +
    +

    If your command runs well, you might be prompted for your username and password. There will be some output (note that +the output may vary depending on your system setup and project content):

    +
    [2021-03-16 12:59:45.344248+0000] INFO: hansken.auth: selected IDP ID (...) with SOAP endpoint (...)
    +[2021-03-16 12:59:45.344450+0000] WARNING: hansken.auth: IDP url known, user+pass auth required but no username supplied
    +username []: testaccount
    +[2021-03-16 12:59:48.423245+0000] INFO: hansken.auth: user acknowledged environment username or supplied custom username: testaccount
    +password for user testaccount:
    +[2021-03-16 12:59:53.799668+0000] INFO: hansken.auth: identity provider url and user+pass provided or known, using Keycloak SAML with Basic auth
    +[2021-03-16 12:59:53.805538+0000] INFO: hansken_extraction_plugin.runtime.extraction_plugin_runner: PluginRunner is running plugin class Plugin
    +[2021-03-16 12:59:53.859299+0000] INFO: hansken.auth: posting SAML request with authorization for user testaccount to IDP endpoint (...)
    +[2021-03-16 12:59:54.240290+0000] INFO: plugin.extraction_plugin: processing trace 54197e67-8135-40c3-93f1-3d73a5552693
    +[2021-03-16 12:59:54.240753+0000] INFO: plugin.extraction_plugin: processing trace OCRimage
    +[2021-03-16 12:59:54.240753+0000] INFO: plugin.extraction_plugin: processing trace (...)
    +
    +
    +

    Note that the arguments -v and -l - are passed to enable logging. To find out what other options can be passed to +this command, please have a look at the hansken.py documentation, or simply run the following command:

    +
    python3 ./run_with_hanskenpy.py --help
    +
    +
    +
    +
    +
    +

    Compatibility

    +

    At this moment, running Extraction Plugins with Hansken.py has a few limitations. These are:

    +
      +
    • When writing an Extraction Plugin for use with Hansken.py, the matcher must contain exactly one “$data.property = +value” expression.

    • +
    • Data transformations are currently not supported by Hansken.py.

    • +
    • Tracelets are not yet supported by the SDK in use with Hansken.py.

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/packaging.html b/0.9.16/dev/python/packaging.html new file mode 100644 index 0000000..89414fd --- /dev/null +++ b/0.9.16/dev/python/packaging.html @@ -0,0 +1,259 @@ + + + + + + + + + Packaging — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Packaging

    +

    Extraction plugins are packaged as OCI images (also known as Docker images). +The OCI images are labeled with the PluginInfo. +To automate packaging of a Python plugin and labeling the OCI image, +the Extraction Plugin SDK comes with three utility applications: label_plugin, build_plugin and build_plugin_ci.

    +

    To package a plugin, make sure that the Extraction Plugins SDK is installed, as well as Docker. +Next build and label your plugin as described in the following sections.

    +

    To verify that the image has been built, use the following command to view all local images:

    +
    docker images
    +
    +
    +

    Once your plugin is packaged and labelled, it can be published or ‘uploaded’ to Hansken. +See “Upload the plugin to Hansken” for instructions.

    +
    +

    label_plugin

    +

    label_plugin is a utility to add labels to an extraction plugin image. +To label a plugin, first build the plugin image with docker build; +for example by using one of the following commands:

    +
    docker build . -t my_plugin
    +docker build . -t my_plugin --build-arg https_proxy=http://your_proxy:8080
    +
    +
    +

    Next, run the label_plugin utility to label the build plugin container:

    +
    label_plugin my_plugin
    +
    +
    +

    This utility will briefly start your plugin using Docker, and requests the PluginInfo from the plugin. +The information from the PluginInfo will be added as labels to the plugin image. +The result of label_plugin is a plugin image that can be published to a docker/OCI image registry.

    +
    +
    +

    build_plugin

    +

    The build_plugin extends label_plugin by also taking care of the docker build command. +Use this as an one-liner to both build and label your plugin image.

    +

    To build your plugin container image you can use the following command:

    +
    build_plugin DOCKER_FILE_DIRECTORY [DOCKER_IMAGE_NAME] [DOCKER_ARGS]
    +
    +
    +

    For example:

    +
    build_plugin .
    +
    +
    +

    and to pass proxy configurations to Docker:

    +
    build_plugin . --build-arg http_proxy="$http_proxy" --build-arg https_proxy="$https_proxy"
    +
    +
    +

    This will generate a plugin image:

    +
      +
    • The extraction plugin is added to your local image registry (docker images),

    • +
    • Note that the variables $http_proxy and $https_proxy are put in quotes, this is needed in case they contain +spaces,

    • +
    • The image is tagged with two tags: latest, and your plugin version.

    • +
    +

    Arguments:

    +
      +
    • DOCKER_FILE_DIRECTORY: Path to the directory containing the Dockerfile of the plugin.

    • +
    • (Optional) DOCKER\_IMAGE\_NAME: Name of the docker image without tag. Note that docker image names cannot start with +a period or dash. If it starts with a dash, it will be interpreted as an additional docker argument (see +DOCKER_ARGS). If no name is given the name defaults to extraction-plugin/PLUGINID, e.g. +extraction-plugin/nfi.nl/extract/chat/whatsapp.

    • +
    • (Optional) DOCKER\_ARGS: Additional arguments for the docker command, which can be as many arguments as you like.

    • +
    +
    +
    +

    build_plugin_ci

    +

    The build_plugin_ci performs the same tasks as build_plugin except that it uses a different approach for labeling +the plugin. Not all CI/CD pipelines allow docker containers to be started and connected to, something which +build_plugin relies on to label the plugin correctly using the plugin info specified in the plugin. build_plugin_ci +uses another approach which exports the image and then parses the plugin info from this image. This way a container +does not have to be started. Therefore the advantage of build_plugin_ci is that it can more reliably build plugins on +CI systems. The downside of this approach is that it is slower than build_plugin utility. It is therefore adviced to +use build_plugin when developing locally to speed up the development process and to use build_plugin_ci when +building plugins in CI/CD pipelines.

    +
    +

    Requirements

    +

    To build your plugin container image using build_plugin_ci you have to add the following line to your Containerfile +after you have copied your plugin to the image. build_plugin_ci requires this to find the plugin information.

    +

    +
    RUN plugin_info "/app/plugin.py"
    +
    +
    +
    +
    +

    Command usage

    +

    build_plugin_ci can be invoked as follows:

    +
    build_plugin DOCKER_FILE_DIRECTORY [--target_name DOCKER_IMAGE_NAME] [--build_agent BUILD_AGENT] [BUILD_AGENT_ARGS]
    +
    +
    +

    Other than the options provided by build_plugin build_plugin_ci also provides a --build_agent flag which allows a +user to choose between different build agents to build and label their plugin. Currently only docker, podman and +buildah are supported. For example:

    +
    build_plugin . --target_name my-image:1.3.5 --build_agent "podman"
    +
    +
    +

    A proxy configurations can be configured as follows:

    +
    build_plugin . --build-arg http_proxy="$http_proxy" --build-arg https_proxy="$https_proxy"
    +
    +
    +

    This will generate a plugin image:

    +
      +
    • The extraction plugin is added to your local image registry (docker images),

    • +
    • Note that the variables $http_proxy and $https_proxy are put in quotes, this is needed in case they contain +spaces,

    • +
    • The image is tagged with two tags: latest, and your plugin version.

    • +
    +

    Arguments:

    +
      +
    • DOCKER_FILE_DIRECTORY: Path to the directory containing the Dockerfile of the plugin.

    • +
    • (Optional) DOCKER\_IMAGE\_NAME: Name of the docker image without tag. Note that docker image names cannot start with +a period or dash. If it starts with a dash, it will be interpreted as an additional docker argument (see +DOCKER_ARGS). If no name is given the name defaults to extraction-plugin/PLUGINID, e.g. +extraction-plugin/nfi.nl/extract/chat/whatsapp.

    • +
    • (Optional) BUILD\_AGENT: The build agent that should be used to build the plugin. Either docker, podman or buildah. +Docker is the default.

    • +
    • (Optional) BUILD\_AGENT\_ARGS: Additional arguments for the buildagent command, which can be as many arguments as +you like.

    • +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/prerequisites.html b/0.9.16/dev/python/prerequisites.html new file mode 100644 index 0000000..f6a56d1 --- /dev/null +++ b/0.9.16/dev/python/prerequisites.html @@ -0,0 +1,139 @@ + + + + + + + + + Prerequisites — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Prerequisites

    +

    All required project dependencies to build extraction plugins are published on the public PyPI.

    +

    Required:

    +
      +
    • Python 3.10 or higher

    • +
    • Java 11 (for running the test-framework, which is implemented in Java)

    • +
    • Docker (for packaging and deploying extraction plugins in containers, can be omitted if you have an external build pipeline that provides Docker)

    • +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/snippets.html b/0.9.16/dev/python/snippets.html new file mode 100644 index 0000000..1d9c89a --- /dev/null +++ b/0.9.16/dev/python/snippets.html @@ -0,0 +1,404 @@ + + + + + + + + + Python code snippets — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Python code snippets

    +
    +

    Adding properties to a trace

    +

    Use update +to add trace types and their properties to an +ExtractionTrace. +Example:

    +
    def process(self, trace, data_context):
    +    # get the name of the file
    +    file_name = trace.get('file.name')
    +    # set the chat application property on the trace
    +    trace.update('chatConversation.application', f'DemoApp {file_name}')
    +
    +
    +

    All types and properties that can be set are defined in the Hansken trace model.

    +
    +

    Date properties

    +

    When adding a property which holds a value of data-type Date, always define timezone as being UTC. Example:

    +
    def process(self, trace, data_context):
    +    trace.update('file.modifiedOn',
    +                 datetime.fromtimestamp(1630510809, tz=timezone.utc))
    +
    +
    +
    +
    +

    Category for extra properties

    +

    If the information, which must be added as a property, does not match any of the existing properties of Hansken trace +model, use the category “misc” (miscellaneous). When part of the category “misc”, any name can be given to a property. +The values of miscellaneous properties are expected to be of data-type string. Example:

    +
    def process(self, trace, data_context):
    +    trace.update({
    +        'file.misc.notes': 'Some additional notes about the file trace.',
    +        'file.misc.anyName': 'Even more notes.'
    +    })
    +
    +
    +
    +
    +

    Adding tracelets

    +

    In the following Python example, a “prediction” tracelet is added to a trace. The tracelet consists +of a list of four properties, namely “class”, “confidence”, “modelName” and “modelVersion”.

    +
    trace.add_tracelet(Tracelet('prediction', {'class': 'telephone',
    +                                           'confidence': 0.8,
    +                                           'modelName': 'yolo',
    +                                           'modelVersion': '2.0'}))
    +
    +
    +
    +
    +
    +

    Adding child traces to a trace

    +

    Adding child traces to the trace can be done by creating a builder with +child_builder. +Example:

    +
    def process(self, trace, data_context):
    +    child_builder = trace.child_builder('childTrace-1')
    +    child_builder.update({
    +        'chatMessage.application': 'DemoApp',
    +        'chatMessage.from': 'Ann',
    +        'chatMessage.to': ['Mark'],
    +        # list, because there can be multiple receivers
    +        'chatMessage.message': 'Hello, are you there?',
    +    }).build()
    +    grandchild_builder = child_builder.child_builder('grandchild')
    +    grandchild_builder.update(data={'byte': b'some bytes'})
    +    grandchild_builder.build()
    +
    +
    +

    This adds a single child trace with name childTrace-1 with four properties and a grandchild trace with name +grandchild and a byte data stream.

    +
    +
    +

    Adding data to a trace

    +

    Traces can have data attached to them. See Data streams for more information. +The following two snippets demonstrate how to add data to a trace.

    +

    It is currently not possible to verify that a specific data stream is already set or not.

    +
    +

    Data Transformations

    +

    The most efficient way to add data to a trace is using data transformations. +See Data Transformations for more details.

    +

    The following example sets a new datastream with dataType html on a trace, by setting a ranged data transformation:

    +
    trace.add_transformation('html', RangedTransformation(Range(offset, length)))
    +
    +
    +

    The following example creates a child trace and sets a new datastream with dataType raw on it, by setting a ranged +data transformation with two ranges:

    +
    child = trace.child_builder('new trace')
    +child.add_transformation('raw', RangedTransformation.builder()
    +                         .add_range(10, 20)
    +                         .add_range(50, 30)
    +                         .build())
    +});
    +
    +
    +
    +
    +

    Blobs

    +

    It is not always possible to create a transformation for the data that has to be +added to a trace. For example, if the data is a result of a computation, and not +a direct subset of another data stream..

    +

    The following snippet shows how to create a new data stream of dataType raw on a trace from a blob stored in bytes:

    +
    data = {'raw': b'...'}
    +trace.update(data=data);
    +
    +
    +
    +

    Streaming data

    +
    +

    Warning

    +

    Streaming data does not work with the Hansken.py runner because Hansken.py does not support it. It does +work when running your plugin in Hansken and in the test framework.

    +
    +

    When dealing with large quantities of data, it is possible to keep the memory usage +of the plugin within manageable limits by streaming the data from the plugin to Hansken in smaller chunks. +To do this, use the with trace.open(data_type=..., mode='wb') syntax. Here are some examples:

    +

    Stream strings to raw (default) datastream:

    +
    with trace.open(mode='wb') as writer:
    +    writer.write(b'a string')
    +    writer.write(bytes(another_string, 'utf-8'))
    +
    +
    +

    Stream a BufferedReader object to a text datastream:

    +
    with trace.open(data_type='text', mode='wb') as output, open('input.text', 'rb') as in_file:
    +    output.write(in_file)
    +
    +
    +
    +
    +

    Streaming text

    +

    To write str values directly, use mode w (or wt). +By default, it is assumed that the written text is ‘utf-8’ encoded. The default encoding can be overwritten by using the 'encoding=' argument.

    +

    (In a future Hansken update) Hansken will set the correct data-stream properties for your text stream (mimeType, mimeClass, and fileType).

    +
    with trace.open(data_type='raw', mode='w', encoding='utf-8') as text_writer:
    +    text_writer.write('hello.world')  # write strings directly to the writer
    +    json.dump({'hello': 'world'}, text_writer)  # or pass the writer to json.dump
    +
    +
    +

    It is recommended to pass utf-8 explictly as encoding.

    +
    +
    +
    +
    +

    Specifying system resources

    +

    It is possible to specify system resources hints in the PluginInfo. To run a plugin with at least 0.5 cpu (= 0.5 +vCPU/Core/hyperthread), 1 gb memory and 10 (concurrent) cpu workers (threads), for example, the following configuration can be added to PluginInfo:

    +
    plugin_info = PluginInfo(...,
    +                         resources=PluginResources(maximum_cpu=0.5, maximum_memory=1000, maximum_workers=10))
    +
    +
    +
    +
    +

    Deferred Plugins

    +

    Implementing a deferred extraction plugin requires inheriting the +DeferredExtractionPlugin +base class.

    +
    class DeferredPlugin(DeferredExtractionPlugin):
    +    def process(self, trace, context, searcher):
    +
    +
    +

    This allows accessing a third TraceSearcher +parameter in the process function. This can be used to search for traces:

    +
    with searcher.search('file.extension:html', 10, scope='image') as searchresult:
    +    for trace in searchresult:
    +        log.debug(f'extension {trace.get("file.extension")}')
    +
    +
    +

    The search method accepts three arguments;

    +
      +
    1. a HQL query (note: this is the traditional HQL query, and not the matchers HQL-lite variant),

    2. +
    3. (optional) the maximum number of traces to return (currently hard-limited to a maximum of 50 traces),

    4. +
    5. (optional) a scope, which can be either image, or project. When set to image, the searcher will only search for traces +within the same image as the trace that is being processed.

    6. +
    +

    The returned SearchResult +should be closed, for example by using with. The resulting search result is an iterable, which will be exhausted when +no more traces are available. The search result allows taking one or more traces by calling :py: +meth:take <hansken_extraction_plugin.api.search_result.SearchResult.take> or +takeone.

    +
    +

    Note

    +

    The command trace.open(datastream_type) will fail on search result traces that do not originate from the +same image (evidence item) as the trace that is being processed.

    +
    +
    +
    +

    Deferred Meta Extraction Plugins

    +

    Implementing a deferred meta extraction plugin requires inheriting the +DeferredMetaExtractionPlugin +base class. This plugin is not able to call the trace.open() method since the actual trace data is not available to this plugin. +Also matching on data type will not work for this plugin since this plugin only works for meta traces

    +
    class DeferredMetaPlugin(DeferredMetaExtractionPlugin):
    +    def plugin_info(self):
    +        ...
    +
    +    def process(self, trace, searcher):
    +        ...
    +
    +
    +
    +
    +

    Bulk Mode

    +

    The PluginInfo contains a parameter bulk_mode. This can be used for lightweight plugins which have to process a lot +of data (either a lot of traces with data or a small number of traces with large data streams). For streaming +extractions, these plugins will run inside the worker pod, and will therefore be able to process data more efficiently.

    +

    WARNING: The plugin should be lightweight. This means that it should not use a lot of resources like CPU or memory, +because this will limit the resources of the worker pod, and therefore Hansken will not be able to start enough workers +to do extractions.

    +

    Creating a plugin with bulk mode enabled can be done by setting the parameter to True in the PluginInfo as follows:

    +
    plugin_info = PluginInfo(...,
    +                         bulk_mode=True)
    +
    +
    +
    +
    +

    Logging

    +

    We use Logbook to log messages in Python. Logbook is a logging system for Python that replaces the standard library’s +logging module.

    +

    To enable logging in your plugin, add the following to the top of your plugin code:

    +
    from logbook import Logger
    +
    +log = Logger(__name__)
    +
    +
    +

    From there on the logging is pretty straight forward:

    +
    log.info(f'Logging a variable: {my_variable}')
    +
    +
    +

    The default log level is WARNING. There are two ways to set the logging level. You can use the -v (or -vv or -vvv) option of serve_plugin.py to increase the log level. This is typically done in the plugin Dockerfile. Another option is to use an environment variable, LOG_LEVEL. Available levels are WARNING, NOTICE, INFO and DEBUG. The environment variable overrides the option.

    +
    +

    Warning

    +

    Be careful with logging sensitive information.

    +
    +
    +

    Note

    +

    Contact your Hansken administrator for more information on where to find logs for your Hansken environment.

    +
    +
    +
    +

    [EXPERIMENTAL FEATURE] Adding previews to a trace

    +
    +

    Warning

    +

    This is an experimental feature, which might change or get removed in future releases.

    +
    +

    Use update +to add previews to an +ExtractionTrace. +Example:

    +
    def process(self, trace, data_context):
    +    # set the preview data for the image/png MIME-type
    +    trace.update('preview.image/png', b'\x00\xff')
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/testing.html b/0.9.16/dev/python/testing.html new file mode 100644 index 0000000..e1c2f48 --- /dev/null +++ b/0.9.16/dev/python/testing.html @@ -0,0 +1,249 @@ + + + + + + + + + Advanced use of the Test Framework in Python — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Advanced use of the Test Framework in Python

    +

    This section assumes you use the same setup as is used in +the Extraction Plugin Examples.

    +

    By default, the build scripts as described in the Getting Started section will automatically run +tests. The appropriate commands have been added to the tox.ini directly. This section gives a little more detail on the +test commands and options.

    +

    One can simply create unit tests for a plugin directly. However, we also provide a test-framework for testing them over +gRPC. The test-framework serves a running instance of a Python plugin, and feeds it input files and compares the results +against an expected result set.

    +

    Note that the test-framework is implemented in Java, hence the Java 11 requirement. A jar file is included in the Python +SDK which is called from a Python wrapper.

    +
    +

    Regenerate expected test results

    +

    The build and test scripts run some integration tests. To update the expected test outcome, the following command can be +used:

    +
    tox -e regenerate
    +
    +
    +
    +
    +

    Standalone testing

    +

    The test runner is a script called test_plugin which is available in the SDK.

    +

    To get started, cd into the directory of the plugin you want to test and run:

    +
    test_plugin --standalone plugin/chat_plugin.py
    +
    +
    +

    Note that the argument provided to the option --standalone in this example is the relative path to the plugin py +file which is to be tested. This test accepts input files from the directory testdata/input and compares the results +to the result files in found in testdata/results. Use the optional argument --regenerate to regenerate the expected +results for the test when needed.

    +

    This standalone test is also used by the tox.ini file to validate the plugin. Simply calling tox should be enough to +install all dependencies and run the test.

    +

    In case the plugin was defined in a module that is to be imported by the interpreter, it’s also possible to run this +command by referencing either the module that defines the plugin or the plugin directly:

    +
    test_plugin --standalone plugin_module
    +# or, assuming the plugin class is called ChatPlugin
    +test_plugin --standalone plugin_module:ChatPlugin
    +
    +
    +
    +
    +

    Testing with a Docker image

    +

    If there is a docker image available for the plugin you can also test it by executing:

    +
    test_plugin --docker extraction-plugin-examples-my-plugin
    +
    +
    +

    Replace the ‘extraction-plugin-examples-chat’ with the docker image you want to test. Run the following command to see +which docker images are available:

    +
    docker images
    +
    +
    +
    +
    +

    Manual testing

    +

    The third option for testing is a manually started plugin. Start the plugin service in a terminal by executing:

    +
    serve_plugin -vvv plugin/my_plugin.py
    +
    +
    +

    This will spin up the chat plugin at port 8999. In this example the argument is also a path to the plugin’s .py file. +The same alternative reference to the plugin shown with test_plugin above applies here.

    +

    In another terminal window, run the test with:

    +
    test_plugin --manual localhost 8999
    +
    +
    +
    +
    +

    Tip: Start tests in your IDE

    +

    To start the extraction plugin from code, create a __main__ method which calls the _test_validate_standalone +method of the test framework (see the example below). This method causes the extraction plugin to be started and +supplied with data by the FLITS test framework. In this way the test can be started from the IDE, which has the +advantage that it is easier to debug.

    +
    from hansken_extraction_plugin.test_framework.test_plugin import _test_validate_standalone
    +from hansken_extraction_plugin.api.extraction_plugin import ExtractionPlugin
    +
    +
    +class PluginToTest(ExtractionPlugin):
    +
    +    def plugin_info(self):
    +        # return plugin info
    +        pass
    +
    +    def process(self, trace, data_context):
    +        # process the data/trace here
    +        pass
    +
    +
    +if __name__ == '__main__':
    +    _test_validate_standalone(PluginToTest, 'testdata/input', 'testdata/result', False)
    +
    +
    +
    +
    +

    Help

    +

    Run the following for an overview of all the available options in the test script:

    +
    test_plugin --help
    +
    +
    +
    +
    +

    Testing transformers

    +

    The sdk includes a script to test transformer functions. This script will start an extraction plugin, executes a single transformer function with the provided arguments and stops the plugin. Try it with:

    +
    execute_transformer docker_image method_name arguments
    +
    +
    +

    The arguments are provided in named argument pairs, so calling a method called translate with two parameters language and input might look like this:

    +
    execute_transformer translator_plugin translate language nl_NL input "example input"
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/python/transformers.html b/0.9.16/dev/python/transformers.html new file mode 100644 index 0000000..7ae21df --- /dev/null +++ b/0.9.16/dev/python/transformers.html @@ -0,0 +1,245 @@ + + + + + + + + + Using Transformers for on-demand execution — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Using Transformers for on-demand execution

    +
    +

    What are Transformers?

    +

    Transformers are methods inside a plugin that can be called remotely at any moment. +This allows for live plugin execution independent of extraction. +Examples on how transformers could be used:

    +
      +
    • For searching images using text (i.e. a purple car).

    • +
    • For translating text in traces so that an investigator can read the text in their preferred language in a UI.

    • +
    • For converting speech to text.

    • +
    +
    +
    +

    How do Transformers work in Hansken?

    +

    Transformers can be implemented in extraction plugins. Using the Hansken REST API, calls can be made to a +specific plugin’s transformer by specifying the transformer one wishes to call as well as its arguments. +Hansken can automatically discover transformers before plugins are actually started. +Once it has received a request for invoking a transformer it can choose to start the plugin’s Docker container if it +is not already started and send the request once it is up and running.

    +
    +
    +

    Developing Transformers

    +

    This section assumes you use the same setup as is used in the Extraction Plugin Examples.

    +

    A transformer can be easily defined by using the transformer decorator. By creating a method inside your plugin and +decorating it with the transformer decorator it will automatically be made available to be remotely called.

    +
    from hansken_extraction_plugin.api.extraction_plugin import ExtractionPlugin
    +from hansken_extraction_plugin.decorators.transformer import transformer
    +class Plugin(ExtractionPlugin):
    +
    +    def plugin_info(self):
    +        ...
    +
    +    def process(self, trace, data_context):
    +        ...
    +
    +    @transformer
    +    def translate_text(self, text: str, language: str) -> str:
    +        # To implement: Translate the text here.
    +        return "Translated text"
    +
    +
    +
    +
    +

    Limitations on Transformers

    +

    However, there are some limitations on which methods can be turned into a decorator method:

    +
      +
    • Transformers may only be defined on methods of a class that derives (indirectly) from BaseExtractionPlugin.

      +
        +
      • Note: ExtractionPlugin derives from BaseExtractionPlugin and is therefore allowed.

      • +
      +
    • +
    • Transformer may not be static methods.

    • +
    • All parameters and the return type must be annotated with type hints (except the self parameter).

    • +
    • Parameters may not be positional-only or contain variable parameters like *args or **kwarg.

    • +
    • Parameters and return types may only be of the following (returning None is not supported):

      +
        +
      • bool

      • +
      • int

      • +
      • float

      • +
      • str

      • +
      • bytes

      • +
      • bytearray

      • +
      • datetime.datetime (The datetime will be converted to unix time and then converted to datetime with the zone “UTC”. So the zone id is always(“UTC”))

      • +
      • hansken.util.GeographicLocation

      • +
      • hansken.util.Vector

      • +
      • typing.Sequence

      • +
      • typing.Mapping

      • +
      +
    • +
    +

    Upon starting a plugin every method decorated with the transformer decorator will be automatically validated to see if they adhere to these requirements. An exception will be thrown when a method does not adhere to all of these requirements.

    +
    +
    +

    Error handling in Transformers

    +

    If at some point a transformer wishes to signal to the caller of the transformer that something has gone wrong +it can simply throw a suitable exception. Any exceptions being thrown will automatically be propagated to the client +calling the transformer by wrapping the exception in a gRPC exception. The stack trace will be provided as well for +debugging purposes.

    +
    +
    +

    Testing transformers

    +

    For more information on testing transformers, see the ‘Testing Transformers’ section on the page on testing plugins.

    +
    +
    +

    Calling transformer with /tools/transformers

    +

    This REST Call calls a specified transformer method on a given tool/plugin with supplied arguments. +This endpoint allows a transformer to be executed on demand, outside an extraction. The transformer call can be used to transform user input to an output. A tool/plugin can have multiple transformer methods. +To use /tools/transformers REST CALL you need to know the following (see extractions tool or use the rest call/tools to get the information below):

    +
      +
    • The name of the plugin/tool

    • +
    • The transformer name

    • +
    • The names of the parameters (arguments)

    • +
    +

    Example JSON request body for the transformer above:

    +
    {
    +  "arguments": {
    +    "text": "value1",
    +    "language": "value2"
    +  },
    +  "tool": "ExampleTool",
    +  "transformer": "translate_text"
    +}
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/dev/spec.html b/0.9.16/dev/spec.html new file mode 100644 index 0000000..6d11b6f --- /dev/null +++ b/0.9.16/dev/spec.html @@ -0,0 +1,189 @@ + + + + + + + + + Extraction Plugin specifications — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Extraction Plugin specifications

    +
    +

    Note

    +

    If you use the Java or Python extraction plugin SDK, you don’t have +to worry about these specifications. The Java and Python SDKs makes +sure your plugin is compiled and packaged conform to the extraction +plugin specifications.

    +
    +

    This page describes the specifications that define an extraction plugin. +The spec contains two major parts: a plugin protocol, and the plugin packaging +method.

    +

    This specification applies to plugins that are not embedded within Hansken, +but to plugins that developed and distributed outside the scope of the Hansken +platform development.

    +
    +

    Plugin protocol

    +

    An extraction plugin is a process that implements a GRPC +service ExtractionPluginService. The service defines a protocol that is +used to allow communication between Hansken and an extraction plugin. The +GRPC and protocol definitions can be found in the extraction plugin source +code, under the folder grpc.

    +
    +

    Note

    +

    The source code of the Extraction Plugin is currently not available +outside the scope of the Hansken core development teams. If you are +interested in the GRPC definitions, please Contact the +Hansken development team.

    +
    +
    +
    +

    Packaging

    +

    An extraction plugin is packaged as a container image – conform the open +container initiative image spec. +An extraction plugin can be

    +

    The ENTRYPOINT of the container image should be a process that starts a GRPC +server that implements the plugin protocol. The GRPC protocol should run on port +8999 by default. The plugin should always observe the PLUGIN_PORT environment +variable, and run on that port if set.

    +

    The container image should be labeled with the plugin info. +The plugin info returned by the plugin plugin-info call and container labels +are required to match. If not, Hansken will not accept your plugin during +extractions - as it is unsure if the intended plugin is processing traces.

    +

    The labels that are expected are:

    +
      +
    • org.hansken.plugin-info.id (conform Plugin naming convention)

    • +
    • org.hansken.plugin-info.version

    • +
    • org.hansken.plugin-info.api-version

    • +
    • org.hansken.plugin-info.description

    • +
    • org.hansken.plugin-info.webpage

    • +
    • org.hansken.plugin-info.deferred-iterations (optional, only has a meaning for deferred extraction plugins)

    • +
    • org.hansken.plugin-info.matcher (see HQL-Lite)

    • +
    • org.hansken.plugin-info.license

    • +
    • org.hansken.plugin-info.author-name

    • +
    • org.hansken.plugin-info.author-organisation

    • +
    • org.hansken.plugin-info.author-email

    • +
    • org.hansken.plugin-info.resource-max_cpu (in millicpu, optional)

    • +
    • org.hansken.plugin-info.resource-max_mem (in mbs, optional)

    • +
    • org.hansken.plugin-info.bulk-mode (optional, false by default)

    • +
    • org.hansken.plugin-info.transformers (the signatures of the transformer methods as JSON). The transformers field contains a JSON array and is structured as follows:

      +
      [
      +    {"method_name": "test_func", "parameters": {"arg_1": "str", "arg_2": "str"}, "return_type": "vector"}
      +]
      +
      +
      +
    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/genindex.html b/0.9.16/genindex.html new file mode 100644 index 0000000..ce8fe32 --- /dev/null +++ b/0.9.16/genindex.html @@ -0,0 +1,599 @@ + + + + + + + + Index — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    +
      +
    • + +
    • +
    • +
    +
    +
    +
    +
    + + +

    Index

    + +
    + A + | B + | C + | D + | E + | F + | G + | H + | I + | L + | M + | N + | O + | P + | R + | S + | T + | U + | V + | W + +
    +

    A

    + + + +
    + +

    B

    + + + +
    + +

    C

    + + + +
    + +

    D

    + + + +
    + +

    E

    + + + +
    + +

    F

    + + + +
    + +

    G

    + + + +
    + +

    H

    + + + +
      +
    • + hansken_extraction_plugin.api + +
    • +
    • + hansken_extraction_plugin.api.data_context + +
    • +
    • + hansken_extraction_plugin.api.extraction_plugin + +
    • +
    • + hansken_extraction_plugin.api.extraction_trace + +
    • +
    • + hansken_extraction_plugin.api.plugin_info + +
    • +
    • + hansken_extraction_plugin.api.search_result + +
    • +
      +
    • + hansken_extraction_plugin.api.search_sort_option + +
    • +
    • + hansken_extraction_plugin.api.trace_searcher + +
    • +
    • + hansken_extraction_plugin.api.tracelet + +
    • +
    • + hansken_extraction_plugin.api.transformation + +
    • +
    • + hansken_extraction_plugin.api.transformer + +
    • +
    + +

    I

    + + + +
    + +

    L

    + + + +
    + +

    M

    + + +
    + +

    N

    + + +
    + +

    O

    + + + +
    + +

    P

    + + + +
    + +

    R

    + + + +
    + +

    S

    + + + +
    + +

    T

    + + + +
    + +

    U

    + + +
    + +

    V

    + + +
    + +

    W

    + + +
    + + + +
    +
    +
    + +
    + +
    +

    © Copyright 2020-2026 Netherlands Forensic Institute.

    +
    + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/index.html b/0.9.16/index.html new file mode 100644 index 0000000..dfcf63e --- /dev/null +++ b/0.9.16/index.html @@ -0,0 +1,164 @@ + + + + + + + + + Hansken extraction plugin SDK documentation for plugin developers — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    +
      +
    • + +
    • + View page source +
    • +
    +
    +
    +
    +
    + +
    +

    Hansken extraction plugin SDK documentation for plugin developers

    +_images/cartoon.png + +
    +

    Welcome

    +

    Welcome to the Hansken extraction plugin SDK documentation for plugin developers. +This documentation describes the Hansken extraction plugin Software Development Kit (SDK). +If you are new here, you can start by reading the introduction.

    +
    +

    Attention

    +

    Hansken extraction plugins is a technology preview. +Please don’t consider the SDK and integration in Hansken to be fully stable.

    +
    + +

    + +Cartoon by @jorgb, all rights reserved +

    +
    +
    + + +
    +
    +
    + +
    + +
    +

    © Copyright 2020-2026 Netherlands Forensic Institute.

    +
    + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/objects.inv b/0.9.16/objects.inv new file mode 100644 index 0000000..668e1be Binary files /dev/null and b/0.9.16/objects.inv differ diff --git a/0.9.16/py-modindex.html b/0.9.16/py-modindex.html new file mode 100644 index 0000000..05f075c --- /dev/null +++ b/0.9.16/py-modindex.html @@ -0,0 +1,185 @@ + + + + + + + + Python Module Index — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    +
      +
    • + +
    • +
    • +
    +
    +
    + +
    + +
    + +
    +

    © Copyright 2020-2026 Netherlands Forensic Institute.

    +
    + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/0.9.16/search.html b/0.9.16/search.html new file mode 100644 index 0000000..6fd4019 --- /dev/null +++ b/0.9.16/search.html @@ -0,0 +1,130 @@ + + + + + + + + Search — Hansken Extraction Plugins for plugin developers 0.9.16 + documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    +
      +
    • + +
    • +
    • +
    +
    +
    +
    +
    + + + + +
    + +
    + +
    +
    +
    + +
    + +
    +

    © Copyright 2020-2026 Netherlands Forensic Institute.

    +
    + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
    +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/0.9.16/searchindex.js b/0.9.16/searchindex.js new file mode 100644 index 0000000..370ddf5 --- /dev/null +++ b/0.9.16/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles": {"$data matchers": [[7, "data-matchers"]], "0.2.0": [[18, "id17"], [37, "id23"]], "0.3.0": [[18, "id16"], [37, "id22"]], "0.4.0": [[18, "id15"], [37, "id21"]], "0.4.13": [[18, "id12"], [37, "id18"]], "0.4.6": [[18, "id14"], [37, "id20"]], "0.4.7": [[18, "id13"], [37, "id19"]], "0.5.0": [[18, "id11"], [37, "id17"]], "0.5.1": [[37, "id16"]], "0.6.0": [[18, "id10"], [37, "id15"]], "0.6.1": [[18, "id9"], [37, "id14"]], "0.6.3": [[18, "id8"]], "0.7.0": [[18, "id7"], [37, "id13"]], "0.7.3": [[37, "id12"]], "0.8.0": [[18, "id5"], [37, "id10"]], "0.8.1": [[37, "id9"]], "0.8.2": [[37, "id8"]], "0.8.3": [[37, "id7"]], "0.9.10": [[18, "id3"], [37, "id2"]], "0.9.11": [[18, "id2"]], "0.9.13": [[18, "id1"], [37, "id1"]], "0.9.2": [[37, "id6"]], "0.9.4": [[37, "id5"]], "0.9.5": [[18, "id4"], [37, "id4"]], "0.9.9": [[37, "id3"]], "API Documentation": [[25, "api-documentation"]], "API changes": [[37, "api-changes"]], "Adding child traces to a trace": [[43, "adding-child-traces-to-a-trace"]], "Adding data to a trace": [[23, "adding-data-to-a-trace"], [43, "adding-data-to-a-trace"]], "Adding properties to a trace": [[43, "adding-properties-to-a-trace"]], "Adding tracelets": [[23, "adding-tracelets"], [43, "adding-tracelets"]], "Advanced use of the Test Framework in Python": [[44, "advanced-use-of-the-test-framework-in-python"]], "Anatomy of a plugin": [[4, "anatomy-of-a-plugin"]], "Autoscaling": [[9, "autoscaling"]], "Basic test data directory structure": [[12, "basic-test-data-directory-structure"]], "Blobs": [[23, "blobs"], [43, "blobs"]], "Build a Docker image": [[19, "build-a-docker-image"], [38, "build-a-docker-image"]], "Build pipeline change": [[37, "build-pipeline-change"]], "Building a plugin": [[6, "building-a-plugin"]], "Bulk Mode": [[23, "bulk-mode"], [43, "bulk-mode"]], "Calling transformer with /tools/transformers": [[45, "calling-transformer-with-tools-transformers"]], "Can I reuse or modify the Extraction Plugins SDK?": [[15, "can-i-reuse-or-modify-the-extraction-plugins-sdk"]], "Can I use a plugin that someone else wrote?": [[15, "can-i-use-a-plugin-that-someone-else-wrote"]], "Can my Extraction Plugin be embedded into Hansken for performance reasons?": [[15, "can-my-extraction-plugin-be-embedded-into-hansken-for-performance-reasons"]], "Category for extra properties": [[43, "category-for-extra-properties"]], "Changelog": [[0, "changelog"]], "Child traces": [[13, "child-traces"]], "Command usage": [[41, "command-usage"]], "Compatibility": [[40, "compatibility"]], "Configuring debugpy in Python": [[38, "configuring-debugpy-in-python"]], "Configuring the connection to the Docker container": [[38, "configuring-the-connection-to-the-docker-container"]], "Contact": [[1, "contact"]], "Contents:": [[2, null], [17, null], [25, null], [47, null]], "Create a runner file": [[40, "create-a-runner-file"]], "Creating test data": [[12, "creating-test-data"]], "Customize logging": [[23, "customize-logging"]], "Data Transformations": [[5, "data-transformations"], [23, "data-transformations"], [43, "data-transformations"]], "Data streams": [[13, "data-streams"]], "Date properties": [[43, "date-properties"]], "Debug HQL": [[19, "debug-hql"], [38, "debug-hql"]], "Debugging locally with Hansken All in One (AIO)": [[3, "debugging-locally-with-hansken-all-in-one-aio"]], "Deferred Extraction Plugins": [[11, "deferred-extraction-plugins"], [23, "deferred-extraction-plugins"]], "Deferred Meta Extraction Plugins": [[11, "deferred-meta-extraction-plugins"], [43, "deferred-meta-extraction-plugins"]], "Deferred Plugins": [[43, "deferred-plugins"]], "Developing Transformers": [[45, "developing-transformers"]], "Development steps of a plugin": [[16, "development-steps-of-a-plugin"]], "Download an extraction plugin template (empty plugin)": [[39, "download-an-extraction-plugin-template-empty-plugin"]], "Embedded Testing example": [[24, "embedded-testing-example"]], "Embedded Testing versus Remote Testing": [[24, "embedded-testing-versus-remote-testing"]], "Error handling in Transformers": [[45, "error-handling-in-transformers"]], "Examples": [[10, "examples"], [14, "examples"]], "Extracting": [[4, "extracting"]], "Extraction Plugin specifications": [[46, "extraction-plugin-specifications"]], "Extraction plugin types": [[11, "extraction-plugin-types"]], "Finding the right settings": [[9, "finding-the-right-settings"]], "Finishing an extraction": [[4, "finishing-an-extraction"]], "Frequently Asked Questions": [[15, "frequently-asked-questions"]], "General concepts": [[2, "general-concepts"]], "Getting started": [[39, "getting-started"]], "HQL-Lite": [[7, "hql-lite"]], "HQL-Lite syntax": [[7, "hql-lite-syntax"]], "Hansken Extraction Plugins": [[6, "hansken-extraction-plugins"]], "Hansken extraction plugin SDK documentation for plugin developers": [[47, "hansken-extraction-plugin-sdk-documentation-for-plugin-developers"]], "Hansken trace model": [[13, "hansken-trace-model"]], "Help": [[44, "help"]], "How can I access Hansken developer community": [[15, "how-can-i-access-hansken-developer-community"]], "How can I describe that input with the information Hansken provides?": [[7, "how-can-i-describe-that-input-with-the-information-hansken-provides"]], "How do Transformers work in Hansken?": [[45, "how-do-transformers-work-in-hansken"]], "How does Hansken work?": [[7, "how-does-hansken-work"]], "How precise should a matcher be?": [[7, "how-precise-should-a-matcher-be"]], "How safe are Extraction Plugins?": [[15, "how-safe-are-extraction-plugins"]], "How to debug an Extraction Plugin": [[19, "how-to-debug-an-extraction-plugin"], [38, "how-to-debug-an-extraction-plugin"]], "How to run python extraction plugins standalone with Hansken.py": [[40, "how-to-run-python-extraction-plugins-standalone-with-hansken-py"]], "How to test your plugin": [[12, "how-to-test-your-plugin"]], "How to write a matcher?": [[7, "how-to-write-a-matcher"]], "Import the Extraction Plugins Skeleton in PyCharm": [[39, "import-the-extraction-plugins-skeleton-in-pycharm"]], "Input trace JSON format": [[12, "input-trace-json-format"]], "Install Docker (Ubuntu, Windows)": [[39, "install-docker-ubuntu-windows"]], "Install debugpy": [[38, "install-debugpy"]], "Install required software on Ubuntu": [[39, "install-required-software-on-ubuntu"]], "Install required software on Windows": [[39, "install-required-software-on-windows"]], "Intrinsic properties": [[13, "intrinsic-properties"]], "Introduction": [[16, "introduction"]], "Java": [[12, "java"], [17, "java"]], "Java API Changelog": [[18, "java-api-changelog"]], "Java code snippets": [[23, "java-code-snippets"]], "Javadoc": [[20, "javadoc"]], "Kubernetes": [[19, "kubernetes"], [38, "kubernetes"]], "Kubernetes, Autoscaling, Resourcemanagement": [[9, "kubernetes-autoscaling-resourcemanagement"]], "Leaving out the message": [[12, "leaving-out-the-message"]], "Limitations on Transformers": [[45, "limitations-on-transformers"]], "Locally": [[19, "locally"], [38, "locally"]], "Locally with Docker": [[19, "locally-with-docker"], [38, "locally-with-docker"]], "Logging": [[19, "logging"], [23, "logging"], [38, "logging"], [43, "logging"]], "Logging in Docker": [[19, "logging-in-docker"], [38, "logging-in-docker"]], "Logging in Kubernetes": [[19, "logging-in-kubernetes"], [38, "logging-in-kubernetes"]], "Manual testing": [[44, "manual-testing"]], "Match if \u2018property is set\u2019": [[7, "match-if-property-is-set"]], "Match on data size": [[7, "match-on-data-size"]], "Match on excluding a certain path": [[7, "match-on-excluding-a-certain-path"]], "Match on extension": [[7, "match-on-extension"]], "Match on mime-type": [[7, "match-on-mime-type"]], "Match on specific datastream type, an anti-pattern": [[7, "match-on-specific-datastream-type-an-anti-pattern"]], "Matchers to the rescue": [[7, "matchers-to-the-rescue"]], "Meta Extraction Plugins": [[11, "meta-extraction-plugins"]], "Network isolation": [[8, "network-isolation"]], "Next steps": [[39, "next-steps"]], "Overview": [[7, "overview"]], "Package the plugin": [[6, "package-the-plugin"]], "Packaging": [[21, "packaging"], [41, "packaging"], [46, "packaging"]], "PdfPlugin example": [[7, "pdfplugin-example"]], "Plugin discovery": [[4, "plugin-discovery"]], "Plugin identifier": [[10, "plugin-identifier"]], "Plugin isolation": [[8, "plugin-isolation"]], "Plugin naming convention": [[10, "plugin-naming-convention"]], "Plugin protocol": [[46, "plugin-protocol"]], "Preparing for the command": [[40, "preparing-for-the-command"]], "Prerequisites": [[22, "prerequisites"], [24, "prerequisites"], [42, "prerequisites"]], "Python": [[12, "python"], [25, "python"]], "Python API Changelog": [[37, "python-api-changelog"]], "Python code snippets": [[43, "python-code-snippets"]], "Quick links": [[47, "quick-links"]], "RandomAccessData as InputStream": [[23, "randomaccessdata-as-inputstream"]], "Refresh the Hansken tools list": [[6, "refresh-the-hansken-tools-list"]], "Regenerate expected test results": [[44, "regenerate-expected-test-results"]], "Release-0.1.0": [[0, "release-0-1-0"]], "Release-0.1.1": [[0, "release-0-1-1"]], "Release-0.1.2": [[0, "release-0-1-2"]], "Release-0.1.3": [[0, "release-0-1-3"]], "Release-0.1.4": [[0, "release-0-1-4"]], "Release-0.1.5": [[0, "release-0-1-5"]], "Release-0.1.6": [[0, "release-0-1-6"]], "Release-0.1.7": [[0, "release-0-1-7"]], "Release-0.1.8": [[0, "release-0-1-8"]], "Release-0.2.0": [[0, "release-0-2-0"]], "Release-0.3.0": [[0, "release-0-3-0"]], "Release-0.4.0": [[0, "release-0-4-0"]], "Release-0.4.1": [[0, "release-0-4-1"]], "Release-0.4.10": [[0, "release-0-4-10"]], "Release-0.4.11": [[0, "release-0-4-11"]], "Release-0.4.12": [[0, "release-0-4-12"]], "Release-0.4.13": [[0, "release-0-4-13"]], "Release-0.4.14": [[0, "release-0-4-14"]], "Release-0.4.2": [[0, "release-0-4-2"]], "Release-0.4.3": [[0, "release-0-4-3"]], "Release-0.4.4": [[0, "release-0-4-4"]], "Release-0.4.5": [[0, "release-0-4-5"]], "Release-0.4.6": [[0, "release-0-4-6"]], "Release-0.4.7": [[0, "release-0-4-7"]], "Release-0.4.8": [[0, "release-0-4-8"]], "Release-0.4.9": [[0, "release-0-4-9"]], "Release-0.5.0": [[0, "release-0-5-0"]], "Release-0.5.1": [[0, "release-0-5-1"]], "Release-0.6.0": [[0, "release-0-6-0"]], "Release-0.6.1": [[0, "release-0-6-1"]], "Release-0.6.2": [[0, "release-0-6-2"]], "Release-0.6.3": [[0, "release-0-6-3"]], "Release-0.7.0": [[0, "release-0-7-0"]], "Release-0.7.1": [[0, "release-0-7-1"]], "Release-0.7.2": [[0, "release-0-7-2"]], "Release-0.7.3": [[0, "release-0-7-3"]], "Release-0.7.4": [[0, "release-0-7-4"]], "Release-0.8.0": [[0, "release-0-8-0"]], "Release-0.8.1": [[0, "release-0-8-1"]], "Release-0.8.2": [[0, "release-0-8-2"]], "Release-0.8.3": [[0, "release-0-8-3"]], "Release-0.8.4": [[0, "release-0-8-4"]], "Release-0.9.0": [[0, "release-0-9-0"]], "Release-0.9.1": [[0, "release-0-9-1"]], "Release-0.9.10": [[0, "release-0-9-10"]], "Release-0.9.11": [[0, "release-0-9-11"]], "Release-0.9.12": [[0, "release-0-9-12"]], "Release-0.9.13": [[0, "release-0-9-13"]], "Release-0.9.14": [[0, "release-0-9-14"]], "Release-0.9.15": [[0, "release-0-9-15"]], "Release-0.9.16\n": [[0, "release-version"]], "Release-0.9.2": [[0, "release-0-9-2"]], "Release-0.9.4": [[0, "release-0-9-4"]], "Release-0.9.5": [[0, "release-0-9-5"]], "Release-0.9.6": [[0, "release-0-9-6"]], "Release-0.9.7": [[0, "release-0-9-7"]], "Release-0.9.8": [[0, "release-0-9-8"]], "Release-0.9.9": [[0, "release-0-9-9"]], "Remote Testing example": [[24, "remote-testing-example"]], "Requirements": [[41, "requirements"]], "Result trace JSON format": [[12, "result-trace-json-format"]], "Run plugins with Hansken.py": [[40, "run-plugins-with-hansken-py"]], "Run the Docker image with specific Java tool options": [[19, "run-the-docker-image-with-specific-java-tool-options"]], "Running your plugin with Hansken.py": [[40, "running-your-plugin-with-hansken-py"]], "See also": [[5, "see-also"]], "Set up your IDE: PyCharm": [[39, "set-up-your-ide-pycharm"]], "Setting breakpoints in the code": [[19, "setting-breakpoints-in-the-code"], [38, "setting-breakpoints-in-the-code"]], "Software Development Kit (SDK)": [[16, "software-development-kit-sdk"]], "Specifying system resources": [[23, "specifying-system-resources"], [43, "specifying-system-resources"]], "Standalone testing": [[44, "standalone-testing"]], "Standard Extraction Plugins": [[11, "standard-extraction-plugins"]], "Start an extraction with the plugin enabled": [[6, "start-an-extraction-with-the-plugin-enabled"]], "Starting an extraction": [[4, "starting-an-extraction"]], "Streaming data": [[43, "streaming-data"]], "Streaming text": [[43, "streaming-text"]], "System calls": [[8, "system-calls"]], "Test data structure for deferred extraction plugins": [[12, "test-data-structure-for-deferred-extraction-plugins"]], "Test framework": [[12, "test-framework"]], "Testing exceptions": [[12, "testing-exceptions"]], "Testing transformers": [[44, "testing-transformers"], [45, "testing-transformers"]], "Testing with a Docker image": [[44, "testing-with-a-docker-image"]], "The containsInOrder partial result matcher": [[12, "the-containsinorder-partial-result-matcher"]], "The execution in Hansken": [[4, "the-execution-in-hansken"]], "The method pluginInfo()": [[4, "the-method-plugininfo"]], "The method process()": [[4, "the-method-process"]], "The plugin itself": [[4, "the-plugin-itself"]], "The startsWith partial result matcher": [[12, "the-startswith-partial-result-matcher"]], "Tip: Start tests in your IDE": [[44, "tip-start-tests-in-your-ide"]], "Tips/notes": [[3, "tips-notes"]], "Trace format": [[12, "trace-format"]], "Trace model and the extraction plugin SDK": [[13, "trace-model-and-the-extraction-plugin-sdk"]], "Trace property types": [[13, "trace-property-types"]], "Tracelets": [[13, "tracelets"]], "Traces": [[13, "traces"]], "Traces & Trace model": [[13, "traces-trace-model"]], "Types and Properties": [[13, "types-and-properties"]], "Upload the plugin to Hansken": [[6, "upload-the-plugin-to-hansken"]], "Usage": [[23, "usage"]], "User isolation": [[8, "user-isolation"]], "Using Transformers for on-demand execution": [[45, "using-transformers-for-on-demand-execution"]], "Using the Test Framework in Java": [[24, "using-the-test-framework-in-java"]], "Vector": [[13, "vector"]], "Verify full setup": [[39, "verify-full-setup"]], "Welcome": [[47, "welcome"]], "What are Transformers?": [[45, "what-are-transformers"]], "What are the legal implications of creating your own Extraction Plugin(s)?": [[15, "what-are-the-legal-implications-of-creating-your-own-extraction-plugin-s"]], "What does can_this_tool_process_the_provided_trace() do?": [[7, "what-does-can-this-tool-process-the-provided-trace-do"]], "What does my plugin expect as input?": [[7, "what-does-my-plugin-expect-as-input"]], "What is HQL-Lite?": [[7, "what-is-hql-lite"]], "What programming languages are supported?": [[15, "what-programming-languages-are-supported"]], "When is it useful to use a $data matcher?": [[7, "when-is-it-useful-to-use-a-data-matcher"]], "Why not just use HQL for plugins?": [[7, "why-not-just-use-hql-for-plugins"]], "Why use Extraction Plugins?": [[15, "why-use-extraction-plugins"]], "Will you support language foobar?": [[15, "will-you-support-language-foobar"]], "[EXPERIMENTAL FEATURE] Adding previews to a trace": [[23, "experimental-feature-adding-previews-to-a-trace"], [43, "experimental-feature-adding-previews-to-a-trace"]], "build_plugin": [[41, "build-plugin"]], "build_plugin_ci": [[41, "build-plugin-ci"]], "hansken_extraction_plugin.api": [[26, "module-hansken_extraction_plugin.api"]], "hansken_extraction_plugin.api.data_context": [[27, "module-hansken_extraction_plugin.api.data_context"]], "hansken_extraction_plugin.api.extraction_plugin": [[28, "module-hansken_extraction_plugin.api.extraction_plugin"]], "hansken_extraction_plugin.api.extraction_trace": [[29, "module-hansken_extraction_plugin.api.extraction_trace"]], "hansken_extraction_plugin.api.plugin_info": [[30, "module-hansken_extraction_plugin.api.plugin_info"]], "hansken_extraction_plugin.api.search_result": [[31, "module-hansken_extraction_plugin.api.search_result"]], "hansken_extraction_plugin.api.search_sort_option": [[32, "module-hansken_extraction_plugin.api.search_sort_option"]], "hansken_extraction_plugin.api.trace_searcher": [[33, "module-hansken_extraction_plugin.api.trace_searcher"]], "hansken_extraction_plugin.api.tracelet": [[34, "module-hansken_extraction_plugin.api.tracelet"]], "hansken_extraction_plugin.api.transformation": [[35, "module-hansken_extraction_plugin.api.transformation"]], "hansken_extraction_plugin.api.transformer": [[36, "module-hansken_extraction_plugin.api.transformer"]], "label_plugin": [[41, "label-plugin"]]}, "docnames": ["changes", "contact", "dev/concepts", "dev/concepts/all_in_one_debugging", "dev/concepts/anatomy_of_a_plugin", "dev/concepts/data_transformations", "dev/concepts/extraction_plugins", "dev/concepts/hql_lite", "dev/concepts/isolation", "dev/concepts/kubernetes_autoscaling", "dev/concepts/plugin_naming_convention", "dev/concepts/plugin_types", "dev/concepts/test_framework", "dev/concepts/traces", "dev/examples", "dev/faq", "dev/introduction", "dev/java", "dev/java/api_changelog", "dev/java/debugging", "dev/java/javadoc", "dev/java/packaging", "dev/java/prerequisites", "dev/java/snippets", "dev/java/testing", "dev/python", "dev/python/api/hansken_extraction_plugin.api", "dev/python/api/hansken_extraction_plugin.api.data_context", "dev/python/api/hansken_extraction_plugin.api.extraction_plugin", "dev/python/api/hansken_extraction_plugin.api.extraction_trace", "dev/python/api/hansken_extraction_plugin.api.plugin_info", "dev/python/api/hansken_extraction_plugin.api.search_result", "dev/python/api/hansken_extraction_plugin.api.search_sort_option", "dev/python/api/hansken_extraction_plugin.api.trace_searcher", "dev/python/api/hansken_extraction_plugin.api.tracelet", "dev/python/api/hansken_extraction_plugin.api.transformation", "dev/python/api/hansken_extraction_plugin.api.transformer", "dev/python/api_changelog", "dev/python/debugging", "dev/python/getting_started", "dev/python/hanskenpy", "dev/python/packaging", "dev/python/prerequisites", "dev/python/snippets", "dev/python/testing", "dev/python/transformers", "dev/spec", "index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1}, "filenames": ["changes.rst", "contact.md", "dev/concepts.rst", "dev/concepts/all_in_one_debugging.md", "dev/concepts/anatomy_of_a_plugin.md", "dev/concepts/data_transformations.md", "dev/concepts/extraction_plugins.md", "dev/concepts/hql_lite.md", "dev/concepts/isolation.md", "dev/concepts/kubernetes_autoscaling.md", "dev/concepts/plugin_naming_convention.md", "dev/concepts/plugin_types.md", "dev/concepts/test_framework.md", "dev/concepts/traces.md", "dev/examples.md", "dev/faq.md", "dev/introduction.md", "dev/java.rst", "dev/java/api_changelog.md", "dev/java/debugging.md", "dev/java/javadoc.md", "dev/java/packaging.md", "dev/java/prerequisites.md", "dev/java/snippets.md", "dev/java/testing.md", "dev/python.rst", "dev/python/api/hansken_extraction_plugin.api.rst", "dev/python/api/hansken_extraction_plugin.api.data_context.rst", "dev/python/api/hansken_extraction_plugin.api.extraction_plugin.rst", "dev/python/api/hansken_extraction_plugin.api.extraction_trace.rst", "dev/python/api/hansken_extraction_plugin.api.plugin_info.rst", "dev/python/api/hansken_extraction_plugin.api.search_result.rst", "dev/python/api/hansken_extraction_plugin.api.search_sort_option.rst", "dev/python/api/hansken_extraction_plugin.api.trace_searcher.rst", "dev/python/api/hansken_extraction_plugin.api.tracelet.rst", "dev/python/api/hansken_extraction_plugin.api.transformation.rst", "dev/python/api/hansken_extraction_plugin.api.transformer.rst", "dev/python/api_changelog.md", "dev/python/debugging.md", "dev/python/getting_started.md", "dev/python/hanskenpy.md", "dev/python/packaging.md", "dev/python/prerequisites.md", "dev/python/snippets.md", "dev/python/testing.md", "dev/python/transformers.md", "dev/spec.md", "index.md"], "indexentries": {"add_data() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.add_data", false]], "add_range() (rangedtransformation.builder method)": [[35, "hansken_extraction_plugin.api.transformation.RangedTransformation.Builder.add_range", false]], "add_tracelet() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.add_tracelet", false]], "add_tracelet() (metaextractiontrace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.MetaExtractionTrace.add_tracelet", false]], "add_transformation() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.add_transformation", false]], "add_transformation() (metaextractiontrace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.MetaExtractionTrace.add_transformation", false]], "ascending (direction attribute)": [[32, "hansken_extraction_plugin.api.search_sort_option.Direction.ASCENDING", false]], "author (class in hansken_extraction_plugin.api.plugin_info)": [[30, "hansken_extraction_plugin.api.plugin_info.Author", false]], "author (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.author", false]], "baseextractionplugin (class in hansken_extraction_plugin.api.extraction_plugin)": [[28, "hansken_extraction_plugin.api.extraction_plugin.BaseExtractionPlugin", false]], "build() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.build", false]], "build() (rangedtransformation.builder method)": [[35, "hansken_extraction_plugin.api.transformation.RangedTransformation.Builder.build", false]], "builder() (rangedtransformation static method)": [[35, "hansken_extraction_plugin.api.transformation.RangedTransformation.builder", false]], "bulk_mode (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.bulk_mode", false]], "category (pluginid attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginId.category", false]], "child_builder() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.child_builder", false]], "child_builder() (metaextractiontrace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.MetaExtractionTrace.child_builder", false]], "close() (searchresult method)": [[31, "hansken_extraction_plugin.api.search_result.SearchResult.close", false]], "data_size (datacontext attribute)": [[27, "hansken_extraction_plugin.api.data_context.DataContext.data_size", false]], "data_type (datacontext attribute)": [[27, "hansken_extraction_plugin.api.data_context.DataContext.data_type", false]], "datacontext (class in hansken_extraction_plugin.api.data_context)": [[27, "hansken_extraction_plugin.api.data_context.DataContext", false]], "deferred_iterations (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.deferred_iterations", false]], "deferredextractionplugin (class in hansken_extraction_plugin.api.extraction_plugin)": [[28, "hansken_extraction_plugin.api.extraction_plugin.DeferredExtractionPlugin", false]], "deferredmetaextractionplugin (class in hansken_extraction_plugin.api.extraction_plugin)": [[28, "hansken_extraction_plugin.api.extraction_plugin.DeferredMetaExtractionPlugin", false]], "descending (direction attribute)": [[32, "hansken_extraction_plugin.api.search_sort_option.Direction.DESCENDING", false]], "description (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.description", false]], "direction (class in hansken_extraction_plugin.api.search_sort_option)": [[32, "hansken_extraction_plugin.api.search_sort_option.Direction", false]], "direction() (searchsortoption method)": [[32, "hansken_extraction_plugin.api.search_sort_option.SearchSortOption.direction", false]], "domain (pluginid attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginId.domain", false]], "email (author attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.Author.email", false]], "extractionplugin (class in hansken_extraction_plugin.api.extraction_plugin)": [[28, "hansken_extraction_plugin.api.extraction_plugin.ExtractionPlugin", false]], "extractiontrace (class in hansken_extraction_plugin.api.extraction_trace)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTrace", false]], "extractiontracebuilder (class in hansken_extraction_plugin.api.extraction_trace)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder", false]], "field() (searchsortoption method)": [[32, "hansken_extraction_plugin.api.search_sort_option.SearchSortOption.field", false]], "from_dict() (plugininfo static method)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.from_dict", false]], "generate_label() (transformer method)": [[36, "hansken_extraction_plugin.api.transformer.Transformer.generate_label", false]], "get() (trace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.Trace.get", false]], "hansken_extraction_plugin.api": [[26, "module-hansken_extraction_plugin.api", false]], "hansken_extraction_plugin.api.data_context": [[27, "module-hansken_extraction_plugin.api.data_context", false]], "hansken_extraction_plugin.api.extraction_plugin": [[28, "module-hansken_extraction_plugin.api.extraction_plugin", false]], "hansken_extraction_plugin.api.extraction_trace": [[29, "module-hansken_extraction_plugin.api.extraction_trace", false]], "hansken_extraction_plugin.api.plugin_info": [[30, "module-hansken_extraction_plugin.api.plugin_info", false]], "hansken_extraction_plugin.api.search_result": [[31, "module-hansken_extraction_plugin.api.search_result", false]], "hansken_extraction_plugin.api.search_sort_option": [[32, "module-hansken_extraction_plugin.api.search_sort_option", false]], "hansken_extraction_plugin.api.trace_searcher": [[33, "module-hansken_extraction_plugin.api.trace_searcher", false]], "hansken_extraction_plugin.api.tracelet": [[34, "module-hansken_extraction_plugin.api.tracelet", false]], "hansken_extraction_plugin.api.transformation": [[35, "module-hansken_extraction_plugin.api.transformation", false]], "hansken_extraction_plugin.api.transformer": [[36, "module-hansken_extraction_plugin.api.transformer", false]], "id (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.id", false]], "image (searchscope attribute)": [[33, "hansken_extraction_plugin.api.trace_searcher.SearchScope.image", false]], "length (range attribute)": [[35, "hansken_extraction_plugin.api.transformation.Range.length", false]], "license (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.license", false]], "matcher (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.matcher", false]], "maturity (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.maturity", false]], "maturitylevel (class in hansken_extraction_plugin.api.plugin_info)": [[30, "hansken_extraction_plugin.api.plugin_info.MaturityLevel", false]], "maximum_cpu (pluginresources attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginResources.maximum_cpu", false]], "maximum_memory (pluginresources attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginResources.maximum_memory", false]], "maximum_workers (pluginresources attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginResources.maximum_workers", false]], "metaextractionplugin (class in hansken_extraction_plugin.api.extraction_plugin)": [[28, "hansken_extraction_plugin.api.extraction_plugin.MetaExtractionPlugin", false]], "metaextractiontrace (class in hansken_extraction_plugin.api.extraction_trace)": [[29, "hansken_extraction_plugin.api.extraction_trace.MetaExtractionTrace", false]], "method_name (transformerlabel attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.TransformerLabel.method_name", false]], "module": [[26, "module-hansken_extraction_plugin.api", false], [27, "module-hansken_extraction_plugin.api.data_context", false], [28, "module-hansken_extraction_plugin.api.extraction_plugin", false], [29, "module-hansken_extraction_plugin.api.extraction_trace", false], [30, "module-hansken_extraction_plugin.api.plugin_info", false], [31, "module-hansken_extraction_plugin.api.search_result", false], [32, "module-hansken_extraction_plugin.api.search_sort_option", false], [33, "module-hansken_extraction_plugin.api.trace_searcher", false], [34, "module-hansken_extraction_plugin.api.tracelet", false], [35, "module-hansken_extraction_plugin.api.transformation", false], [36, "module-hansken_extraction_plugin.api.transformer", false]], "name (author attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.Author.name", false]], "name (pluginid attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginId.name", false]], "offset (range attribute)": [[35, "hansken_extraction_plugin.api.transformation.Range.offset", false]], "open() (extractiontrace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTrace.open", false]], "open() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.open", false]], "open() (searchtrace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.SearchTrace.open", false]], "organisation (author attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.Author.organisation", false]], "parameters (transformerlabel attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.TransformerLabel.parameters", false]], "plugin_info() (baseextractionplugin method)": [[28, "hansken_extraction_plugin.api.extraction_plugin.BaseExtractionPlugin.plugin_info", false]], "pluginid (class in hansken_extraction_plugin.api.plugin_info)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginId", false]], "plugininfo (class in hansken_extraction_plugin.api.plugin_info)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo", false]], "pluginresources (class in hansken_extraction_plugin.api.plugin_info)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginResources", false]], "process() (deferredextractionplugin method)": [[28, "hansken_extraction_plugin.api.extraction_plugin.DeferredExtractionPlugin.process", false]], "process() (deferredmetaextractionplugin method)": [[28, "hansken_extraction_plugin.api.extraction_plugin.DeferredMetaExtractionPlugin.process", false]], "process() (extractionplugin method)": [[28, "hansken_extraction_plugin.api.extraction_plugin.ExtractionPlugin.process", false]], "process() (metaextractionplugin method)": [[28, "hansken_extraction_plugin.api.extraction_plugin.MetaExtractionPlugin.process", false]], "production_ready (maturitylevel attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.MaturityLevel.PRODUCTION_READY", false]], "project (searchscope attribute)": [[33, "hansken_extraction_plugin.api.trace_searcher.SearchScope.project", false]], "proof_of_concept (maturitylevel attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.MaturityLevel.PROOF_OF_CONCEPT", false]], "range (class in hansken_extraction_plugin.api.transformation)": [[35, "hansken_extraction_plugin.api.transformation.Range", false]], "rangedtransformation (class in hansken_extraction_plugin.api.transformation)": [[35, "hansken_extraction_plugin.api.transformation.RangedTransformation", false]], "rangedtransformation.builder (class in hansken_extraction_plugin.api.transformation)": [[35, "hansken_extraction_plugin.api.transformation.RangedTransformation.Builder", false]], "ready_for_test (maturitylevel attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.MaturityLevel.READY_FOR_TEST", false]], "resources (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.resources", false]], "return_type (transformerlabel attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.TransformerLabel.return_type", false]], "search() (tracesearcher method)": [[33, "hansken_extraction_plugin.api.trace_searcher.TraceSearcher.search", false]], "searchresult (class in hansken_extraction_plugin.api.search_result)": [[31, "hansken_extraction_plugin.api.search_result.SearchResult", false]], "searchscope (class in hansken_extraction_plugin.api.trace_searcher)": [[33, "hansken_extraction_plugin.api.trace_searcher.SearchScope", false]], "searchsortoption (class in hansken_extraction_plugin.api.search_sort_option)": [[32, "hansken_extraction_plugin.api.search_sort_option.SearchSortOption", false]], "searchtrace (class in hansken_extraction_plugin.api.extraction_trace)": [[29, "hansken_extraction_plugin.api.extraction_trace.SearchTrace", false]], "supported_primitives (transformer attribute)": [[36, "hansken_extraction_plugin.api.transformer.Transformer.supported_primitives", false]], "take() (searchresult method)": [[31, "hansken_extraction_plugin.api.search_result.SearchResult.take", false]], "takeone() (searchresult method)": [[31, "hansken_extraction_plugin.api.search_result.SearchResult.takeone", false]], "total_results() (searchresult method)": [[31, "hansken_extraction_plugin.api.search_result.SearchResult.total_results", false]], "trace (class in hansken_extraction_plugin.api.extraction_trace)": [[29, "hansken_extraction_plugin.api.extraction_trace.Trace", false]], "tracelet (class in hansken_extraction_plugin.api.tracelet)": [[34, "hansken_extraction_plugin.api.tracelet.Tracelet", false]], "tracesearcher (class in hansken_extraction_plugin.api.trace_searcher)": [[33, "hansken_extraction_plugin.api.trace_searcher.TraceSearcher", false]], "transformation (class in hansken_extraction_plugin.api.transformation)": [[35, "hansken_extraction_plugin.api.transformation.Transformation", false]], "transformer (class in hansken_extraction_plugin.api.transformer)": [[36, "hansken_extraction_plugin.api.transformer.Transformer", false]], "transformerlabel (class in hansken_extraction_plugin.api.plugin_info)": [[30, "hansken_extraction_plugin.api.plugin_info.TransformerLabel", false]], "transformers (baseextractionplugin property)": [[28, "hansken_extraction_plugin.api.extraction_plugin.BaseExtractionPlugin.transformers", false]], "transformers (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.transformers", false]], "update() (extractiontracebuilder method)": [[29, "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder.update", false]], "update() (metaextractiontrace method)": [[29, "hansken_extraction_plugin.api.extraction_trace.MetaExtractionTrace.update", false]], "version (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.version", false]], "webpage_url (plugininfo attribute)": [[30, "hansken_extraction_plugin.api.plugin_info.PluginInfo.webpage_url", false]]}, "objects": {"hansken_extraction_plugin": [[26, 0, 0, "-", "api"]], "hansken_extraction_plugin.api": [[27, 0, 0, "-", "data_context"], [28, 0, 0, "-", "extraction_plugin"], [29, 0, 0, "-", "extraction_trace"], [30, 0, 0, "-", "plugin_info"], [31, 0, 0, "-", "search_result"], [32, 0, 0, "-", "search_sort_option"], [33, 0, 0, "-", "trace_searcher"], [34, 0, 0, "-", "tracelet"], [35, 0, 0, "-", "transformation"], [36, 0, 0, "-", "transformer"]], "hansken_extraction_plugin.api.data_context": [[27, 1, 1, "", "DataContext"]], "hansken_extraction_plugin.api.data_context.DataContext": [[27, 2, 1, "", "data_size"], [27, 2, 1, "", "data_type"]], "hansken_extraction_plugin.api.extraction_plugin": [[28, 1, 1, "", "BaseExtractionPlugin"], [28, 1, 1, "", "DeferredExtractionPlugin"], [28, 1, 1, "", "DeferredMetaExtractionPlugin"], [28, 1, 1, "", "ExtractionPlugin"], [28, 1, 1, "", "MetaExtractionPlugin"]], "hansken_extraction_plugin.api.extraction_plugin.BaseExtractionPlugin": [[28, 3, 1, "", "plugin_info"], [28, 4, 1, "", "transformers"]], "hansken_extraction_plugin.api.extraction_plugin.DeferredExtractionPlugin": [[28, 3, 1, "", "process"]], "hansken_extraction_plugin.api.extraction_plugin.DeferredMetaExtractionPlugin": [[28, 3, 1, "", "process"]], "hansken_extraction_plugin.api.extraction_plugin.ExtractionPlugin": [[28, 3, 1, "", "process"]], "hansken_extraction_plugin.api.extraction_plugin.MetaExtractionPlugin": [[28, 3, 1, "", "process"]], "hansken_extraction_plugin.api.extraction_trace": [[29, 1, 1, "", "ExtractionTrace"], [29, 1, 1, "", "ExtractionTraceBuilder"], [29, 1, 1, "", "MetaExtractionTrace"], [29, 1, 1, "", "SearchTrace"], [29, 1, 1, "", "Trace"]], "hansken_extraction_plugin.api.extraction_trace.ExtractionTrace": [[29, 3, 1, "", "open"]], "hansken_extraction_plugin.api.extraction_trace.ExtractionTraceBuilder": [[29, 3, 1, "", "add_data"], [29, 3, 1, "", "add_tracelet"], [29, 3, 1, "", "add_transformation"], [29, 3, 1, "", "build"], [29, 3, 1, "", "child_builder"], [29, 3, 1, "", "open"], [29, 3, 1, "", "update"]], "hansken_extraction_plugin.api.extraction_trace.MetaExtractionTrace": [[29, 3, 1, "", "add_tracelet"], [29, 3, 1, "", "add_transformation"], [29, 3, 1, "", "child_builder"], [29, 3, 1, "", "update"]], "hansken_extraction_plugin.api.extraction_trace.SearchTrace": [[29, 3, 1, "", "open"]], "hansken_extraction_plugin.api.extraction_trace.Trace": [[29, 3, 1, "", "get"]], "hansken_extraction_plugin.api.plugin_info": [[30, 1, 1, "", "Author"], [30, 1, 1, "", "MaturityLevel"], [30, 1, 1, "", "PluginId"], [30, 1, 1, "", "PluginInfo"], [30, 1, 1, "", "PluginResources"], [30, 1, 1, "", "TransformerLabel"]], "hansken_extraction_plugin.api.plugin_info.Author": [[30, 2, 1, "", "email"], [30, 2, 1, "", "name"], [30, 2, 1, "", "organisation"]], "hansken_extraction_plugin.api.plugin_info.MaturityLevel": [[30, 2, 1, "", "PRODUCTION_READY"], [30, 2, 1, "", "PROOF_OF_CONCEPT"], [30, 2, 1, "", "READY_FOR_TEST"]], "hansken_extraction_plugin.api.plugin_info.PluginId": [[30, 2, 1, "", "category"], [30, 2, 1, "", "domain"], [30, 2, 1, "", "name"]], "hansken_extraction_plugin.api.plugin_info.PluginInfo": [[30, 2, 1, "", "author"], [30, 2, 1, "", "bulk_mode"], [30, 2, 1, "", "deferred_iterations"], [30, 2, 1, "", "description"], [30, 3, 1, "", "from_dict"], [30, 2, 1, "", "id"], [30, 2, 1, "", "license"], [30, 2, 1, "", "matcher"], [30, 2, 1, "", "maturity"], [30, 2, 1, "", "resources"], [30, 2, 1, "", "transformers"], [30, 2, 1, "", "version"], [30, 2, 1, "", "webpage_url"]], "hansken_extraction_plugin.api.plugin_info.PluginResources": [[30, 2, 1, "", "maximum_cpu"], [30, 2, 1, "", "maximum_memory"], [30, 2, 1, "", "maximum_workers"]], "hansken_extraction_plugin.api.plugin_info.TransformerLabel": [[30, 2, 1, "", "method_name"], [30, 2, 1, "", "parameters"], [30, 2, 1, "", "return_type"]], "hansken_extraction_plugin.api.search_result": [[31, 1, 1, "", "SearchResult"]], "hansken_extraction_plugin.api.search_result.SearchResult": [[31, 3, 1, "", "close"], [31, 3, 1, "", "take"], [31, 3, 1, "", "takeone"], [31, 3, 1, "", "total_results"]], "hansken_extraction_plugin.api.search_sort_option": [[32, 1, 1, "", "Direction"], [32, 1, 1, "", "SearchSortOption"]], "hansken_extraction_plugin.api.search_sort_option.Direction": [[32, 2, 1, "", "ASCENDING"], [32, 2, 1, "", "DESCENDING"]], "hansken_extraction_plugin.api.search_sort_option.SearchSortOption": [[32, 3, 1, "", "direction"], [32, 3, 1, "", "field"]], "hansken_extraction_plugin.api.trace_searcher": [[33, 1, 1, "", "SearchScope"], [33, 1, 1, "", "TraceSearcher"]], "hansken_extraction_plugin.api.trace_searcher.SearchScope": [[33, 2, 1, "", "image"], [33, 2, 1, "", "project"]], "hansken_extraction_plugin.api.trace_searcher.TraceSearcher": [[33, 3, 1, "", "search"]], "hansken_extraction_plugin.api.tracelet": [[34, 1, 1, "", "Tracelet"]], "hansken_extraction_plugin.api.transformation": [[35, 1, 1, "", "Range"], [35, 1, 1, "", "RangedTransformation"], [35, 1, 1, "", "Transformation"]], "hansken_extraction_plugin.api.transformation.Range": [[35, 2, 1, "", "length"], [35, 2, 1, "", "offset"]], "hansken_extraction_plugin.api.transformation.RangedTransformation": [[35, 1, 1, "", "Builder"], [35, 3, 1, "", "builder"]], "hansken_extraction_plugin.api.transformation.RangedTransformation.Builder": [[35, 3, 1, "", "add_range"], [35, 3, 1, "", "build"]], "hansken_extraction_plugin.api.transformer": [[36, 1, 1, "", "Transformer"]], "hansken_extraction_plugin.api.transformer.Transformer": [[36, 3, 1, "", "generate_label"], [36, 2, 1, "", "supported_primitives"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"], "4": ["py", "property", "Python property"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:attribute", "3": "py:method", "4": "py:property"}, "terms": {"": [0, 3, 4, 7, 9, 12, 13, 18, 23, 30, 35, 37, 40, 43, 44, 45], "0": [3, 7, 12, 13, 15, 19, 21, 22, 23, 24, 29, 30, 33, 38, 39, 43], "00": 13, "000": 37, "0000": 40, "03": [18, 37, 40], "09": [13, 18, 37], "1": [3, 7, 11, 12, 13, 19, 22, 23, 30, 38, 41, 43], "10": [7, 23, 39, 42, 43], "100": [31, 37], "1000": [8, 18, 23, 37, 43], "1000000": 7, "1024": 37, "11": [7, 22, 39, 42, 44], "11jdk": 39, "12": [9, 37, 40], "1234": 23, "13414": 0, "13554": 0, "13560": 0, "13577": 0, "13578": 0, "13579": 0, "13580": 0, "13581": 0, "13643": 0, "13648": 0, "13650": 0, "13651": 0, "13655": 0, "13656": 0, "13658": 0, "13660": 0, "13663": 0, "13668": 0, "13676": 0, "13705": 0, "13706": 0, "13709": 0, "13713": 0, "13714": 0, "13733": 0, "13756": 0, "13761": 0, "13769": 0, "13771": 0, "13772": 0, "13773": 0, "13774": 0, "13775": 0, "13776": 0, "13777": 0, "13784": 0, "13798": 0, "13799": 0, "13800": 0, "13801": 0, "13809": 0, "13810": 0, "13922": 0, "13966": 0, "14008": 0, "14009": 0, "14010": 0, "14011": 0, "14030": 0, "14031": 0, "14035": 0, "14037": 0, "14044": 0, "14060": 0, "14073": 0, "14074": 0, "14079": 0, "14083": 0, "14090": 0, "14092": 0, "14104": 0, "14122": 0, "14128": 0, "14130": 0, "14131": 0, "14134": 0, "14135": 0, "14161": 0, "14216": 0, "14234": 0, "14283": 0, "14286": 0, "14314": 0, "14318": 0, "14531": 0, "14547": 0, "14580": 0, "14581": 0, "14582": 0, "14586": 0, "14591": 0, "14618": 0, "14619": 0, "14632": 0, "14635": 0, "14660": 0, "14703": 0, "14704": 0, "14720": 0, "14737": 0, "14738": 0, "14739": 0, "14755": 0, "14763": 0, "14777": 0, "14787": 0, "14793": 0, "14820": 0, "14841": 0, "14844": 0, "14867": 0, "14879": 0, "14923": 0, "15": [7, 39], "15015": 0, "15029": 0, "15034": 0, "15035": 0, "15042": 0, "15048": 0, "15059": 0, "15139": 0, "15186": 0, "15187": 0, "15189": 0, "15192": 0, "15193": 0, "15231": 0, "15232": 0, "15233": 0, "15236": 0, "15237": 0, "15274": 0, "15276": 0, "15282": 0, "15288": 0, "15294": 0, "15338": 0, "15353": 0, "15365": 0, "15370": 0, "15390": 0, "15391": 0, "15392": 0, "15393": 0, "15466": 0, "15491": 0, "15495": 0, "15498": 0, "15502": 0, "15505": 0, "15511": 0, "15512": 0, "15514": 0, "15515": 0, "15520": 0, "15527": 0, "15541": 0, "15542": 0, "15562": 0, "15572": 0, "15588": 0, "15589": 0, "15607": 0, "15632": 0, "15641": 0, "15650": 0, "15651": 0, "15653": 0, "15656": 0, "15668": 0, "15683": 0, "15711": 0, "15743": 0, "15745": 0, "15765": 0, "15766": 0, "15770": 0, "15771": 0, "15772": 0, "15773": 0, "15790": 0, "15801": 0, "15846": 0, "15857": 0, "15858": 0, "15871": 0, "15913": 0, "15961": 0, "15964": 0, "15993": 0, "16": 40, "16001": 0, "16012": 0, "16037": 0, "16038": 0, "16044": 0, "16048": 0, "16090": 0, "16095": 0, "16105": 0, "16111": 0, "16115": 0, "16116": 0, "16118": 0, "16128": 0, "16139": 0, "16160": 0, "16191": 0, "16229": 0, "16238": 0, "16257": 0, "16258": 0, "16268": 0, "1630510809": 43, "16403": 0, "16489": 0, "16558": 0, "16574": 0, "16575": 0, "16576": 0, "16632": 0, "16634": 0, "16638": 0, "16704": 0, "16705": 0, "16707": 0, "16725": 0, "16753": 0, "16756": 0, "16764": 0, "16781": 0, "16900": 0, "16901": 0, "16905": 0, "16908": 0, "17": 39, "17064": 0, "17138": 0, "17141": 0, "17151": 0, "17178": 0, "17191": 0, "17194": 0, "17196": 0, "17203": 0, "17214": 0, "17264": 0, "17265": 0, "17273": 0, "17274": 0, "17276": 0, "17277": 0, "17278": 0, "17460": 0, "17502": 0, "17556": 0, "17636": 0, "17672": 0, "17675": 0, "17692": 0, "17742": 0, "17786": 0, "18": [0, 13], "18400": 0, "18517": 0, "18673": 0, "18677": 0, "18830": 0, "18883": 0, "18907": 0, "18915": 0, "18982": 0, "19064": 0, "19065": 0, "19076": 0, "19148": 0, "19151": 0, "19179": 0, "19435": 0, "19436": 0, "19447": 0, "19448": 0, "19759": 0, "19954": 0, "1st": 0, "2": [7, 13, 15, 22, 23, 30, 38, 39, 43], "20": [11, 13, 18, 19, 23, 30, 37, 38, 39, 43], "2000": 8, "2001": 22, "20127": 0, "20128": 0, "2021": [0, 13, 40], "2022": 0, "20389": 0, "20410": 0, "2048": 37, "20552": 0, "20733": 0, "20735": 0, "20812": 0, "20813": 0, "20814": 0, "20824": 0, "20852": 0, "20938": 0, "20962": 0, "20t": 23, "21": 0, "21073": 0, "21096": 0, "21097": 0, "21104": 0, "21130": 0, "21132": 0, "21135": 0, "21217": 0, "21218": 0, "21219": 0, "21220": 0, "21221": 0, "21222": 0, "21247": 0, "21385": 0, "21410": 0, "21411": 0, "21436": 0, "21486": 0, "21495": 0, "21540": 0, "21571": 0, "21582": 0, "21684": 0, "21689": 0, "21694": 0, "21803": 0, "21816": 0, "21817": 0, "21818": 0, "21819": 0, "21840": 0, "21942": 0, "22002": 0, "22172": 0, "22279": 0, "22500": 0, "22505": 0, "22634": 0, "22635": 0, "22636": 0, "22637": 0, "22638": 0, "22639": 0, "22647": 0, "22724": 0, "22728": 0, "22730": 0, "22752": 0, "22755": 0, "22788": 0, "22900": 0, "23": 39, "23051": 0, "23258": 0, "23330": 0, "23399": 0, "23401": 0, "23402": 0, "23403": 0, "23424": 0, "240290": 40, "240753": 40, "2g": 0, "3": [7, 19, 23, 24, 39, 41, 42], "30": [18, 23, 37, 43], "3000": 8, "32": 23, "32c": 23, "34": [18, 37], "344248": 40, "344450": 40, "3509": 0, "3d73a5552693": 40, "4": [3, 22, 24, 38, 39], "4096": 37, "40c3": 40, "423245": 40, "44228": 0, "45": 40, "46": 3, "48": [0, 40], "4bin": 39, "5": [7, 23, 30, 38, 41, 43], "50": [7, 11, 18, 23, 37, 43], "5005": 19, "53": 40, "54": 40, "54197e67": 40, "5678": 38, "59": 40, "5f": [18, 23], "5p": 23, "64": 0, "681": 13, "6m": 0, "7": [13, 38], "774": [18, 37], "79": 12, "799668": 40, "8": [13, 22, 23, 29, 43], "8001": 21, "805538": 40, "8080": [37, 41], "8135": 40, "859299": 40, "8999": [0, 3, 24, 44, 46], "8f": [18, 23], "9": 13, "93f1": 40, "A": [4, 6, 7, 10, 11, 12, 13, 18, 29, 30, 31, 34, 35, 36, 37, 38, 40, 41, 44, 45], "AND": 7, "And": 7, "As": [7, 37], "At": [4, 24, 38, 40], "Be": [0, 3, 23, 37, 39, 43], "But": 7, "By": [5, 7, 18, 37, 43, 44, 45], "For": [0, 4, 6, 7, 9, 12, 13, 15, 18, 19, 21, 22, 23, 24, 34, 37, 39, 41, 43, 45, 47], "If": [1, 3, 4, 6, 7, 9, 10, 11, 12, 13, 15, 18, 19, 21, 23, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47], "In": [0, 7, 13, 15, 16, 19, 23, 37, 38, 39, 43, 44], "It": [3, 6, 7, 12, 13, 15, 18, 21, 23, 30, 36, 37, 39, 40, 41, 43], "NOT": [3, 7, 11], "Not": [7, 41], "OR": 7, "One": [0, 2, 16, 30, 44], "Or": 7, "The": [0, 5, 6, 7, 8, 9, 10, 11, 13, 15, 16, 18, 19, 21, 22, 23, 24, 28, 29, 30, 32, 33, 34, 36, 37, 38, 39, 40, 41, 43, 44, 45, 46], "Then": [13, 24, 37, 39], "There": [7, 12, 24, 38, 40, 43], "These": [0, 6, 7, 10, 11, 12, 13, 18, 23, 37, 40], "To": [4, 6, 7, 8, 12, 13, 16, 18, 19, 21, 23, 24, 37, 38, 39, 40, 41, 43, 44, 45], "With": [13, 16, 19, 38, 40], "_": 12, "__": 12, "__main__": [40, 44], "__name__": [40, 43, 44], "_agent": 41, "_arg": 41, "_build": 0, "_client": 24, "_direct": 32, "_field": 32, "_imag": 41, "_name": 41, "_server": 24, "_test": 0, "_test_validate_standalon": 44, "abc": [28, 29, 31, 35], "abil": [0, 12], "abl": [0, 4, 12, 16, 18, 23, 29, 37, 39, 43], "abort": [13, 37], "about": [1, 4, 6, 7, 11, 13, 23, 28, 30, 43, 46], "abov": [7, 12, 23, 39, 44, 45, 47], "absenc": 10, "absolut": 7, "abstract": [28, 29, 31, 33], "accept": [0, 7, 13, 23, 38, 43, 44, 46], "access": [1, 13, 16, 18, 23, 28, 37, 39, 43, 47], "accommod": 0, "accomplish": 4, "accord": 7, "accordingli": [9, 37], "account": 15, "achiev": [7, 37], "acknowledg": 40, "action": 10, "activ": 7, "actual": [0, 5, 7, 11, 12, 13, 16, 18, 30, 37, 39, 43, 45], "ad": [0, 4, 7, 11, 12, 13, 16, 18, 21, 29, 37, 38, 41, 44], "adapt": [0, 9, 38], "add": [0, 6, 7, 12, 15, 16, 18, 19, 23, 29, 35, 37, 38, 39, 41, 43], "add_data": [0, 29], "add_rang": [35, 37, 43], "add_tracelet": [29, 37, 43], "add_transform": [29, 37, 43], "addit": [0, 11, 12, 19, 37, 38, 39, 41, 43], "addrang": [18, 23], "address": [19, 37], "addtracelet": [18, 23], "adher": [36, 45], "adipisc": 12, "adjust": 0, "administr": [23, 39, 43], "adob": 13, "advanc": [3, 12, 25, 37, 39], "advantag": [19, 38, 41, 44], "advic": 41, "advis": 3, "after": [0, 4, 7, 11, 15, 19, 29, 37, 38, 41], "afteral": 24, "again": [4, 7], "against": [7, 10, 12, 24, 44], "agent": [0, 21, 41], "agentlib": 19, "ahead": 29, "aid": [39, 40], "aim": [18, 37], "aio": [0, 2], "algorithm": 16, "all": [0, 2, 4, 6, 7, 11, 12, 13, 15, 16, 18, 22, 23, 24, 28, 29, 30, 37, 39, 41, 42, 43, 44, 45, 47], "allow": [0, 7, 8, 11, 12, 13, 18, 19, 23, 28, 30, 36, 37, 39, 41, 43, 45, 46], "along": 0, "alreadi": [0, 7, 19, 23, 29, 40, 43, 45], "also": [0, 3, 6, 7, 12, 13, 18, 19, 21, 28, 30, 36, 37, 38, 39, 41, 43, 44], "alt": 39, "altern": [18, 21, 22, 23, 37, 44], "although": [4, 5, 18, 37], "alwai": [0, 7, 11, 12, 13, 23, 43, 45, 46], "amet": 12, "among": 30, "an": [0, 3, 5, 9, 10, 12, 13, 15, 16, 17, 18, 21, 23, 24, 25, 29, 30, 31, 36, 37, 40, 41, 42, 43, 44, 45, 46], "analysi": [0, 36], "analyz": 0, "anatomi": [0, 2], "ani": [4, 7, 12, 13, 29, 34, 43, 45, 47], "ann": 43, "annot": 45, "anoth": [9, 11, 13, 23, 41, 43, 44], "another_str": [37, 43], "anotheremail": 34, "answer": 7, "antlr": 0, "anumb": 23, "anymor": 37, "anynam": 43, "apach": [0, 15, 18, 22, 37], "apart": 0, "api": [0, 13, 15, 16, 17, 20, 23, 24, 40, 43, 44, 45, 46, 47], "app": 41, "appdata": [18, 37], "appear": 39, "append": [3, 23], "appenderref": 23, "appli": [5, 7, 10, 13, 16, 21, 36, 44, 46], "applic": [0, 7, 13, 19, 23, 29, 41, 43], "approach": 41, "appropri": 44, "apt": 39, "ar": [0, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 18, 19, 21, 22, 23, 24, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47], "arbitrari": [8, 10], "archiv": [5, 10, 13, 18, 37], "arg": [0, 37, 41, 45], "arg_1": 46, "arg_2": 46, "argument": [0, 18, 21, 23, 30, 37, 38, 40, 41, 43, 44, 45], "around": [0, 7], "arrai": [13, 23, 46], "arrayoutofboundsexcept": 0, "art": [19, 38], "artifact": 0, "artifactid": [22, 24], "asc": [18, 23], "ascend": 32, "asinputstream": 23, "ask": [30, 39, 47], "aspect": 16, "assign": 30, "assist": 15, "associ": 4, "assum": [24, 37, 43, 44, 45], "attach": [19, 23, 29, 38, 43], "attempt": 0, "attribut": [4, 32], "audio": [16, 37], "auth": 40, "author": [0, 4, 18, 19, 30, 37, 38, 40, 46], "auto": 0, "autom": [0, 21, 22, 39, 41], "automat": [9, 12, 18, 37, 44, 45], "autosc": [2, 4], "autoscal": 9, "avail": [0, 3, 4, 5, 6, 7, 8, 13, 18, 21, 23, 29, 31, 37, 38, 43, 44, 45, 46], "avoid": 0, "aw": 7, "awesomeplugin": 0, "b": [7, 12, 13, 37, 39, 43, 47], "back": 29, "backslash": 7, "backward": [0, 18, 37], "bad": 0, "bake": 19, "balanc": [0, 37], "bar": [7, 40], "bare": [7, 30], "base": [0, 7, 9, 10, 12, 13, 22, 23, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 43], "baseextractionplugin": [28, 36, 45], "basenam": 12, "basi": 22, "basic": [0, 7, 40], "batch": [0, 31, 37], "batchedsearchresult": 37, "baz": 7, "becaus": [0, 5, 7, 11, 19, 23, 37, 38, 43], "becom": 7, "been": [0, 7, 12, 18, 21, 37, 39, 40, 41, 44], "befor": [0, 3, 6, 7, 13, 16, 21, 29, 37, 40, 45], "beforeal": 24, "beforehand": 7, "begin": [23, 38], "behav": 7, "behaviour": 3, "being": [0, 7, 12, 13, 18, 19, 23, 27, 28, 29, 33, 37, 43, 45], "belong": 13, "below": [7, 10, 12, 13, 18, 19, 24, 37, 38, 39, 44, 45], "benefit": 16, "best": [7, 37], "beta": [15, 18, 37], "better": [0, 18, 37], "between": [0, 4, 7, 12, 24, 41, 46], "beyond": 0, "big": 37, "bin": 39, "binari": [13, 36], "bind": 23, "bit": [4, 19, 38, 39], "bla": 7, "blob": 5, "block": [0, 38], "bodi": 45, "boilerpl": 18, "bool": [13, 30, 36, 45], "boolean": [12, 13, 19, 24, 36], "both": [7, 12, 13, 14, 18, 23, 29, 37, 41], "bottom": 40, "bracket": 7, "break": [18, 37], "breakpoint": 3, "briefli": 41, "broad": 7, "broke": 0, "broken": 0, "browser": 6, "buffer": [0, 29, 37], "buffer_s": [0, 29, 37], "bufferedread": [0, 29, 43], "bufferedwrit": 29, "bug": [0, 1, 7, 19, 38], "bugfix": 0, "build": [0, 12, 18, 21, 22, 23, 24, 29, 30, 35, 39, 41, 42, 43, 44], "build_ag": 41, "build_agent_arg": 41, "build_plugin": [0, 30, 37], "build_plugin_ci": 0, "buildag": 41, "buildah": 41, "buildarg": 21, "builder": [18, 23, 29, 35, 37, 43], "builderfor": [18, 23], "built": [6, 12, 19, 29, 37, 38, 41], "bulk": 46, "bulk_mod": [30, 37, 43], "bulkmod": [0, 18, 23], "bundl": 13, "busi": [0, 1, 15], "button": [39, 40], "byte": [0, 7, 13, 23, 29, 35, 36, 37, 43, 45], "bytearrai": [5, 13, 18, 37, 45], "c": [7, 12, 39], "cach": [0, 29], "caffein": 0, "calcul": 7, "call": [0, 4, 6, 7, 12, 13, 18, 23, 28, 31, 33, 36, 37, 38, 43, 44, 46], "callback": 0, "caller": 45, "can": [0, 1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 16, 18, 19, 21, 22, 23, 24, 26, 28, 29, 30, 31, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], "cancel": 13, "candid": 13, "cannot": [7, 41], "capabl": [0, 4], "car": 45, "cardin": 13, "care": [3, 7, 23, 41, 43], "carefulli": 37, "cartoon": [0, 47], "carv": 10, "case": [0, 5, 7, 11, 12, 13, 15, 16, 18, 23, 37, 39, 41, 44], "cat": [18, 37], "categor": 10, "categori": [0, 10, 13, 18, 30, 37], "caught": 0, "caus": [0, 12, 37, 44], "cd": [41, 44], "central": [0, 18, 22], "certain": [6, 11, 18, 37], "certif": 39, "chang": [0, 12, 18, 23, 43], "changelog": [17, 25, 47], "channel": [1, 39], "chapter": 6, "char": 7, "charact": [7, 10, 18, 37], "chat": [1, 18, 21, 37, 41, 43, 44, 47], "chat_plugin": 44, "chatconvers": 43, "chatmessag": [7, 43], "chatplugin": [37, 44], "check": [0, 4, 6, 7, 12, 13, 39], "checkbox": 6, "checklist": 7, "checkstyl": 0, "child": [0, 4, 5, 11, 12, 18, 23, 29, 37], "child_build": [29, 37, 43], "childnumb": 13, "children": [0, 12, 13], "childtrac": 43, "choic": [7, 39], "choos": [6, 11, 39, 41, 45], "choose_your_artifactid_her": 22, "chunk": [0, 43], "ci": 41, "circumst": 12, "class": [0, 12, 13, 18, 19, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45], "classic": 10, "classif": [18, 23, 37], "classifi": 10, "cleanup": 0, "clear": [0, 10], "clearli": 19, "click": [13, 39], "client": [0, 12, 13, 18, 24, 36, 37, 38, 40, 45], "close": [23, 24, 31, 37, 39, 43], "cloud": 30, "cluster": [8, 9, 15, 19, 38], "cmd": 39, "code": [0, 6, 8, 11, 12, 13, 15, 17, 18, 24, 25, 37, 39, 44, 46, 47], "collect": [12, 13, 30, 34], "colon": 7, "column": 10, "com": 34, "combin": [10, 16, 18, 37], "come": [18, 37, 41], "comfort": 39, "comma": 0, "command": [0, 6, 18, 19, 21, 37, 38, 39, 43, 44], "comment": 0, "commit": 0, "common": [0, 7, 23, 39], "commun": [0, 1, 4, 8, 16, 18, 24, 38, 46, 47], "compact": 7, "compar": [0, 12, 40, 44], "compat": [0, 15, 18, 31, 37], "compil": [7, 46], "complet": [0, 39], "complex": 7, "compli": [12, 13], "compliant": 8, "complic": 39, "compon": 12, "compos": 13, "comput": [8, 10, 23, 43], "concept": [0, 7, 47], "concurr": [0, 3, 18, 23, 30, 43], "condit": 7, "confid": [18, 23, 37, 43], "configur": [0, 18, 21, 23, 37, 39, 41, 43], "conflict": 0, "conform": 46, "congratul": 39, "connect": [0, 19, 37, 41], "consectetur": 12, "consequ": 12, "consid": [15, 47], "consist": [0, 10, 11, 12, 23, 30, 32, 35, 43], "consol": [19, 23, 38, 39], "construct": 36, "consum": [0, 7, 18], "contact": [15, 23, 39, 43, 46, 47], "contain": [0, 6, 7, 10, 12, 13, 15, 16, 18, 19, 21, 23, 24, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 40, 41, 42, 43, 45, 46], "containerfil": 41, "containsinord": 0, "content": [7, 10, 18, 37, 40], "context": [0, 7, 18, 23, 27, 33, 37, 43], "continu": 39, "contrarili": 7, "contribut": 1, "control": [0, 7, 37], "conveni": 18, "convent": [0, 2, 18, 37, 46], "convert": [29, 36, 45], "convieni": 0, "cool": 39, "copi": [0, 41], "core": [7, 18, 23, 30, 37, 43, 46], "correct": [0, 7, 24, 37, 40, 43], "correctli": [0, 23, 39, 41], "correspond": 12, "cosin": 13, "could": [0, 7, 13, 16, 37, 45], "count": [0, 7, 13, 33, 37], "coupl": [7, 29], "cours": [7, 9], "cpu": [0, 7, 9, 18, 23, 30, 37, 43], "crash": [0, 7], "creat": [0, 4, 5, 9, 10, 11, 13, 16, 18, 23, 24, 29, 30, 37, 38, 43, 44, 45, 47], "createdon": 13, "criteria": 7, "crypto": 16, "csv": 7, "cumul": 13, "curl": 0, "currenc": 16, "current": [0, 3, 5, 7, 11, 12, 13, 18, 19, 23, 32, 35, 37, 38, 40, 41, 43, 46], "custom": 40, "cutoff": 7, "cve": 0, "cycl": 40, "d": [12, 18, 23], "dai": 7, "dap": 38, "dash": 41, "data": [0, 2, 4, 10, 11, 16, 18, 19, 27, 28, 29, 30, 35, 37, 38, 40, 44], "data_context": [28, 37, 43, 44, 45], "data_s": [27, 37], "data_typ": [27, 29, 37, 43], "databas": [7, 10], "dataclass": 0, "datacontext": [0, 18, 23, 27, 28, 37], "dataset": 12, "datastream": [0, 13, 18, 23, 28, 29, 37, 43], "datastream_typ": 43, "datastreamtyp": 13, "datatransform": 0, "datatransformationsplugin": 24, "datatyp": [0, 7, 11, 18, 19, 23, 37, 38, 43], "date": [13, 36], "datetim": [0, 13, 36, 43, 45], "dd": 23, "ddocker": 21, "de": [18, 37], "deal": [7, 43], "debug": [0, 2, 17, 25, 39, 43, 44, 45], "debugextractionplugintool": [0, 3], "debugg": [3, 19, 38], "debugge": 19, "declar": [0, 37], "decod": 13, "decor": [0, 28, 45], "decrypt": [7, 13, 18], "dedic": 0, "deeper": 4, "def": [37, 43, 44, 45], "default": [0, 3, 8, 9, 11, 18, 19, 23, 28, 29, 37, 39, 41, 43, 44, 46], "default_buffer_s": 0, "defer": [0, 18, 30, 37, 46], "deferred_iter": 30, "deferredexampl": 12, "deferredexamplesearch": 12, "deferredextractionplugin": [3, 23, 28, 43], "deferredextractioplugin": [18, 37], "deferrediter": 11, "deferredmetaextractionplugin": [0, 28, 43], "deferredmetaplugin": 43, "deferredplugin": 43, "deferredpluginnam": 12, "defin": [5, 6, 7, 12, 13, 18, 32, 37, 43, 44, 45, 46], "definit": [0, 27, 30, 33, 34, 35, 46], "deliber": 12, "demand": [16, 25, 36, 39], "demoapp": 43, "demonstr": [23, 39, 43], "depend": [0, 4, 6, 7, 9, 12, 22, 37, 39, 40, 42, 44], "deploi": [0, 39, 42], "deprec": [0, 18, 37], "depth": [12, 29], "deriv": [7, 10, 13, 28, 45], "descend": 32, "describ": [0, 4, 5, 8, 10, 12, 13, 18, 19, 21, 23, 28, 30, 33, 35, 37, 38, 39, 41, 44, 46, 47], "descript": [4, 10, 13, 18, 30, 37, 46], "descriptor": 12, "deseri": 0, "design": [7, 8, 16], "desir": [0, 23, 37], "destruct": 24, "detail": [0, 4, 10, 13, 15, 16, 18, 23, 37, 39, 43, 44], "detect": [10, 13, 37, 39], "determin": [0, 4], "dev": [0, 7, 18, 37], "develop": [0, 1, 4, 7, 10, 11, 18, 37, 38, 39, 40, 41, 46], "dialog": [6, 40], "dict": [0, 13, 29, 30], "dictionari": [12, 30], "did": [0, 7], "didn": 0, "differ": [0, 3, 4, 7, 10, 11, 12, 13, 18, 26, 28, 29, 34, 37, 39, 41], "difficult": 7, "digest": 10, "digit": 16, "dimension": 13, "dir": 0, "direct": [13, 23, 32, 33, 37, 43], "directli": [0, 24, 33, 37, 43, 44], "directori": [0, 37, 41, 44], "disabl": [3, 37], "disallow": 0, "disconnect": 0, "discord": [1, 39, 47], "discov": [0, 45], "discuss": [7, 12, 15], "disk": 16, "displai": [13, 19, 38], "distanc": 13, "distinct": [19, 38], "distribut": [0, 15, 18, 22, 46], "dive": 4, "do": [6, 12, 13, 15, 23, 24, 30, 37, 39, 43], "doc": [0, 37, 39], "docker": [0, 4, 6, 18, 21, 22, 24, 30, 37, 41, 42, 45], "docker_arg": [37, 41], "docker_file_directori": [37, 41], "docker_host": 21, "docker_imag": 44, "docker_image_nam": [37, 41], "dockerfil": [41, 43], "document": [0, 7, 10, 12, 13, 16, 18, 37, 40], "documentplugin": 7, "docutil": 0, "doe": [0, 13, 15, 21, 29, 30, 37, 41, 43, 45], "doesn": [7, 12, 13], "dolor": 12, "domain": [0, 6, 10, 18, 30, 37], "don": [0, 1, 7, 12, 13, 15, 24, 37, 39, 46, 47], "done": [4, 6, 7, 9, 12, 18, 23, 24, 37, 39, 43], "doubl": [0, 12, 13, 18], "down": [9, 37], "downgrad": 0, "download": 0, "downsid": 41, "drop": 37, "dropbox": [18, 37], "dt_socket": 19, "due": [0, 12], "dump": [37, 43], "dure": [0, 3, 4, 7, 8, 12, 13, 15, 29, 36, 40, 46], "dynam": [28, 30, 36], "e": [0, 7, 10, 16, 18, 19, 21, 23, 29, 30, 37, 41, 44, 45], "each": [4, 5, 7, 8, 9, 10, 12, 13, 18, 24, 37, 39], "earlier": [18, 37], "easi": [16, 23, 40], "easier": 44, "easiest": 7, "easili": [19, 38, 45], "edg": 7, "edit": 39, "effect": [7, 18, 37], "effici": [18, 23, 37, 43], "effort": 15, "either": [0, 7, 18, 23, 29, 33, 37, 41, 43, 44], "elabor": 7, "elasticsearch": [7, 37], "element": [7, 13, 16], "elit": 12, "elsewher": 7, "email": [7, 30, 46], "emailaddress": 34, "embed": [13, 18, 19, 23, 37, 46], "embeddedextractionpluginflit": [19, 24], "eminjenv": [15, 24], "empti": [7, 16], "enabl": [0, 3, 8, 15, 16, 18, 19, 23, 37, 38, 39, 40, 43], "encod": [7, 22, 23, 29, 37, 43], "encourag": 16, "encrypt": 7, "end": [4, 24, 30, 37, 39], "endpoint": [6, 13, 40, 45], "enforc": 0, "engin": 16, "enhanc": 0, "enough": [11, 23, 43, 44], "enrich": 0, "ensur": [0, 8, 23], "enter": [39, 40], "entir": 12, "entri": [5, 13, 16, 18, 37], "entrypoint": 46, "enum": [30, 32, 33, 37], "enumer": 32, "environ": [0, 18, 19, 21, 23, 37, 39, 40, 43, 46], "eof": 0, "ep": [0, 13], "equal": [0, 7], "equival": 30, "erron": 13, "error": [0, 13, 19, 29, 37, 38], "escap": [0, 7, 18, 19, 37, 38], "especi": [7, 37], "etc": [7, 23, 29], "euclidean": 13, "even": [7, 43], "eventu": 37, "everi": [3, 4, 7, 11, 12, 13, 28, 37, 45], "everyth": [6, 15, 39], "evid": [13, 43], "exact": 7, "exactli": [12, 40], "exampl": [0, 5, 6, 11, 12, 13, 15, 16, 18, 19, 21, 23, 29, 34, 37, 38, 41, 43, 44, 45, 47], "example1": 12, "example2": 12, "exampledef": 23, "exampleplugin": 23, "exampletool": 45, "excel": 39, "except": [0, 7, 24, 29, 41, 45], "exclud": 0, "execut": [0, 8, 11, 13, 18, 25, 36, 37, 38, 39, 40, 44], "execute_transform": [0, 37, 44], "exhaust": [31, 43], "exist": [0, 7, 11, 13, 29, 43], "exit": [0, 12], "expand": [0, 4], "expect": [0, 6, 12, 16, 39, 43, 46], "experiment": 0, "expert": [13, 40], "expertui": 40, "explain": [7, 12, 40], "explan": [0, 7, 10], "explicit": 37, "explicitli": [0, 18, 29, 37], "explictli": 43, "export": [21, 41], "expos": [0, 36], "express": [7, 40], "extend": [0, 12, 19, 23, 24, 41], "extens": [12, 13, 18, 23, 37, 43], "extern": [0, 9, 37, 42, 47], "extra": [0, 7, 21], "extract": [0, 1, 2, 3, 5, 7, 8, 9, 10, 14, 16, 17, 18, 20, 21, 22, 24, 25, 26, 28, 29, 30, 36, 37, 41, 42, 44, 45], "extraction_context": 37, "extraction_plugin": [37, 40, 44, 45], "extraction_plugin_runn": 40, "extraction_plugin_serv": 0, "extraction_trac": 37, "extractioncontext": [0, 18, 23, 37], "extractionplugin": [0, 18, 19, 23, 24, 28, 37, 44, 45], "extractionpluginbuild": 0, "extractionplugincli": [0, 24], "extractionpluginexcept": 12, "extractionpluginflit": [0, 19], "extractionpluginserv": [0, 24], "extractionpluginservic": 46, "extractionserv": 24, "extractiontrac": [28, 29, 37, 43], "extractiontracebuild": 29, "extrat": 12, "extrem": 7, "f": [19, 38, 43], "f12": 39, "face": 13, "facet": 16, "factor": 7, "factori": 30, "fail": [0, 12, 13, 24, 37, 39, 43], "failur": 0, "fals": [24, 44, 46], "faq": [0, 47], "far": 7, "fast": [7, 37], "faster": [15, 40], "faucibu": 12, "featur": [1, 3, 6, 7, 11], "feed": 44, "feel": [1, 15, 39], "few": [3, 13, 34, 39, 40], "field": [0, 4, 10, 12, 18, 32, 33, 37, 46], "figur": [5, 13], "file": [0, 5, 7, 10, 12, 13, 15, 16, 18, 19, 23, 24, 29, 37, 38, 43, 44], "file_nam": 43, "filenam": 7, "filenotfounderror": 0, "filesystem": 10, "filetyp": [7, 13, 37, 43], "fill": 1, "final": [18, 23, 24], "find": [1, 6, 7, 13, 15, 16, 19, 23, 38, 40, 41, 43], "finish": [7, 12, 39], "fiod": 10, "firefli": 13, "firewal": 38, "first": [0, 6, 12, 13, 15, 29, 31, 37, 38, 39, 41], "first_100": 31, "firstnam": 34, "five": 12, "fix": [0, 13, 37], "flag": [37, 38, 41], "flaki": 0, "flexibl": 7, "flexibli": 15, "flit": [0, 12, 19, 24, 44], "flitsutil": 24, "float": [0, 13, 18, 30, 36, 37, 45], "flood": 0, "flow": [0, 37], "flush": [0, 29, 37], "folder": [0, 12, 23, 24, 39, 40, 46], "follow": [0, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 37, 38, 39, 40, 41, 43, 44, 45, 46], "foo": 7, "forens": [16, 40], "forget": [7, 37], "form": [1, 10, 13, 15], "format": [0, 10, 16, 18, 23], "forward": [0, 10, 43], "found": [1, 11, 12, 13, 14, 18, 19, 23, 26, 33, 37, 38, 40, 44, 46], "four": [11, 23, 43], "fraction": 30, "fragment": 10, "framework": [0, 2, 6, 7, 13, 16, 17, 25, 37, 38, 39, 42, 43], "free": [1, 4, 10, 15, 39], "frequent": 47, "friendli": 0, "from": [0, 3, 4, 5, 7, 10, 12, 13, 16, 18, 19, 23, 24, 28, 29, 30, 37, 38, 39, 40, 41, 43, 44, 45], "from_dict": 30, "from_sequ": 37, "fromtimestamp": 43, "fsgroup": 8, "full": [7, 10, 12, 13, 18, 33, 37], "fulli": [0, 39, 47], "fullmatch": 0, "function": [0, 4, 7, 11, 18, 19, 23, 28, 29, 30, 36, 37, 38, 43, 44], "further": [0, 1, 6, 7, 13, 37], "futur": [13, 23, 37, 43], "fvt": [13, 34], "g": [0, 7, 10, 16, 18, 21, 23, 29, 37, 41], "gatekeep": [6, 13, 40], "gb": [18, 23, 37, 43], "gener": [0, 4, 7, 12, 13, 18, 19, 21, 36, 37, 38, 41, 47], "generate_label": 36, "geographicloc": [13, 36, 45], "get": [0, 1, 13, 15, 18, 23, 25, 29, 31, 32, 37, 43, 44, 45], "get_first_byt": 37, "getalldata": 0, "getdata": 0, "getdatatyp": 0, "getlisteningport": 24, "getlogg": 23, "gettrac": 23, "git": [15, 24], "github": [0, 14, 39], "gitlab": 0, "give": [0, 10, 16, 39, 44], "given": [11, 12, 13, 28, 36, 39, 41, 43, 45], "go": [0, 7, 39, 40], "goal": 16, "gom": 39, "gone": 45, "good": [7, 13, 15, 39], "gracefulli": 0, "grandchild": 43, "grandchild_build": 43, "greater": 37, "greatli": 37, "group": [7, 8, 13, 15, 37], "groupid": [22, 24], "grpc": [0, 4, 12, 13, 15, 24, 44, 45, 46], "grpctraceresult": 37, "grpctracesearch": 37, "guava": 0, "gui": 13, "guid": [0, 6, 15, 39], "guidelin": 7, "ha": [0, 7, 10, 12, 13, 18, 19, 21, 23, 37, 38, 39, 40, 41, 43, 44, 45, 46], "half": 30, "handi": 37, "handl": [0, 21], "hanskaton": 24, "hansken": [0, 1, 2, 5, 8, 9, 10, 11, 12, 14, 16, 18, 19, 21, 22, 23, 24, 25, 29, 30, 31, 32, 33, 36, 37, 38, 39, 41, 43, 46], "hansken_extraction_plugin": [37, 40, 43, 44, 45], "hansken_image1": 7, "hansken_project_id": 40, "hansken_tool": 7, "happi": 3, "hard": [23, 43], "hash": 10, "have": [1, 5, 6, 7, 9, 11, 12, 13, 15, 18, 21, 23, 37, 39, 40, 41, 42, 43, 44, 45, 46], "he": [1, 7], "header": 0, "health": 0, "height": 37, "hello": [7, 37, 43], "help": [7, 16, 39, 40], "helper": 35, "henc": 44, "here": [7, 11, 13, 15, 21, 23, 24, 38, 39, 43, 44, 45, 47], "heterogen": 0, "heurist": 13, "hh": 23, "higher": [22, 39, 42], "highli": 18, "hint": [43, 45], "hit": [3, 10, 31, 39, 40], "hold": [36, 43], "holm": 37, "hood": 15, "hopefulli": [19, 38], "horizont": 9, "host": [0, 14, 38, 39], "hostnam": 0, "how": [0, 5, 6, 9, 13, 17, 18, 23, 25, 30, 37, 39, 43, 47], "howev": [12, 13, 15, 40, 44, 45], "hpa": 9, "hql": [0, 2, 11, 12, 18, 23, 33, 37, 43, 46], "hql_lite": [19, 38], "hqllitehumanquerypars": [19, 38], "hqlmatcher": 18, "html": [18, 23, 29, 37, 43], "http": [13, 18, 21, 22, 24, 37, 41], "http_proxi": 41, "https_proxi": [21, 37, 41], "huge": 7, "human": [7, 13], "hyperthread": [18, 23, 30, 37, 43], "i": [0, 1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 16, 18, 19, 21, 23, 24, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], "id": [0, 3, 4, 13, 18, 19, 21, 29, 30, 37, 38, 40, 45, 46], "idea": 7, "ident": [13, 34, 37, 40], "identifi": [4, 7, 13, 18, 30, 37], "idp": 40, "ignor": 0, "illegalargumentexcept": 13, "illegalstateexcept": [0, 13], "illustr": 23, "imag": [0, 3, 4, 5, 6, 7, 11, 18, 21, 23, 24, 30, 33, 37, 41, 43, 45, 46], "imageid": [18, 37], "immut": [0, 29], "implement": [0, 4, 6, 7, 13, 15, 16, 18, 23, 24, 26, 35, 37, 38, 42, 43, 44, 45, 46], "impli": 8, "implicitli": 37, "import": [0, 4, 13, 18, 23, 24, 37, 38, 40, 43, 44, 45], "imposs": 12, "impract": 12, "improv": [0, 1, 37], "in_fil": 43, "inadvert": 0, "includ": [0, 4, 7, 11, 12, 23, 24, 44], "incompat": [0, 7], "incorpor": 12, "incorrect": 7, "incorrectli": 0, "increas": [0, 9, 37, 43], "independ": [12, 45], "index": [0, 3, 13, 29, 33], "indirectli": 45, "infinit": [0, 12], "info": [0, 9, 11, 23, 37, 40, 41, 43, 44, 46], "inform": [0, 4, 6, 11, 13, 15, 16, 18, 23, 28, 30, 37, 38, 39, 41, 43, 45], "inherit": [23, 43], "ini": [37, 44], "init": 24, "initi": [0, 46], "inner": 7, "input": [0, 18, 19, 24, 37, 38, 43, 44, 45], "inputstream": 0, "inrins": 13, "insid": [8, 12, 18, 23, 37, 38, 39, 43, 45], "insight": 16, "instal": [0, 21, 37, 40, 41, 44], "install_requir": 38, "instanc": [0, 3, 4, 12, 22, 23, 36, 44], "instanti": 37, "instead": [0, 3, 5, 7, 8, 18, 19, 37, 38], "institut": 40, "instruct": [18, 19, 21, 37, 39, 41], "int": [0, 13, 23, 24, 27, 29, 30, 31, 33, 35, 36, 45], "integ": [12, 13, 18, 36], "integr": [0, 12, 19, 24, 44, 47], "intel": 30, "intellij": [0, 19], "intend": [7, 46], "intention": 7, "interest": [7, 34, 46], "interfac": [0, 6, 13, 24], "intern": [0, 7, 18, 37], "internet": 6, "interpret": [12, 41, 44], "intim": 7, "intrins": 0, "introduc": [0, 18, 37], "introduct": 47, "invalid": [0, 7, 19, 38], "investig": [16, 36, 45], "invit": 1, "invok": [6, 12, 21, 37, 41, 45], "io": 13, "ioexcept": [0, 18], "ipsum": 12, "irrelev": 12, "isn": 39, "isol": [2, 15], "isort": 0, "issu": [0, 37], "isverboseloggingen": [0, 19], "item": 43, "iter": [0, 4, 7, 11, 28, 30, 31, 43, 46], "its": [4, 6, 7, 10, 12, 13, 16, 18, 28, 37, 45], "itself": [9, 12, 13, 30], "jar": [0, 12, 44], "java": [0, 5, 6, 9, 11, 13, 14, 15, 16, 21, 22, 39, 42, 44, 46, 47], "java_tool_opt": 19, "javadoc": [0, 17, 23], "javajava": 39, "jb": 0, "jdk": [0, 39], "jdwp": 19, "jenkin": 0, "jenkinsfil": 0, "jetbrain": 39, "jmockit": 0, "john": 37, "jorgb": 47, "jpeg": [7, 12], "jpegtool": 7, "jpg": [19, 38], "json": [0, 23, 37, 38, 43, 45, 46], "junit": [0, 24], "jupit": 24, "just": [5, 18, 37, 40], "jvm": 15, "k": [18, 30, 37], "keep": [0, 31, 43], "kei": [7, 12, 13, 18, 29, 30, 37], "key_or_upd": 29, "keycloak": 40, "keystor": 40, "kit": 47, "know": [1, 4, 7, 15, 45], "knowledg": [7, 12, 13, 16], "known": [6, 10, 21, 40, 41], "kotlin": 15, "kubectl": [19, 38], "kubernet": [2, 4, 8, 15], "kwarg": 45, "l": 40, "label": [0, 18, 21, 23, 30, 37, 41, 46], "label_plugin": [0, 37], "land": 0, "lang": [13, 19, 38], "languag": [0, 7, 12, 16, 44, 45], "larg": [0, 18, 23, 37, 43], "last": [10, 19, 38], "later": [16, 18, 28, 37], "latest": [0, 18, 21, 37, 41, 47], "latlong": [0, 13, 36], "launch": 38, "layer": 24, "lazi": 0, "lead": 7, "least": [4, 11, 43], "left": [0, 7], "length": [5, 12, 18, 23, 27, 35, 37, 43], "less": [0, 5, 31, 37], "let": [0, 4, 7, 12, 19], "letter": 7, "lettercountplugin": 7, "level": [0, 23, 30, 43], "libr": 13, "librari": [39, 43], "licens": [0, 4, 15, 18, 22, 30, 37, 46], "lightweight": [7, 18, 23, 37, 43], "like": [4, 7, 18, 19, 23, 29, 34, 38, 39, 41, 43, 44, 45], "limit": [0, 3, 7, 8, 13, 23, 37, 40, 43], "line": [0, 18, 19, 37, 38, 41], "linenumb": [18, 23], "liner": 41, "link": [0, 9, 12], "lint": 0, "linter": 0, "linux": 8, "list": [0, 3, 4, 5, 7, 10, 12, 13, 18, 23, 28, 30, 31, 33, 35, 36, 37, 43], "listen": [0, 38], "lite": [0, 2, 11, 12, 18, 23, 37, 43, 46], "liter": 29, "littl": 44, "live": 45, "ll": 7, "llo": 7, "load": [0, 6, 18, 37, 39], "loadbalanc": 0, "local": [0, 2, 6, 18, 21, 37, 41], "localhost": [24, 38, 44], "localroot": 38, "locat": [0, 13, 37, 39], "log": [0, 6, 7, 13, 40], "log4j": [0, 23], "log4j2": 23, "log_level": 43, "logbook": [0, 43], "logger": [23, 43], "loggerfactori": 23, "logic": [7, 13, 16], "login": 6, "long": [0, 3, 13, 37], "longer": [0, 7, 10, 18, 23, 37], "look": [7, 11, 34, 39, 40, 44], "loop": [4, 12], "loos": 7, "lorem": 12, "lot": [0, 5, 7, 18, 23, 37, 43], "m": 23, "m2r2": 0, "machin": 21, "made": [0, 45], "mai": [7, 12, 34, 37, 39, 40, 45], "main": [13, 23], "mainclass": 22, "mainli": 30, "maintain": [12, 16, 40], "major": 46, "make": [0, 6, 7, 12, 13, 15, 16, 18, 24, 29, 37, 38, 39, 40, 41, 46], "manag": [4, 9, 18, 39, 43], "manhattan": 13, "mani": [7, 12, 13, 24, 30, 39, 41], "manner": [8, 37], "manual": [0, 24, 30, 37], "map": [0, 12, 13, 29, 34, 36, 38, 45], "mark": [5, 13, 18, 37, 43], "markdownlint": 0, "match": [0, 4, 10, 11, 12, 13, 18, 19, 24, 37, 38, 43, 46], "matcher": [0, 4, 11, 13, 18, 23, 30, 37, 40, 43, 46], "materi": 16, "matur": [30, 37], "maturity_level": 37, "maturitylevel": [0, 18, 30, 37], "mauri": 12, "maven": [0, 18, 21, 22, 24], "max": [7, 30], "max_cpu": 46, "max_mem": 46, "maximum": [9, 11, 18, 23, 33, 37, 43], "maximum_cpu": [30, 37, 43], "maximum_memori": [30, 37, 43], "maximum_work": [30, 43], "maximumcpu": [18, 23], "maximummemori": [18, 23], "maximumwork": 23, "mb": [0, 7, 46], "md": 39, "mean": [4, 7, 12, 13, 23, 24, 37, 39, 43, 46], "measur": [8, 30], "mechan": [0, 37], "megabyt": [30, 37], "member": [1, 16, 47], "memori": [0, 9, 18, 23, 30, 37, 43], "mention": [0, 39], "merg": 0, "messag": [0, 13, 19, 23, 38, 43], "meta": [0, 13, 18, 37], "metadata": [10, 13, 18, 28, 29, 30, 37], "metaextractionplugin": 28, "metaextractiontrac": [28, 29], "metal": 30, "meth": 43, "method": [0, 7, 18, 19, 23, 24, 28, 30, 33, 36, 37, 39, 43, 44, 45, 46], "method_nam": [30, 44, 46], "metric": [9, 23], "microsoft": [38, 39], "might": [3, 7, 23, 39, 40, 43, 44], "migrat": [18, 37], "millicpu": 46, "million": 7, "mime": [23, 43], "mimeclass": [7, 12, 37, 43], "mimetyp": [0, 7, 19, 37, 38, 43], "min": 7, "minim": [3, 38], "minimum": 7, "minor": 7, "minut": 39, "minvenj": 24, "misc": [0, 43], "miscellan": 43, "mismatch": [0, 12], "misnam": 7, "miss": [0, 10], "mistun": 0, "mm": 23, "mode": [0, 8, 29, 37, 46], "model": [0, 2, 7, 12, 36, 37, 43], "modelnam": [18, 23, 37, 43], "modelvers": [18, 22, 23, 37, 43], "modif": 11, "modifi": 11, "modifiedon": 43, "modul": [0, 13, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44], "moment": [5, 40, 45], "monei": 10, "monitor": 9, "more": [0, 4, 6, 7, 9, 10, 13, 15, 18, 23, 24, 28, 29, 31, 34, 37, 38, 39, 41, 43, 44, 45], "most": [4, 7, 11, 23, 31, 33, 43], "move": [0, 37], "much": [7, 12, 30, 40], "multilin": 0, "multipl": [0, 3, 7, 10, 11, 12, 13, 15, 18, 34, 37, 43, 45], "must": [4, 6, 13, 19, 23, 38, 40, 43, 45], "mvn": [18, 19, 21], "mvt": 13, "my": [41, 44], "my_cat_detector": [18, 37], "my_modul": 0, "my_plugin": [37, 40, 41, 44], "my_vari": 43, "mypi": 0, "myplugin": [3, 24, 40], "mypluginit": 24, "n": [7, 13, 19, 23, 37, 39, 47], "name": [0, 2, 4, 12, 13, 18, 19, 21, 22, 23, 27, 29, 30, 31, 34, 37, 38, 41, 43, 44, 45, 46], "natur": 0, "nb": 18, "nearbi": 13, "necessari": 7, "need": [0, 3, 4, 6, 7, 9, 11, 12, 15, 30, 37, 39, 40, 41, 44, 45], "negat": 7, "nest": [0, 13], "netherland": 40, "netti": 0, "network": [13, 39], "neural": 13, "never": 0, "new": [0, 5, 7, 11, 13, 16, 18, 19, 23, 24, 29, 37, 39, 40, 43, 47], "new_trac": 7, "newchild": [18, 23], "newer": 0, "newli": [0, 13], "next": [4, 11, 12, 15, 19, 23, 37, 38, 40, 41], "nfi": [0, 10, 18, 21, 24, 37, 41], "nice": 0, "nio": 24, "nl": [10, 15, 18, 21, 24, 37, 41], "nl_nl": 44, "nly": 30, "no_error": 13, "node": 9, "non": [0, 13], "none": [12, 29, 30, 31, 33, 37, 45], "normal": 12, "note": [0, 5, 7, 10, 11, 12, 13, 15, 18, 21, 23, 24, 28, 29, 30, 37, 39, 40, 41, 43, 44, 45], "noth": 7, "notic": 43, "notreal": 34, "now": [0, 5, 6, 7, 10, 18, 37, 38, 39], "null": [18, 24, 37], "num": 31, "number": [0, 3, 4, 7, 9, 12, 13, 18, 23, 29, 30, 31, 33, 37, 43], "object": [0, 4, 13, 23, 27, 29, 30, 32, 33, 34, 35, 36, 37, 43], "observ": [9, 46], "obtain": [5, 11, 18, 28, 37], "occas": 13, "occasion": 12, "occur": [0, 12, 37], "oci": [6, 21, 41], "ocr": [10, 18, 37], "ocrimag": 40, "offer": [29, 30], "offic": 13, "offici": 15, "offset": [5, 12, 18, 23, 29, 35, 37, 43], "often": [7, 12], "ok": 39, "old": [0, 18, 37], "omit": [37, 42], "onc": [3, 7, 13, 21, 29, 31, 41, 45], "one": [0, 4, 7, 9, 11, 12, 18, 19, 28, 30, 31, 34, 37, 38, 39, 40, 41, 43, 45], "onerror": 13, "ones": 7, "onli": [0, 3, 5, 7, 8, 11, 12, 13, 18, 19, 23, 28, 29, 31, 33, 35, 37, 38, 40, 41, 43, 45, 46], "onlin": 37, "open": [0, 13, 29, 37, 39, 40, 43, 46], "openjdk": 39, "oper": [7, 9], "opportun": 1, "opposit": 7, "optic": 10, "option": [0, 3, 11, 12, 13, 15, 16, 18, 23, 30, 32, 37, 38, 39, 40, 41, 43, 44, 46], "order": [0, 12, 16, 18, 29, 32, 37, 38, 39], "org": [0, 10, 12, 13, 18, 19, 22, 23, 24, 37, 38, 39, 46], "organis": [10, 15, 30, 46], "origin": [5, 13, 16, 18, 37, 43], "other": [1, 3, 4, 7, 11, 12, 13, 16, 18, 28, 29, 33, 37, 40, 41, 47], "otherwis": 3, "our": [7, 39], "out": [0, 13, 19, 38, 40], "outcom": [24, 44], "outdat": 0, "outlin": 6, "output": [0, 12, 16, 19, 38, 39, 40, 43, 45], "outsid": [36, 37, 38, 39, 45, 46], "over": [0, 4, 5, 7, 8, 10, 37, 44], "overhead": [0, 7, 37], "overlap": 7, "overrid": [0, 18, 19, 23, 24, 43], "overridden": 37, "overview": 44, "overwrit": [0, 7], "overwritten": [37, 43], "own": [6, 24, 39], "owner": [1, 15], "p": [18, 19, 37, 38], "pack": [0, 30], "packag": [0, 13, 17, 18, 19, 22, 25, 26, 37, 38, 39, 42], "page": [0, 4, 8, 15, 19, 23, 39, 40, 45, 46], "pair": [7, 13, 44], "paragraph": [7, 13], "param": 35, "paramet": [0, 11, 12, 18, 23, 28, 29, 30, 31, 33, 37, 43, 44, 45, 46], "parent": [13, 22, 24, 29], "parenttraceid": 13, "pars": [0, 7, 10, 41], "parseexcept": [19, 38], "parser": [0, 7], "part": [7, 12, 13, 39, 43, 46], "parti": 15, "partial": 0, "pass": [0, 12, 18, 23, 37, 38, 40, 41, 43, 44], "password": 40, "path": [0, 13, 18, 19, 24, 37, 38, 39, 41, 44], "pathmap": 38, "patient": 39, "pattern": [13, 23, 37, 39], "patternlayout": 23, "pdf": [7, 13], "per": [0, 3, 5, 9, 16, 18, 37], "perform": [0, 4, 7, 10, 11, 31, 41], "period": 41, "perspect": 4, "pictur": [10, 13, 37], "piec": [13, 38], "piet": 34, "pillow": 0, "pin": 0, "pip": 39, "pip3": 39, "pipelin": [0, 41, 42], "place": [8, 39], "plain": 7, "platform": [8, 16, 46], "pleas": [1, 7, 11, 13, 15, 18, 37, 39, 40, 46, 47], "plu": 7, "plugin": [0, 1, 2, 3, 5, 9, 14, 17, 18, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 36, 37, 41, 42, 44, 45], "plugin_fil": 37, "plugin_info": [28, 37, 41, 43, 44, 45], "plugin_modul": 44, "plugin_port": [0, 46], "pluginid": [0, 18, 21, 30, 37, 41], "plugininfo": [0, 9, 18, 21, 23, 24, 28, 30, 36, 37, 41, 43], "plugininfobuild": 0, "pluginnam": [6, 12, 18, 37], "pluginresourc": [0, 18, 23, 30, 37, 43], "pluginrunn": 40, "plugintotest": [19, 24, 44], "pluginvers": 18, "png": [23, 43], "pod": [9, 18, 23, 37, 43], "podman": [18, 21, 22, 41], "point": [7, 13, 35, 45], "pointer": 37, "polici": 0, "politi": 10, "pom": [0, 18, 22, 24], "popul": 30, "popup": 39, "port": [0, 3, 19, 24, 38, 44, 46], "portion": 7, "portutil": 0, "posit": [0, 23, 37, 45], "possibl": [3, 7, 11, 12, 13, 15, 16, 18, 19, 21, 23, 24, 37, 38, 43, 44], "post": 40, "postpon": 28, "potenti": 7, "practic": 7, "pre": [23, 29], "predefin": 13, "predict": [13, 18, 23, 37, 43], "prefer": [5, 10, 37, 45], "prefil": 0, "prefix": [6, 37], "prematur": 37, "prepar": 3, "prepend": 7, "prerequisit": [17, 21, 25, 39], "present": [12, 13], "press": 39, "presum": 24, "pretti": 43, "prettier": 0, "prevent": [0, 7], "preview": [0, 47], "previewdata": 23, "previou": [10, 37, 39], "primari": 16, "primarili": 13, "primit": 0, "principl": 8, "print": [19, 31, 38], "prior": [18, 37], "privaci": 8, "privat": [1, 23, 24], "probabl": 15, "process": [0, 5, 7, 9, 10, 11, 12, 13, 18, 23, 24, 27, 28, 29, 30, 31, 33, 37, 40, 41, 43, 44, 45, 46], "process_batch": 31, "process_the_trac": 7, "processor": 30, "produc": [3, 7, 11, 13, 19, 37, 38], "product": 16, "production_readi": 30, "profil": 0, "program": [0, 4, 12, 16, 38, 39], "programm": 0, "prohibit": 7, "project": [0, 3, 11, 16, 18, 21, 22, 23, 33, 37, 39, 40, 42, 43], "promis": 7, "prompt": [39, 40], "prone": 12, "proof_of_concept": [18, 30, 37], "propag": [0, 45], "proper": 15, "properli": 0, "properti": [0, 4, 6, 9, 11, 12, 18, 19, 22, 23, 28, 29, 30, 34, 37, 38, 40], "propertynam": 13, "protect": [19, 24], "proto": 0, "protobuf": 0, "protocol": [0, 4, 38], "prototyp": 39, "provid": [0, 6, 8, 9, 11, 12, 13, 23, 24, 30, 33, 35, 37, 40, 41, 42, 44, 45], "proxi": [0, 21, 37, 39, 41], "pseudocod": 7, "public": [18, 19, 22, 23, 24, 37, 42], "publish": [0, 19, 21, 22, 38, 41, 42], "pure": 12, "purpl": 45, "purpos": [12, 45], "push": [0, 6], "put": [7, 12, 19, 38, 41], "py": [0, 15, 25, 30, 31, 37, 38, 39, 41, 43, 44], "py38": 39, "pypi": [0, 42], "pytest": 0, "python": [0, 3, 5, 6, 9, 11, 13, 14, 15, 16, 18, 36, 39, 41, 42, 46, 47], "python3": [39, 40], "quantiti": 43, "queri": [0, 7, 11, 12, 19, 23, 33, 37, 38, 40, 43], "question": [1, 7, 47], "quick": 39, "quickli": [19, 38], "quicklink": 0, "quot": [0, 7, 41], "r": 7, "ra": 7, "raaaaaw": 7, "rais": [0, 29], "randomaccessdata": 0, "randomaccessdatainputstream": 23, "rang": [0, 5, 7, 12, 18, 23, 35, 37, 43], "rangeddatatransform": [0, 18, 23], "rangedtransform": [0, 35, 37, 43], "rapidli": 39, "raw": [0, 7, 12, 13, 18, 19, 23, 29, 37, 38, 43], "rawbyt": 23, "rb": [29, 37, 43], "re": [3, 7], "reach": [3, 9], "read": [0, 4, 10, 11, 15, 16, 18, 23, 29, 37, 39, 45, 47], "readabl": 0, "readm": 39, "ready_for_test": 30, "real": [0, 13, 36], "realli": 7, "rearrang": 0, "reason": 7, "reassembl": 10, "receiv": [0, 13, 43, 45], "recognit": [10, 19, 38], "recommend": [7, 10, 18, 19, 22, 37, 38, 39, 43], "red": 0, "reduc": [0, 7, 37], "redund": 0, "ref": [12, 23], "refactor": 0, "refer": [0, 15, 16, 18, 23, 30, 36, 37, 44], "referenc": 44, "reflect": 12, "regener": [12, 19, 24, 38], "regex": 7, "regist": 0, "registri": [4, 6, 16, 18, 21, 37, 41], "registryentri": [18, 37], "regular": 11, "rel": 44, "relat": 13, "relax": 0, "releas": [13, 18, 23, 37, 43], "relev": 12, "reli": 41, "reliabl": [0, 7, 41], "remain": 0, "remark": 7, "rememb": 7, "remot": [0, 19, 29, 36, 37, 38, 45], "remoteextractionpluginflit": [0, 24], "remoteroot": 38, "remotetransformationpluginflitsit": 24, "remov": [0, 18, 19, 23, 24, 37, 38, 43], "renam": [0, 18, 37], "repair": 0, "replac": [0, 7, 18, 37, 40, 43, 44], "replica": 9, "repo": [0, 22], "report": 10, "repositori": [0, 14], "repres": [4, 13, 18, 29, 30, 31, 32, 37], "represent": [7, 31], "request": [0, 1, 4, 11, 15, 29, 30, 31, 38, 40, 41, 45], "requir": [0, 3, 7, 12, 15, 16, 18, 19, 22, 23, 31, 36, 37, 38, 40, 42, 43, 44, 45, 46], "research": 0, "reserv": [12, 30, 47], "resourc": [0, 3, 7, 9, 18, 30, 37, 46, 47], "resourcemanag": 2, "respect": 40, "respons": [0, 15], "rest": [0, 13, 18, 37, 40, 45], "restart": [3, 9], "restrict": 8, "restructur": 0, "result": [0, 4, 7, 18, 19, 23, 24, 29, 31, 33, 37, 38, 41, 43], "resultpath": [19, 24], "retri": 0, "retriev": [0, 4, 13, 28, 29, 30, 31, 36, 37], "return": [0, 4, 7, 11, 18, 19, 23, 24, 28, 29, 30, 31, 32, 33, 35, 37, 39, 43, 44, 45, 46], "return_typ": [30, 46], "right": [7, 13, 47], "risk": 15, "root": [0, 8, 13, 23, 39, 40], "rout": 0, "row": [7, 12], "rpc": 0, "rpcfinish": 0, "rpcstart": 0, "rpcstringmap": 0, "rpcsync": 0, "rpcsyncack": 0, "rpcunixtim": 0, "rpczoneddatetim": 0, "rst": [0, 13, 37], "rule": [7, 38], "run": [0, 3, 4, 6, 8, 9, 12, 15, 18, 21, 23, 24, 25, 28, 30, 37, 38, 39, 41, 42, 43, 44, 45, 46], "run_with_hansken": 40, "run_with_hanskenpi": [0, 37, 40], "runner": [0, 12, 37, 43, 44], "runtim": [0, 12, 24, 26, 37, 40], "runtimedefault": 8, "safe": 23, "sai": 7, "said": 7, "same": [0, 3, 7, 9, 10, 11, 12, 18, 23, 24, 37, 39, 41, 43, 44, 45], "saml": 40, "sane": 8, "save": [5, 18, 29, 37, 40], "scala": 15, "scalabl": 15, "scale": [9, 15, 23], "scan": [0, 4, 6, 10], "scenario": 12, "schemaloc": 22, "scheme": 0, "scope": [0, 7, 18, 23, 33, 37, 43, 46], "score": [18, 37], "screen": 13, "screenshot": 39, "script": [0, 18, 30, 37, 38, 44], "sdk": [0, 1, 5, 9, 11, 12, 18, 20, 23, 24, 37, 38, 39, 40, 41, 44, 46], "search": [0, 4, 7, 11, 12, 13, 18, 23, 29, 31, 32, 33, 37, 40, 43, 45], "search_result": 43, "search_sort_opt": 33, "searcher": [0, 18, 23, 28, 33, 37, 43], "searchresult": [18, 23, 31, 33, 43], "searchscop": [18, 23, 33, 37], "searchsortopt": [32, 33], "searchtrac": [12, 29, 31], "seccomp": 8, "second": [0, 7, 13, 31, 37], "secondarili": 13, "section": [4, 7, 12, 13, 18, 24, 37, 39, 40, 41, 44, 45], "secur": [8, 15], "see": [0, 1, 3, 4, 6, 7, 12, 13, 15, 18, 21, 23, 24, 30, 37, 38, 41, 43, 44, 45, 46, 47], "seek": 0, "seem": 4, "seiz": 16, "select": [4, 6, 30, 33, 39, 40], "self": [0, 37, 43, 44, 45], "send": [0, 45], "sens": [7, 10], "sensit": [7, 23, 43], "sent": [0, 4, 36], "separ": [0, 7, 9, 12], "seper": 0, "sequenc": [0, 36, 45], "serial": [0, 12, 18, 36, 37], "serv": [0, 24, 44], "serve_plugin": [37, 43, 44], "server": [0, 1, 12, 19, 24, 46], "servic": [0, 21, 38, 44, 46], "session": 3, "set": [0, 3, 4, 6, 8, 11, 13, 18, 23, 24, 29, 37, 43, 44, 46], "set_the_plugin_main_class_her": 22, "set_the_plugin_version_her": 22, "set_the_sdk_version_her": 22, "setdata": [18, 23], "setup": [12, 24, 37, 38, 40, 44, 45], "setuptool": 38, "sever": [13, 38], "sha256": 10, "shade": [0, 13], "share": 16, "she": 1, "short": 30, "shortest": 10, "should": [0, 6, 12, 13, 15, 18, 23, 29, 37, 39, 41, 43, 44, 46], "show": [0, 4, 5, 10, 12, 13, 18, 19, 23, 37, 39, 40, 43], "shown": [4, 10, 12, 19, 23, 38, 44], "shut": 37, "shutdown": 4, "sibl": 0, "side": [0, 7, 18, 37], "sign": 15, "signal": 45, "signatur": [0, 46], "significantli": 37, "sigterm": 0, "similar": [0, 3, 7, 13], "simpl": [7, 23, 37], "simpli": [24, 40, 44, 45], "simplifi": [4, 7, 18, 37], "sinc": [0, 7, 43], "singl": [0, 7, 11, 12, 13, 18, 31, 34, 43, 44], "sit": 12, "six": 12, "size": [0, 27, 29, 35, 37], "skeleton": 0, "skip": [0, 39], "slash": [0, 7, 10, 19, 38], "slf4j": 23, "slight": 12, "slow": [0, 7, 37], "slower": [40, 41], "small": [3, 18, 23, 37, 43], "smaller": 43, "snapshot": 0, "snippet": [0, 17, 18, 22, 25, 37, 39, 47], "so": [3, 4, 7, 13, 16, 19, 37, 38, 44, 45], "soap": 40, "sock": 21, "socketproxi": 0, "sodal": 12, "softwar": [18, 22, 37, 47], "solut": 7, "some": [0, 3, 5, 7, 10, 12, 13, 18, 37, 39, 40, 43, 44, 45], "someon": 7, "someth": [7, 23, 41, 45], "sometim": [7, 11], "sort": [0, 13, 18, 32, 33, 37], "sourc": [0, 5, 15, 18, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 46], "space": [5, 13, 18, 37, 41], "spec": 46, "specif": [0, 10, 11, 12, 13, 18, 23, 36, 37, 38, 40, 43, 45, 47], "specifi": [0, 3, 5, 9, 13, 18, 21, 37, 41, 45], "speech": [16, 45], "speed": [0, 41], "spin": 44, "split": [0, 12], "src": 23, "srcpath": [19, 24], "ss": 23, "stabil": 0, "stabl": 47, "stack": 45, "stage": [18, 28, 37, 40], "stand": 7, "standalon": [0, 38], "standalonetestrunn": 0, "standard": [13, 39, 43], "standardis": 38, "start": [0, 3, 5, 11, 12, 15, 18, 19, 23, 24, 25, 29, 33, 35, 37, 38, 40, 41, 43, 45, 46, 47], "startswith": 0, "startup": [6, 7], "state": 23, "statement": [7, 18, 19, 23, 37, 38], "static": [0, 23, 24, 30, 35, 45], "statu": 37, "statusruntimeexcept": [0, 13], "stdout": 23, "step": [0, 3, 6, 15, 18, 19, 37, 38], "still": [0, 7, 12, 15, 18, 37], "stop": [0, 4, 37, 44], "store": [0, 5, 7, 12, 13, 23, 30, 43], "str": [13, 27, 29, 30, 32, 33, 34, 36, 37, 43, 45, 46], "straight": 43, "strategi": 0, "stream": [0, 5, 7, 12, 18, 23, 27, 28, 29, 31, 37], "streamobserv": 13, "string": [7, 12, 13, 18, 36, 37, 43], "stringlist": 12, "strongli": 37, "structur": [10, 13, 37, 46], "studio": 38, "stuff": 39, "style": [18, 37], "subclass": 0, "subject": 8, "subprocess": 0, "subsequ": 7, "subset": [7, 23, 43], "substitut": 13, "succe": 12, "succeed": 39, "sudo": 39, "suit": 39, "suitabl": 45, "summar": [7, 18, 37], "summari": 39, "super": [0, 22, 24, 35], "superclass": 28, "superpom": [0, 18, 21], "suppli": [29, 40, 44, 45], "support": [0, 3, 5, 7, 11, 12, 13, 18, 23, 30, 35, 37, 40, 41, 43, 45], "supported_primit": 36, "sure": [0, 6, 7, 12, 13, 15, 24, 37, 39, 41, 46], "surround": 7, "suspend": 19, "switch": [0, 18, 37], "syntax": [11, 18, 37, 43], "system": [3, 9, 13, 18, 21, 37, 39, 40, 41], "system_out": 23, "t": [0, 1, 7, 12, 13, 15, 24, 37, 39, 41, 46, 47], "tabl": 10, "tag": [18, 21, 37, 41], "take": [3, 5, 6, 7, 15, 31, 37, 39, 41, 43], "takeon": [31, 43], "talk": 24, "target": [0, 23, 37], "target_nam": 41, "task": [4, 41], "team": [1, 10, 15, 46], "technic": 0, "technologi": 47, "tediou": 7, "telephon": [23, 43], "tell": [7, 38], "temporarili": 0, "tensorflow": 0, "term": 0, "termin": [0, 39, 40, 44], "tesseract": 10, "test": [0, 2, 3, 6, 7, 13, 16, 17, 18, 19, 25, 37, 38, 39, 42, 43], "test_framework": [0, 44], "test_func": 46, "test_plugin": [0, 38, 44], "testaccount": 40, "testdata": [24, 44], "tester": 37, "testframework": [0, 12], "testpath": [19, 24], "testplugin": [18, 19, 37], "testpluginflitsit": 19, "testrandomaccessdata": 0, "testtracesearch": 0, "text": [7, 10, 12, 16, 29, 37, 45], "text_writ": [37, 43], "textiobas": 29, "textual": 13, "tgz": 0, "than": [7, 12, 13, 15, 18, 29, 37, 39, 41], "thei": [5, 7, 11, 12, 13, 16, 31, 41, 45], "them": [0, 4, 6, 7, 12, 13, 15, 23, 43, 44], "theori": 15, "thereaft": 12, "therefor": [12, 13, 18, 23, 37, 41, 43, 45], "thi": [1, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47], "think": [7, 15], "third": [15, 43, 44], "this_property_does_not_exist": 13, "those": [7, 12, 39], "though": 7, "thread": [3, 9, 23, 43], "three": [0, 10, 12, 23, 31, 34, 40, 41, 43], "through": [0, 4, 5, 18, 29, 37], "throw": [0, 12, 18, 24, 45], "thrown": [29, 45], "thu": 16, "tight": 7, "tightli": 7, "time": [0, 3, 7, 11, 12, 13, 15, 18, 21, 36, 37, 39, 45], "timeout": [0, 37], "timezon": 43, "tip": 7, "tmp": 7, "token": [19, 38], "too": [7, 12, 37], "tool": [0, 3, 4, 7, 11, 13, 15, 16, 22, 28, 30, 37, 38, 39], "top": 43, "total": [0, 27, 31], "total_result": 31, "touch": 1, "tox": [0, 37, 39, 44], "trace": [0, 2, 3, 4, 5, 7, 9, 10, 11, 16, 18, 19, 27, 28, 29, 30, 31, 33, 34, 36, 37, 38, 40, 44, 45, 46], "trace__": 12, "trace_search": 37, "tracebuild": 29, "tracedata": 23, "traceid": 0, "tracelet": [0, 18, 29, 37, 40], "traceletproperti": 23, "tracemodel": 13, "tracesearch": [18, 23, 28, 33, 43], "tracetojson": 0, "traceuid": 0, "tradit": [23, 43], "tranform": 0, "transcript": 37, "transform": [0, 2, 11, 12, 18, 25, 28, 29, 30, 37, 39, 40, 46], "transformerargu": 0, "transformerlabel": [30, 36], "translat": [7, 37, 44, 45], "translate_text": 45, "translator_plugin": 44, "transorm": 23, "transpar": 8, "transport": 19, "treat": 31, "trickier": [19, 38], "true": [6, 7, 12, 19, 24, 43], "try": [6, 7, 12, 23, 37, 44], "tupl": [13, 38], "turn": [23, 45], "tutori": 19, "twice": 7, "two": [4, 7, 9, 11, 12, 18, 21, 23, 37, 41, 43, 44, 46], "txt": [0, 7, 22, 37], "type": [0, 2, 4, 6, 10, 12, 16, 18, 19, 23, 27, 28, 29, 30, 34, 36, 37, 38, 39, 43, 45], "typic": [4, 13, 43], "typo": 0, "tz": 43, "u": [1, 12, 15, 21, 47], "ui": [13, 40, 45], "uid": 32, "un": 7, "unaccept": 7, "unavail": 13, "unclutt": 0, "uncommon": 7, "undefin": 3, "under": [0, 7, 12, 13, 15, 18, 22, 37, 39, 46], "understand": 16, "unexpect": [0, 7], "uniqu": [4, 7, 10, 12, 13, 30], "unit": [0, 12, 24, 30, 44], "univers": 7, "unix": [7, 21, 45], "unlik": [7, 30, 36], "unnam": 37, "unnecessari": 7, "unpack": 0, "unrequir": 0, "unstash": 0, "unsupport": [0, 7], "unsur": 46, "until": [13, 37, 38], "unus": 0, "unzip": 39, "up": [0, 4, 12, 15, 29, 37, 38, 40, 41, 44, 45], "upcom": [18, 37], "updat": [0, 18, 23, 29, 37, 39, 43, 44], "upgrad": [0, 18, 37], "upload": [21, 37, 39, 40, 41], "upon": 45, "uri": 6, "url": [0, 22, 24, 30, 40], "us": [0, 3, 4, 6, 8, 10, 11, 12, 13, 16, 17, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 33, 36, 37, 38, 39, 40, 41, 43, 46], "usabl": 30, "usag": [7, 9, 37, 39, 43], "user": [0, 4, 6, 18, 21, 30, 37, 39, 40, 41, 45], "usernam": 40, "usual": [7, 13], "utc": [43, 45], "utf": [13, 22, 23, 29, 37, 43], "util": [0, 9, 13, 23, 24, 36, 37, 41, 45], "uuid": 13, "v": [0, 40, 43], "v47": [18, 37], "valid": [0, 4, 7, 12, 29, 36, 39, 44, 45], "validate_update_argu": 37, "valu": [0, 7, 12, 13, 29, 30, 32, 33, 34, 37, 40, 43], "value1": 45, "value2": 45, "vari": 40, "variabl": [0, 19, 23, 37, 39, 40, 41, 43, 45, 46], "variant": [23, 43], "variou": [5, 12, 18, 23, 37], "variu": 12, "vcpu": [18, 23, 30, 37, 43], "vector": [0, 18, 23, 36, 37, 45, 46], "verbos": [0, 19, 38], "veri": [4, 7, 11, 12], "verif": 39, "verifi": [16, 23, 41, 43], "version": [0, 7, 13, 18, 21, 22, 23, 24, 30, 37, 38, 39, 41, 46, 47], "via": [4, 6, 19, 38], "view": [7, 13, 19, 38, 41], "virtual": 37, "viru": 7, "visibl": [0, 3, 4], "visit": 20, "visual": [5, 38], "vm": 0, "void": [18, 23, 24], "vv": 43, "vvv": [43, 44], "w": [0, 7, 29, 37, 43], "w3": 22, "wa": [0, 7, 10, 13, 18, 19, 37, 44], "wai": [0, 6, 7, 12, 16, 18, 23, 24, 31, 37, 38, 39, 40, 41, 43, 44], "wait": 0, "wait_for_cli": 38, "wallet": 16, "want": [1, 7, 37, 39, 40, 44], "warn": [0, 13, 23, 40, 43], "wasn": 0, "wb": [29, 37, 43], "we": [3, 7, 15, 23, 39, 43, 44], "webpag": [0, 39, 46], "webpage_url": [30, 37], "webpageurl": 18, "websit": [0, 39], "well": [0, 6, 7, 10, 16, 28, 37, 38, 40, 41, 45], "went": 6, "were": [0, 7, 13, 28], "what": [10, 40], "whatev": 4, "whatsapp": [18, 21, 37, 41], "wheel": 0, "when": [0, 3, 6, 11, 12, 13, 18, 23, 29, 31, 36, 37, 39, 40, 41, 43, 44, 45], "whenev": 7, "where": [0, 7, 10, 13, 23, 30, 39, 43], "whether": [10, 36, 39], "which": [0, 4, 6, 7, 11, 12, 13, 16, 18, 23, 24, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "while": [0, 5, 7, 9, 11, 12, 19, 37, 38], "whl": 0, "who": [1, 15, 39], "why": 11, "wide": [0, 18, 37], "width": 37, "wikipedia": 7, "wildcard": [0, 7], "window": [0, 16, 44], "wish": [36, 45], "within": [4, 8, 9, 11, 23, 32, 33, 37, 43, 46], "without": [0, 11, 12, 13, 18, 24, 28, 29, 37, 39, 41], "won": 24, "word": 7, "work": [0, 6, 18, 37, 38, 39, 43], "worker": [0, 3, 18, 23, 30, 37, 43], "workspacefold": 38, "world": [37, 38, 43], "worri": 46, "would": [0, 7, 12], "wrap": [0, 45], "wrapper": [0, 12, 44], "write": [0, 4, 11, 12, 15, 16, 18, 23, 29, 37, 39, 40, 43], "writer": [23, 37, 43], "written": [4, 12, 15, 37, 39, 43], "wrong": [0, 12, 45], "wt": [29, 43], "www": [18, 22], "x": 7, "x00": 43, "xff": 43, "xml": [18, 22, 23], "xmln": 22, "xmlschema": 22, "xsd": 22, "xsi": 22, "y": 19, "yaml": 23, "ye": 15, "yellow": 39, "yet": [0, 12, 15, 29, 40], "yield": 7, "yolo": [18, 23, 43], "you": [1, 3, 6, 7, 11, 12, 13, 18, 21, 23, 24, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47], "your": [0, 1, 3, 6, 7, 11, 18, 19, 21, 23, 24, 37, 38, 41, 43, 45, 46], "your_extraction_plugin_nam": [19, 38], "your_extraction_plugin_pod": [19, 38], "your_gatekeeper_url": 40, "your_keystore_url": 40, "your_plugin": 38, "your_proxi": [37, 41], "yyyi": 23, "zero": 31, "zip": [0, 10, 39], "zone": 45, "zoneddatetim": 0}, "titles": ["Changelog", "Contact", "General concepts", "Debugging locally with Hansken All in One (AIO)", "Anatomy of a plugin", "Data Transformations", "Hansken Extraction Plugins", "HQL-Lite", "Plugin isolation", "Kubernetes, Autoscaling, Resourcemanagement", "Plugin naming convention", "Extraction plugin types", "Test framework", "Traces & Trace model", "Examples", "Frequently Asked Questions", "Introduction", "Java", "Java API Changelog", "How to debug an Extraction Plugin", "Javadoc", "Packaging", "Prerequisites", "Java code snippets", "Using the Test Framework in Java", "Python", "hansken_extraction_plugin.api", "hansken_extraction_plugin.api.data_context", "hansken_extraction_plugin.api.extraction_plugin", "hansken_extraction_plugin.api.extraction_trace", "hansken_extraction_plugin.api.plugin_info", "hansken_extraction_plugin.api.search_result", "hansken_extraction_plugin.api.search_sort_option", "hansken_extraction_plugin.api.trace_searcher", "hansken_extraction_plugin.api.tracelet", "hansken_extraction_plugin.api.transformation", "hansken_extraction_plugin.api.transformer", "Python API Changelog", "How to debug an Extraction Plugin", "Getting started", "Run plugins with Hansken.py", "Packaging", "Prerequisites", "Python code snippets", "Advanced use of the Test Framework in Python", "Using Transformers for on-demand execution", "Extraction Plugin specifications", "Hansken extraction plugin SDK documentation for plugin developers"], "titleterms": {"": 15, "0": [0, 18, 37], "1": [0, 18, 37], "10": [0, 18, 37], "11": [0, 18], "12": 0, "13": [0, 18, 37], "14": 0, "15": 0, "16": 0, "2": [0, 18, 37], "3": [0, 18, 37], "4": [0, 18, 37], "5": [0, 18, 37], "6": [0, 18, 37], "7": [0, 18, 37], "8": [0, 18, 37], "9": [0, 18, 37], "One": 3, "The": [4, 12], "Will": 15, "access": 15, "ad": [23, 43], "advanc": 44, "aio": 3, "all": 3, "also": 5, "an": [4, 6, 7, 19, 38, 39], "anatomi": 4, "anti": 7, "api": [18, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37], "ar": [15, 45], "ask": 15, "autosc": 9, "basic": 12, "blob": [23, 43], "breakpoint": [19, 38], "build": [6, 19, 37, 38], "build_plugin": 41, "build_plugin_ci": 41, "bulk": [23, 43], "call": [8, 45], "can": [7, 15], "can_this_tool_process_the_provided_trac": 7, "categori": 43, "certain": 7, "chang": 37, "changelog": [0, 18, 37], "child": [13, 43], "code": [19, 23, 38, 43], "command": [40, 41], "commun": 15, "compat": 40, "concept": 2, "configur": 38, "connect": 38, "contact": 1, "contain": 38, "containsinord": 12, "content": [2, 17, 25, 47], "convent": 10, "creat": [12, 15, 40], "custom": 23, "data": [5, 7, 12, 13, 23, 43], "data_context": 27, "datastream": 7, "date": 43, "debug": [3, 19, 38], "debugpi": 38, "defer": [11, 12, 23, 43], "demand": 45, "describ": 7, "develop": [15, 16, 45, 47], "directori": 12, "discoveri": 4, "do": [7, 45], "docker": [19, 38, 39, 44], "document": [25, 47], "doe": 7, "download": 39, "els": 15, "embed": [15, 24], "empti": 39, "enabl": 6, "error": 45, "exampl": [7, 10, 14, 24], "except": 12, "exclud": 7, "execut": [4, 45], "expect": [7, 44], "experiment": [23, 43], "extens": 7, "extra": 43, "extract": [4, 6, 11, 12, 13, 15, 19, 23, 38, 39, 40, 43, 46, 47], "extraction_plugin": 28, "extraction_trac": 29, "featur": [23, 43], "file": 40, "find": 9, "finish": 4, "foobar": 15, "format": 12, "framework": [12, 24, 44], "frequent": 15, "full": 39, "gener": 2, "get": 39, "handl": 45, "hansken": [3, 4, 6, 7, 13, 15, 40, 45, 47], "hansken_extraction_plugin": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36], "help": 44, "how": [7, 12, 15, 19, 38, 40, 45], "hql": [7, 19, 38], "i": [7, 15], "id": [39, 44], "identifi": 10, "imag": [19, 38, 44], "implic": 15, "import": 39, "inform": 7, "input": [7, 12], "inputstream": 23, "instal": [38, 39], "intrins": 13, "introduct": 16, "isol": 8, "itself": 4, "java": [12, 17, 18, 19, 23, 24], "javadoc": 20, "json": 12, "just": 7, "kit": 16, "kubernet": [9, 19, 38], "label_plugin": 41, "languag": 15, "leav": 12, "legal": 15, "limit": 45, "link": 47, "list": 6, "lite": 7, "local": [3, 19, 38], "log": [19, 23, 38, 43], "manual": 44, "match": 7, "matcher": [7, 12], "messag": 12, "meta": [11, 43], "method": 4, "mime": 7, "mode": [23, 43], "model": 13, "modifi": 15, "my": [7, 15], "name": 10, "network": 8, "next": 39, "note": 3, "option": 19, "out": 12, "overview": 7, "own": 15, "packag": [6, 21, 41, 46], "partial": 12, "path": 7, "pattern": 7, "pdfplugin": 7, "perform": 15, "pipelin": 37, "plugin": [4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 19, 23, 38, 39, 40, 43, 46, 47], "plugin_info": 30, "plugininfo": 4, "precis": 7, "prepar": 40, "prerequisit": [22, 24, 42], "preview": [23, 43], "process": 4, "program": 15, "properti": [7, 13, 43], "protocol": 46, "provid": 7, "py": 40, "pycharm": 39, "python": [12, 25, 37, 38, 40, 43, 44], "question": 15, "quick": 47, "randomaccessdata": 23, "reason": 15, "refresh": 6, "regener": 44, "releas": 0, "remot": 24, "requir": [39, 41], "rescu": 7, "resourc": [23, 43], "resourcemanag": 9, "result": [12, 44], "reus": 15, "right": 9, "run": [19, 40], "runner": 40, "safe": 15, "sdk": [13, 15, 16, 47], "search_result": 31, "search_sort_opt": 32, "see": 5, "set": [7, 9, 19, 38, 39], "setup": 39, "should": 7, "size": 7, "skeleton": 39, "snippet": [23, 43], "softwar": [16, 39], "someon": 15, "specif": [7, 19, 46], "specifi": [23, 43], "standalon": [40, 44], "standard": 11, "start": [4, 6, 39, 44], "startswith": 12, "step": [16, 39], "stream": [13, 43], "structur": 12, "support": 15, "syntax": 7, "system": [8, 23, 43], "templat": 39, "test": [12, 24, 44, 45], "text": 43, "tip": [3, 44], "tool": [6, 19, 45], "trace": [12, 13, 23, 43], "trace_search": 33, "tracelet": [13, 23, 34, 43], "transform": [5, 23, 35, 36, 43, 44, 45], "type": [7, 11, 13], "ubuntu": 39, "up": 39, "upload": 6, "us": [7, 15, 24, 44, 45], "usag": [23, 41], "user": 8, "vector": 13, "verifi": 39, "versu": 24, "welcom": 47, "what": [7, 15, 45], "when": 7, "why": [7, 15], "window": 39, "work": [7, 45], "write": 7, "wrote": 15, "you": 15, "your": [12, 15, 39, 40, 44]}}) \ No newline at end of file diff --git a/latest b/latest index ea8f4fd..35eb060 120000 --- a/latest +++ b/latest @@ -1 +1 @@ -0.9.10 \ No newline at end of file +0.9.16 \ No newline at end of file