IBaseDataObject.java
package emissary.core;
import emissary.core.channels.SeekableByteChannelFactory;
import emissary.directory.DirectoryEntry;
import org.apache.commons.collections4.CollectionUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
public interface IBaseDataObject {
/**
* Define the merge policy values for parameter handling
*/
enum MergePolicy {
DISTINCT, KEEP_EXISTING, KEEP_ALL, DROP_EXISTING
}
/**
* Default separator when stringing parameter values together
*/
String DEFAULT_PARAM_SEPARATOR = ";";
/**
* @deprecated As of emissary 8.18.0, this method performs no operations
*/
@Deprecated(forRemoval = true)
default void checkForUnsafeDataChanges() {};
/**
* Return the data as a byte array. If using a channel to the data, calling this method will only return up to
* Integer.MAX_VALUE bytes of the original data.
*
* @return byte array of the data
* @see #getChannelFactory() as the preferred data accessor for larger data
*/
byte[] data();
/**
* Set BaseDataObjects data to byte array passed in.
*
* @param newData byte array to set replacing any existing data
*/
void setData(byte[] newData);
/**
* Set BaseDataObjects data to the portion of the byte array specified
*
* @param newData array containing desired data
* @param offset the index of the first byte to use
* @param length the number of bytes to use
*/
void setData(final byte[] newData, int offset, int length);
/**
* Checks if the data is defined with a non-zero length.
*
* @return if data is undefined or zero length.
*/
boolean hasContent() throws IOException;
/**
* Set the byte channel factory using whichever implementation is providing access to the data.
*
* @param sbcf the new channel factory to set on this object
*/
void setChannelFactory(final SeekableByteChannelFactory sbcf);
/**
* Returns a new InputStream to the data that this BaseDataObject contains.
* <p>
* NOTE 1: Mutating the data elements of this IBaseDataObject while reading from the InputStream will have indeterminate
* results.
* <p>
* NOTE 2: The calling code is responsible for closing the returned InputStream.
*
* @return a new stream that reads the data that this object contains, or null if this object has no data.
*/
InputStream newInputStream();
/**
* Returns the seekable byte channel factory containing a reference to the data
*
* @return the factory containing the data reference
*/
SeekableByteChannelFactory getChannelFactory();
/**
* Get the size of the channel referenced by this object
*
* @return the channel size
* @throws IOException if an error occurs with the underlying channel
*/
long getChannelSize() throws IOException;
/**
* Return length of the data, up to Integer.MAX_VALUE if the data is in a channel.
*
* Prefer use of {@link #getChannelSize()} going forwards
*
* @return length in bytes of the data
*/
int dataLength();
/**
* Set the header byte array
*
* @param arg1 the byte array of header data
*/
void setHeader(byte[] arg1);
/**
* Return a reference to the header byte array.
*
* @return byte array of header information or null if none
*/
byte[] header();
/**
* Set the footer byte array
*
* @param arg1 byte array of footer data
*/
void setFooter(byte[] arg1);
/**
* Return a reference to the footer byte array.
*
* @return byte array of footer data or null if none
*/
byte[] footer();
/**
* Get the value of headerEncoding. Tells how to interpret the header information.
*
* @return Value of headerEncoding.
*/
String getHeaderEncoding();
/**
* Set the value of headerEncoding for proper interpretation and processing later
*
* @param arg1 Value to assign to headerEncoding.
*/
void setHeaderEncoding(String arg1);
/**
* Get the classification string for the data
*
* @return String classification value
*/
String getClassification();
/**
* Set the classification.
*
* @param classification string classification value
*/
void setClassification(String classification);
/**
* Sets the number of children that the current agents spawned.
*
* @param num the number value to set
*/
void setNumChildren(int num);
/**
* Gets the number of children that have this as a parent
*
* @return the number of children that have this parent
*/
int getNumChildren();
/**
* Sets the number of siblings for this data object.
*
* @param num the number of siblings to set
*/
void setNumSiblings(int num);
/**
* Get the number of siblings
*
* @return the number of siblings including this one
*/
int getNumSiblings();
/**
* What number is this sibling in the family
*
* @param num the birthorder number value to set
*/
void setBirthOrder(int num);
/**
* Get this sibling number, count from one.
*
* @return the birth order of this sibling
*/
int getBirthOrder();
/**
* Return the header wrapped in a ByteBuffer class.
*
* @return buffer required by the HTML Velocity templates.
*/
@Deprecated
ByteBuffer headerBuffer();
/**
* Return the footer wrapped in a ByteBuffer class.
*
* @return buffer required by the HTML Velocity templates.
*/
@Deprecated
ByteBuffer footerBuffer();
/**
* Return theData wrapped in a ByteBuffer class.
*
* @return buffer required by the HTML Velocity templates.
*/
@Deprecated
ByteBuffer dataBuffer();
/**
* Get the font encoding string
*
* @return string name of font encoding for the data
*/
String getFontEncoding();
/**
* Set the font encoding string
*
* @param arg1 string name of font encoding for the data
*/
void setFontEncoding(String arg1);
/**
* Clear all metadata elements
*/
void clearParameters();
/**
* Determine if parameter is present
*
* @param key name of metadata element to check
*/
boolean hasParameter(String key);
/**
* Replace all of the metadata elements with a new set
*
* @param map the new set
*/
void setParameters(Map<? extends String, ? extends Object> map);
/**
* Set a new parameter value, deleting an old one
*
* @param key the name of the element
* @param val the value of the element
*/
void setParameter(String key, Object val);
/**
* Put a new metadata element into the map
*
* @param key the name of the element
* @param val the value of the element
*/
void putParameter(String key, Object val);
/**
* Put a collection of parameters into the metadata map
*
* @param m the map of new parameters
*/
void putParameters(Map<? extends String, ? extends Object> m);
/**
* Put a collection of parameters into the metadata map using the specified merge policy
*
* @param m the map of new parameters
* @param policy the merge policy
*/
void putParameters(Map<? extends String, ? extends Object> m, MergePolicy policy);
/**
* Merge a collection of parameters into the metadata map
*
* @param m the map of new parameters
*/
void mergeParameters(Map<? extends String, ? extends Object> m);
/**
* Put a collection of parameters into the metadata map uniquely
*
* @param m the map of new parameters
*/
void putUniqueParameters(Map<? extends String, ? extends Object> m);
/**
* Retrieve a specified metadata element
*
* @param key name of the metadata element
* @return the value or null if no such element
*/
List<Object> getParameter(String key);
/**
* Append data to the specified metadata element
*
* @param key name of the metadata element
* @param value the value to append
*/
void appendParameter(String key, CharSequence value);
/**
* Append data values to the specified metadata element
*
* @param key name of the metadata element
* @param values the values to append
*/
void appendParameter(String key, Iterable<? extends CharSequence> values);
/**
* Append data to the specified metadata element if it doesn't exist
*
* @param key name of the metadata element
* @param value the value to append
* @return true if the item is added, false if it already exists
*/
boolean appendUniqueParameter(String key, CharSequence value);
/**
* Retrieve a specified metadata element as a string value
*
* @param key name of the metadata element
* @return the string value or null if no such element
* @deprecated use {@link #getParameterAsString(String)} if a single metadata value is expected, or
* {@link #getParameterAsConcatString(String)} if it might be multivalued
*/
@Deprecated
default String getStringParameter(final String key) {
return getStringParameter(key, DEFAULT_PARAM_SEPARATOR);
}
/**
* Retrieve a specified metadata element as a string value
*
* @param key name of the metadata element
* @param sep the separator for multivalued fields
* @return the string value or null if no such element
* @deprecated use {@link #getParameterAsConcatString(String, String)}
*/
@Deprecated
@Nullable
default String getStringParameter(final String key, final String sep) {
final List<Object> obj = getParameter(key);
if (obj == null) {
return null;
} else if (obj.isEmpty()) {
return null;
} else if ((obj.size() == 1) && (obj.get(0) instanceof String)) {
return (String) obj.get(0);
} else if ((obj.size() == 1) && (obj.get(0) == null)) {
return null;
} else {
final StringBuilder sb = new StringBuilder();
for (final Object item : obj) {
if (sb.length() > 0) {
sb.append(sep);
}
sb.append(item);
}
return sb.toString();
}
}
/**
* Retrieve the Collection of metadata values identified by key where each element is converted to a string
*
* @param key name of the metadata element collection
* @return Collection of elements converted to strings
*/
default Collection<String> getParameterAsStrings(final String key) {
final var obj = getParameter(key);
if (CollectionUtils.isEmpty(obj) || ((obj.size() == 1) && (obj.get(0) == null))) {
return Collections.emptyList();
} else if ((obj.size() == 1) && (obj.get(0) instanceof String)) {
return Collections.singletonList((String) obj.get(0));
} else {
return obj.stream().map(String::valueOf).collect(Collectors.toList());
}
}
/**
* Retrieve the metadata value identified by key where the element is converted to a string
*
* @param key name of the metadata element
* @return parameter converted to strings
*/
String getParameterAsString(String key);
/**
* Retrieve a specified metadata element as a string of concatenated values
*
* @param key name of the metadata element
* @return the string value or null if no such element
*/
default String getParameterAsConcatString(final String key) {
return getParameterAsConcatString(key, DEFAULT_PARAM_SEPARATOR);
}
/**
* Retrieve a specified metadata element as a string of concatenated values
*
* @param key name of the metadata element
* @param sep the separator for multivalued fields
* @return the string value or null if no such element
*/
@Nullable
default String getParameterAsConcatString(final String key, final String sep) {
Collection<String> strings = getParameterAsStrings(key);
if (strings.stream().anyMatch(Objects::nonNull)) {
return String.join(sep, strings);
}
return null;
}
/**
* Retrieve all the metadata elements of this object
*
* @return map of metadata elements
*/
Map<String, Collection<Object>> getParameters();
/**
* Retrieve all the metadata elements of this object in a way that is processed for use external to this instance
*
* @return map of metadata elements
*/
Map<String, String> getCookedParameters();
/**
* Retrieve all of the current metadata keys
*
* @return set of charsequence keys
*/
Set<String> getParameterKeys();
/**
* Delete the specified metadata element named
*
* @param key the name of the metadata item to delete
* @return the object deleted of null if none
*/
List<Object> deleteParameter(String key);
/**
* Put the FILETYPE parameter
*
* @param arg1 the value to store
*/
void setFileType(String arg1);
/**
* Set FILETYPE parameter iff empty.
*
* @param arg1 the value of the filetype to set
* @param arg2 the list of things caller considers equal to being empty
* @return true if it was empty and set
* @deprecated Use {@link #setFileType(String)} instead.
*/
@Deprecated
@SuppressWarnings("AvoidObjectArrays")
boolean setFileTypeIfEmpty(String arg1, String[] arg2);
/**
* Set FILETYPE parameter iff empty using the built-in definition of empty
*
* @param arg1 the value of the filetype to set
* @return true if it was empty and set
*/
boolean setFileTypeIfEmpty(String arg1);
/**
* Return true if the file type is null or in one of the "don't care" set
*
* @since 3.3.3
*/
boolean isFileTypeEmpty();
/**
* Get the FILETYPE parameter
*
* @return the string value of the FILETYPE parameter
*/
String getFileType();
/**
* Disclose how many multipart alternative views of the data exist
*
* @return count of alternate views
*/
int getNumAlternateViews();
/**
* Return a specified multipart alternative view of the data
*
* @param arg1 the name of the view to retrieve
* @return byte array of alternate view data
*/
byte[] getAlternateView(String arg1);
/**
* Return a specified multipart alternative view of the data in a buffer
*
* @param arg1 the name of the view to retrieve
* @return buffer of alternate view data
*/
@Deprecated
ByteBuffer getAlternateViewBuffer(String arg1);
/**
* Add a multipart alternative view of the data
*
* @param name the name of the new view
* @param data the byte array of data for the view
*/
void addAlternateView(String name, byte[] data);
/**
* Add a multipart alternative view of the data
*
* @param name the name of the new view
* @param data the byte array conatining data for the view
* @param offset index of the first byte to use
* @param length number of bytes to use
*/
void addAlternateView(String name, byte[] data, int offset, int length);
/**
* Append the specified data to the alternate view
*
* @param name the name of the new view
* @param data the byte array of data for the view
*/
void appendAlternateView(String name, byte[] data);
/**
* Append to a multipart alternative view of the data
*
* @param name the name of the view
* @param data the byte array conatining data for the view
* @param offset index of the first byte to use
* @param length number of bytes to use
*/
void appendAlternateView(String name, byte[] data, int offset, int length);
/**
* Get the set of alt view names for new foreach loops
*
* @return set of alternate view names
*/
Set<String> getAlternateViewNames();
/**
* Get the alternate view map.
*
* @return map of alternate views, key = String, value = byte[]
*/
Map<String, byte[]> getAlternateViews();
/**
* Test for broken document
*
* @return true if broken
*/
boolean isBroken();
/**
* Set brokenness for document
*
* @param arg1 the message to record
*/
void setBroken(String arg1);
/**
* Get brokenness indicator message
*
* @return string message of what is broken
*/
String getBroken();
/**
* Returns the name of the file without the path with which the file will be written.
*
* @return the short name of the file (no path)
*/
String shortName();
/**
* Returns the filename associated with the data.
*
* @return the string name with path
*/
String getFilename();
/**
* Returns the internally generated identifier used to track the object
*
* @return a String representing the internal ID
*/
UUID getInternalId();
/**
* Set the filename
*
* @param f the new name of the data including path
*/
void setFilename(String f);
/**
* Return the current form of the data (top of the stack)
*
* @return string value of current form
*/
String currentForm();
/**
* Return the current form at specified position of the list
*
* @param i The specified position
* @return String containing the form or empty string if illegal position
*/
String currentFormAt(int i);
/**
* Check to see if this value is already on the stack of itinerary items
*
* @param val the string to look for
* @return the position where it was found or -1
*/
int searchCurrentForm(String val);
/**
* Check to see one of these values is on the stack of itinerary items
*
* @param values the List of strings to look for
* @return the String that was found out of the list sent in or null
*/
String searchCurrentForm(Collection<String> values);
/**
* Get the size of the itinerary stack
*
* @return size of form stack
*/
int currentFormSize();
/**
* Remove a form from the head of the list
*
* @return the new size of the itinerary stack
*/
String popCurrentForm();
/**
* Replace all current forms with specified
*
* @param form the new current form or null if none desired
*/
void replaceCurrentForm(String form);
/**
* Remove a form where ever it appears in the stack
*
* @param form the value to remove
* @return the number of elements removed from the stack
*/
int deleteCurrentForm(String form);
/**
* Remove a form at the specified location of the itinerary stack
*
* @param i the position to delete
* @return the new size of the itinerary stack
*/
int deleteCurrentFormAt(int i);
/**
* Add current form newForm at idx
*
* @param i the position to do the insert
* @param val the value to insert
* @return size of the new stack
*/
int addCurrentFormAt(int i, String val);
/**
* Add a form to the end of the list (the bottom of the stack)
*
* @param val the new value to add to the tail of the stack
* @return the new size of the itinerary stack
*/
int enqueueCurrentForm(String val);
/**
* Push a form onto the head of the list
*
* @param val the new value to push on the stack
* @return the new size of the itinerary stack
*/
int pushCurrentForm(String val);
/**
* Replaces the current form of the data with a new form Does a pop() followed by a push(newForm) to simulate what would
* happen in the old "one form at a time system"
*
* @param val value of the the new form of the data
*/
void setCurrentForm(String val);
/**
* Replaces the current form of the data with a form passed and potentially clears the entire form stack
*
* @param val value of the the new form of the data
* @param clearAllForms whether or not to clear the entire form stack
*/
void setCurrentForm(String val, boolean clearAllForms);
/**
* Return a clone the whole current form list Note this is not a reference to our private store
*
* @return ordered list of current forms
*/
List<String> getAllCurrentForms();
/**
* Move curForm to the top of the stack pushing everything above it down one slot
*
* @param curForm the form to pull to the top
*/
void pullFormToTop(String curForm);
/**
* Return BaseDataObjects info as a String.
*
* @return string value of this object
*/
@Override
String toString();
/**
* Record a processing error
*
* @param val the new error message to record
*/
void addProcessingError(String val);
/**
* Retrieve the processing error(s)
*
* @return string value of processing errors
*/
String getProcessingError();
/**
* Replace history with the new history
*
* @param history of new history strings to use
*/
void setHistory(TransformHistory history);
/**
* Get the transform history
*
* @return history of places visited
*/
TransformHistory getTransformHistory();
/**
* List of places the data object was carried to.
*
* @return List of strings making up the history
*/
List<String> transformHistory();
/**
* List of places the data object was carried to.
*
* @param includeCoordinated include the places that were coordinated
* @return List of strings making up the history
*/
List<String> transformHistory(boolean includeCoordinated);
/**
* Clear the transformation history
*/
void clearTransformHistory();
/**
* Appends the new key to the transform history. This is called by MobileAgent before moving to the new place. It
* usually adds the four-tuple of a place's key
*
* @see emissary.core.MobileAgent#agentControl
* @param key the new value to append
*/
void appendTransformHistory(String key);
/**
* Appends the new key to the transform history. This is called by MobileAgent before moving to the new place. It
* usually adds the four-tuple of a place's key. Coordinated history keys are meant for informational purposes and have
* no bearing on the routing algorithm. It is important to list the places visited in coordination, but should not
* report as the last place visited.
*
* @see emissary.core.MobileAgent#agentControl
* @param key the new value to append
* @param coordinated true if history entries are for informational purposes only
*/
void appendTransformHistory(String key, boolean coordinated);
/**
* Return what machine we are located on
*
* @return string local host name
*/
String whereAmI();
/**
* Return an SDE based on the last item in the transform history or null if empty
*
* @return last item in history
*/
DirectoryEntry getLastPlaceVisited();
/**
* Return an SDE based on the penultimate item in the transform history or null if empty
*
* @return penultimate item in history
*/
DirectoryEntry getPenultimatePlaceVisited();
/**
* Return true if the payload has been to a place matching the key passed in.
*
* @param pattern the key pattern to match
*/
boolean hasVisited(String pattern);
/**
* True if this payload hasn't had any processing yet Does not count parent processing as being for this payload
*
* @return true if not yet started
*/
boolean beforeStart();
/**
* Support deep copy via clone
*/
@Deprecated
IBaseDataObject clone() throws CloneNotSupportedException;
/**
* Print the parameters, nicely formatted
*/
String printMeta();
/**
* Get data object's priority.
*
* @return int priority (lower the number, higher the priority).
*/
int getPriority();
/**
* Set the data object's priority, typically based on input dir/file priority.
*
* @param priority int (lower the number, higher the priority).
*/
void setPriority(int priority);
/**
* Get the timestamp for when the object was created. This attribute will be used for data provenance.
*
* @return date - the timestamp the object was created
*/
Instant getCreationTimestamp();
/**
* Set the timestamp for when the object was created
*
* @param creationTimestamp - the date the object was created
*/
void setCreationTimestamp(Instant creationTimestamp);
/**
* Get the List of extracted records
*/
List<IBaseDataObject> getExtractedRecords();
/**
* Set/replace the list of extracted children
*
* @param records the list of extracted children
*/
void setExtractedRecords(List<? extends IBaseDataObject> records);
/**
* Add an extracted child
*
* @param record the extracted child to add
*/
void addExtractedRecord(IBaseDataObject record);
/**
* Add extracted children
*
* @param records the extracted children to add
*/
void addExtractedRecords(List<? extends IBaseDataObject> records);
/**
* Determine if this object has extracted records.
*
* @return true if this object has extracted records.
*/
boolean hasExtractedRecords();
/**
* Clear the list of extracted records.
*/
void clearExtractedRecords();
/**
* Get count of extracted records
*/
int getExtractedRecordCount();
/**
* Test if tree is outputable
*
* @return true if this tree is not able to be output, false otherwise
*/
boolean isOutputable();
/**
* Set whether or not the tree is able to be written out
*
* @param outputable true if this tree is not able to be output, false otherwise
*/
void setOutputable(boolean outputable);
/**
* Get ID
*
* @return the unique identifier of the IBaseDataObject
*/
String getId();
/**
* Set the unique identifier of the IBaseDataObject
*
* @param id the unique identifier of the IBaseDataObject
*/
void setId(String id);
/**
* Get the Work Bundle ID
*
* @return the unique identifier of the {@link emissary.pickup.WorkBundle}
*/
String getWorkBundleId();
/**
* Set the unique identifier of the {@link emissary.pickup.WorkBundle}
*
* @param workBundleId the unique identifier of the {@link emissary.pickup.WorkBundle}
*/
void setWorkBundleId(String workBundleId);
/**
* Get the Transaction ID
*
* @return the unique identifier of the transaction
*/
String getTransactionId();
/**
* Set the unique identifier of the transaction
*
* @param transactionId the unique identifier of the transaction
*/
void setTransactionId(String transactionId);
/**
* Return the top level document or null if there is none for this IBaseDataObject
*
* @return The TLD IBaseDataObject
*/
IBaseDataObject getTld();
}