"""The path specification factory."""
[docs]
class Factory:
"""Path specification factory."""
PROPERTY_NAMES = frozenset(
[
"cipher_mode",
"column_name",
"compression_method",
"data_stream",
"encoding_method",
"encryption_method",
"identifier",
"initialization_vector",
"inode",
"key",
"location",
"mft_attribute",
"mft_entry",
"part_index",
"password",
"range_offset",
"range_size",
"recovery_password",
"row_condition",
"row_index",
"start_offset",
"startup_key",
"store_index",
"table_name",
"volume_index",
]
)
_path_spec_types = {}
_system_level_type_indicators = {}
[docs]
@classmethod
def DeregisterPathSpec(cls, path_spec_type):
"""Deregisters a path specification type.
Args:
path_spec_type (type): path specification type.
Raises:
KeyError: if path specification type is not registered.
"""
type_indicator = path_spec_type.TYPE_INDICATOR
if type_indicator not in cls._path_spec_types:
raise KeyError(f"Path specification type: {type_indicator:s} not set.")
del cls._path_spec_types[type_indicator]
if type_indicator in cls._system_level_type_indicators:
del cls._system_level_type_indicators[type_indicator]
[docs]
@classmethod
def GetProperties(cls, path_spec):
"""Retrieves a dictionary containing the path specification properties.
Args:
path_spec (PathSpec): path specification.
Returns:
dict[str, str]: path specification properties.
Raises:
dict: path specification properties.
"""
properties = {}
for property_name in cls.PROPERTY_NAMES:
# Note that we do not want to set the properties when not used.
if hasattr(path_spec, property_name):
properties[property_name] = getattr(path_spec, property_name)
return properties
[docs]
@classmethod
def IsSystemLevelTypeIndicator(cls, type_indicator):
"""Determines if the type indicator is at system-level.
Args:
type_indicator (str): type indicator.
Returns:
bool: True if the type indicator is at system-level.
"""
return type_indicator in cls._system_level_type_indicators
[docs]
@classmethod
def NewPathSpec(cls, type_indicator, **kwargs):
"""Creates a new path specification for the specific type indicator.
Args:
type_indicator (str): type indicator.
kwargs (dict): keyword arguments depending on the path specification.
Returns:
PathSpec: path specification.
Raises:
KeyError: if path specification is not registered.
"""
if type_indicator not in cls._path_spec_types:
raise KeyError(f"Path specification type: {type_indicator:s} not set.")
# An empty parent will cause parentless path specifications to raise
# so we conveniently remove it here.
if "parent" in kwargs and kwargs["parent"] is None:
del kwargs["parent"]
path_spec_type = cls._path_spec_types[type_indicator]
return path_spec_type(**kwargs)
[docs]
@classmethod
def RegisterPathSpec(cls, path_spec_type):
"""Registers a path specification type.
Args:
path_spec_type (type): path specification type.
Raises:
KeyError: if path specification type is already registered.
"""
type_indicator = path_spec_type.TYPE_INDICATOR
if type_indicator in cls._path_spec_types:
raise KeyError(f"Path specification type: {type_indicator:s} already set.")
cls._path_spec_types[type_indicator] = path_spec_type
if getattr(path_spec_type, "_IS_SYSTEM_LEVEL", False):
cls._system_level_type_indicators[type_indicator] = path_spec_type