mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Added comments and general code clean up
This commit is contained in:
parent
f4de27095c
commit
d81c2bc22d
@ -52,8 +52,8 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
private static final String NETWORK_LOCALE = "(network)";
|
private static final String NETWORK_LOCALE = "(network)";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All of the known XRY keys for call reports and the blackboard
|
* All of the known XRY keys for call reports and their corresponding
|
||||||
* attribute types they map to.
|
* blackboard attribute types, if any.
|
||||||
*/
|
*/
|
||||||
private enum XryKey {
|
private enum XryKey {
|
||||||
NUMBER("number", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER),
|
NUMBER("number", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER),
|
||||||
@ -97,16 +97,16 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
/**
|
/**
|
||||||
* Matches the display name of the xry key to the appropriate enum type.
|
* Matches the display name of the xry key to the appropriate enum type.
|
||||||
*
|
*
|
||||||
* It is assumed that XRY key string is recognized. Otherwise,
|
* It is assumed that XRY key string is recognized. Otherwise, an
|
||||||
* an IllegalArgumentException is thrown. Test all membership
|
* IllegalArgumentException is thrown. Test all membership with
|
||||||
* with contains() before hand.
|
* contains() before hand.
|
||||||
*
|
*
|
||||||
* @param xryKey
|
* @param xryKey
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static XryKey fromPair(XRYKeyValuePair pair) {
|
public static XryKey fromPair(XRYKeyValuePair pair) {
|
||||||
for(XryKey keyChoice : XryKey.values()) {
|
for (XryKey keyChoice : XryKey.values()) {
|
||||||
if(pair.hasKey(keyChoice.name)) {
|
if (pair.hasKey(keyChoice.name)) {
|
||||||
return keyChoice;
|
return keyChoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,20 +125,22 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
NONE(null);
|
NONE(null);
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
XryNamespace(String name) {
|
XryNamespace(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the display name of the XRY namespace is a recognized type.
|
* Indicates if the display name of the XRY namespace is a recognized
|
||||||
|
* type.
|
||||||
*
|
*
|
||||||
* @param xryNamespace
|
* @param xryNamespace
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean contains(String xryNamespace) {
|
public static boolean contains(String xryNamespace) {
|
||||||
String normalizedNamespace = xryNamespace.trim().toLowerCase();
|
String normalizedNamespace = xryNamespace.trim().toLowerCase();
|
||||||
for(XryNamespace keyChoice : XryNamespace.values()) {
|
for (XryNamespace keyChoice : XryNamespace.values()) {
|
||||||
if(normalizedNamespace.equals(keyChoice.name)) {
|
if (normalizedNamespace.equals(keyChoice.name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,19 +149,20 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches the display name of the xry namespace to the appropriate enum type.
|
* Matches the display name of the xry namespace to the appropriate enum
|
||||||
|
* type.
|
||||||
*
|
*
|
||||||
* It is assumed that XRY namespace string is recognized. Otherwise,
|
* It is assumed that XRY namespace string is recognized. Otherwise, an
|
||||||
* an IllegalArgumentException is thrown. Test all membership
|
* IllegalArgumentException is thrown. Test all membership with
|
||||||
* with contains() before hand.
|
* contains() before hand.
|
||||||
*
|
*
|
||||||
* @param xryNamespace
|
* @param xryNamespace
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static XryNamespace fromDisplayName(String xryNamespace) {
|
public static XryNamespace fromDisplayName(String xryNamespace) {
|
||||||
String normalizedNamespace = xryNamespace.trim().toLowerCase();
|
String normalizedNamespace = xryNamespace.trim().toLowerCase();
|
||||||
for(XryNamespace keyChoice : XryNamespace.values()) {
|
for (XryNamespace keyChoice : XryNamespace.values()) {
|
||||||
if(normalizedNamespace.equals(keyChoice.name)) {
|
if (normalizedNamespace.equals(keyChoice.name)) {
|
||||||
return keyChoice;
|
return keyChoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,7 +186,7 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
Optional<BlackboardAttribute> getBlackboardAttribute(String nameSpace, XRYKeyValuePair pair) {
|
Optional<BlackboardAttribute> getBlackboardAttribute(String nameSpace, XRYKeyValuePair pair) {
|
||||||
XryKey xryKey = XryKey.fromPair(pair);
|
XryKey xryKey = XryKey.fromPair(pair);
|
||||||
XryNamespace xryNamespace = XryNamespace.NONE;
|
XryNamespace xryNamespace = XryNamespace.NONE;
|
||||||
if(XryNamespace.contains(nameSpace)) {
|
if (XryNamespace.contains(nameSpace)) {
|
||||||
xryNamespace = XryNamespace.fromDisplayName(nameSpace);
|
xryNamespace = XryNamespace.fromDisplayName(nameSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +222,7 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
default:
|
default:
|
||||||
//Otherwise, the XryKey enum contains the correct BlackboardAttribute
|
//Otherwise, the XryKey enum contains the correct BlackboardAttribute
|
||||||
//type.
|
//type.
|
||||||
if(xryKey.getType() != null) {
|
if (xryKey.getType() != null) {
|
||||||
return Optional.of(new BlackboardAttribute(xryKey.getType(),
|
return Optional.of(new BlackboardAttribute(xryKey.getType(),
|
||||||
PARSER_NAME, pair.getValue()));
|
PARSER_NAME, pair.getValue()));
|
||||||
}
|
}
|
||||||
@ -253,7 +256,7 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
result = result.substring(0, deviceIndex);
|
result = result.substring(0, deviceIndex);
|
||||||
}
|
}
|
||||||
int networkIndex = result.toLowerCase().indexOf(NETWORK_LOCALE);
|
int networkIndex = result.toLowerCase().indexOf(NETWORK_LOCALE);
|
||||||
if(networkIndex != -1) {
|
if (networkIndex != -1) {
|
||||||
result = result.substring(0, networkIndex);
|
result = result.substring(0, networkIndex);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -272,13 +275,12 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
*
|
*
|
||||||
* 1/3/1990 1:23:54 AM UTC+4
|
* 1/3/1990 1:23:54 AM UTC+4
|
||||||
*
|
*
|
||||||
* In our current version of Java (openjdk-1.8.0.222), there is
|
* In our current version of Java (openjdk-1.8.0.222), there is a bug
|
||||||
* a bug with having the timezone offset (UTC+4 or GMT-7) at the
|
* with having the timezone offset (UTC+4 or GMT-7) at the end of the
|
||||||
* end of the date time input. This is fixed in later versions
|
* date time input. This is fixed in later versions of the JDK (9 and
|
||||||
* of the JDK (9 and beyond).
|
* beyond). https://bugs.openjdk.java.net/browse/JDK-8154050 Rather than
|
||||||
* https://bugs.openjdk.java.net/browse/JDK-8154050
|
* update the JDK to accommodate this, the components of the date time
|
||||||
* Rather than update the JDK to accommodate this, the components of
|
* string are reversed:
|
||||||
* the date time string are reversed:
|
|
||||||
*
|
*
|
||||||
* UTC+4 AM 1:23:54 1/3/1990
|
* UTC+4 AM 1:23:54 1/3/1990
|
||||||
*
|
*
|
||||||
@ -286,11 +288,11 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
*/
|
*/
|
||||||
String reversedDateTime = reverseOrderOfDateTimeComponents(dateTimeWithoutLocale);
|
String reversedDateTime = reverseOrderOfDateTimeComponents(dateTimeWithoutLocale);
|
||||||
/**
|
/**
|
||||||
* Furthermore, the DateTimeFormatter's timezone offset letter ('O') does
|
* Furthermore, the DateTimeFormatter's timezone offset letter ('O')
|
||||||
* not recognize UTC but recognizes GMT. According to
|
* does not recognize UTC but recognizes GMT. According to
|
||||||
* https://en.wikipedia.org/wiki/Coordinated_Universal_Time,
|
* https://en.wikipedia.org/wiki/Coordinated_Universal_Time, GMT only
|
||||||
* GMT only differs from UTC by at most 1 second and so substitution
|
* differs from UTC by at most 1 second and so substitution will only
|
||||||
* will only introduce a trivial amount of error.
|
* introduce a trivial amount of error.
|
||||||
*/
|
*/
|
||||||
String reversedDateTimeWithGMT = reversedDateTime.replace("UTC", "GMT");
|
String reversedDateTimeWithGMT = reversedDateTime.replace("UTC", "GMT");
|
||||||
TemporalAccessor result = DATE_TIME_PARSER.parseBest(reversedDateTimeWithGMT,
|
TemporalAccessor result = DATE_TIME_PARSER.parseBest(reversedDateTimeWithGMT,
|
||||||
@ -298,7 +300,7 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
LocalDateTime::from,
|
LocalDateTime::from,
|
||||||
OffsetDateTime::from);
|
OffsetDateTime::from);
|
||||||
//Query for the ZoneID
|
//Query for the ZoneID
|
||||||
if(result.query(TemporalQueries.zoneId()) == null) {
|
if (result.query(TemporalQueries.zoneId()) == null) {
|
||||||
//If none, assumed GMT+0.
|
//If none, assumed GMT+0.
|
||||||
return ZonedDateTime.of(LocalDateTime.from(result),
|
return ZonedDateTime.of(LocalDateTime.from(result),
|
||||||
ZoneId.of("GMT")).toEpochSecond();
|
ZoneId.of("GMT")).toEpochSecond();
|
||||||
@ -310,10 +312,7 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
|
|||||||
/**
|
/**
|
||||||
* Reverses the order of the date time components.
|
* Reverses the order of the date time components.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example: 1/3/1990 1:23:54 AM UTC+4 becomes UTC+4 AM 1:23:54 1/3/1990
|
||||||
* 1/3/1990 1:23:54 AM UTC+4
|
|
||||||
* becomes
|
|
||||||
* UTC+4 AM 1:23:54 1/3/1990
|
|
||||||
*
|
*
|
||||||
* @param dateTime
|
* @param dateTime
|
||||||
* @return
|
* @return
|
||||||
|
@ -64,8 +64,8 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
private static final int UNREAD = 0;
|
private static final int UNREAD = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All of the known XRY keys for message reports and the blackboard
|
* All of the known XRY keys for message reports and their corresponding
|
||||||
* attribute types they map to.
|
* blackboard attribute types, if any.
|
||||||
*/
|
*/
|
||||||
private enum XryKey {
|
private enum XryKey {
|
||||||
DELETED("deleted", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ISDELETED),
|
DELETED("deleted", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ISDELETED),
|
||||||
@ -121,17 +121,17 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
/**
|
/**
|
||||||
* Matches the display name of the xry key to the appropriate enum type.
|
* Matches the display name of the xry key to the appropriate enum type.
|
||||||
*
|
*
|
||||||
* It is assumed that XRY key string is recognized. Otherwise,
|
* It is assumed that XRY key string is recognized. Otherwise, an
|
||||||
* an IllegalArgumentException is thrown. Test all membership
|
* IllegalArgumentException is thrown. Test all membership with
|
||||||
* with contains() before hand.
|
* contains() before hand.
|
||||||
*
|
*
|
||||||
* @param xryKey
|
* @param xryKey
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static XryKey fromDisplayName(String name) {
|
public static XryKey fromDisplayName(String name) {
|
||||||
String normalizedName = name.trim().toLowerCase();
|
String normalizedName = name.trim().toLowerCase();
|
||||||
for(XryKey keyChoice : XryKey.values()) {
|
for (XryKey keyChoice : XryKey.values()) {
|
||||||
if(normalizedName.equals(keyChoice.name)) {
|
if (normalizedName.equals(keyChoice.name)) {
|
||||||
return keyChoice;
|
return keyChoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +157,8 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the display name of the XRY namespace is a recognized type.
|
* Indicates if the display name of the XRY namespace is a recognized
|
||||||
|
* type.
|
||||||
*
|
*
|
||||||
* @param xryNamespace
|
* @param xryNamespace
|
||||||
* @return
|
* @return
|
||||||
@ -172,19 +173,20 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches the display name of the xry namespace to the appropriate enum type.
|
* Matches the display name of the xry namespace to the appropriate enum
|
||||||
|
* type.
|
||||||
*
|
*
|
||||||
* It is assumed that XRY namespace string is recognized. Otherwise,
|
* It is assumed that XRY namespace string is recognized. Otherwise, an
|
||||||
* an IllegalArgumentException is thrown. Test all membership
|
* IllegalArgumentException is thrown. Test all membership with
|
||||||
* with contains() before hand.
|
* contains() before hand.
|
||||||
*
|
*
|
||||||
* @param xryNamespace
|
* @param xryNamespace
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static XryNamespace fromDisplayName(String xryNamespace) {
|
public static XryNamespace fromDisplayName(String xryNamespace) {
|
||||||
String normalizedNamespace = xryNamespace.trim().toLowerCase();
|
String normalizedNamespace = xryNamespace.trim().toLowerCase();
|
||||||
for(XryNamespace keyChoice : XryNamespace.values()) {
|
for (XryNamespace keyChoice : XryNamespace.values()) {
|
||||||
if(normalizedNamespace.equals(keyChoice.name)) {
|
if (normalizedNamespace.equals(keyChoice.name)) {
|
||||||
return keyChoice;
|
return keyChoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,7 +214,6 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the display name of the XRY key is a recognized type.
|
* Indicates if the display name of the XRY key is a recognized type.
|
||||||
*
|
*
|
||||||
@ -231,17 +232,17 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
/**
|
/**
|
||||||
* Matches the display name of the xry key to the appropriate enum type.
|
* Matches the display name of the xry key to the appropriate enum type.
|
||||||
*
|
*
|
||||||
* It is assumed that XRY key string is recognized. Otherwise,
|
* It is assumed that XRY key string is recognized. Otherwise, an
|
||||||
* an IllegalArgumentException is thrown. Test all membership
|
* IllegalArgumentException is thrown. Test all membership with
|
||||||
* with contains() before hand.
|
* contains() before hand.
|
||||||
*
|
*
|
||||||
* @param xryKey
|
* @param xryKey
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static XryMetaKey fromDisplayName(String name) {
|
public static XryMetaKey fromDisplayName(String name) {
|
||||||
String normalizedName = name.trim().toLowerCase();
|
String normalizedName = name.trim().toLowerCase();
|
||||||
for(XryMetaKey keyChoice : XryMetaKey.values()) {
|
for (XryMetaKey keyChoice : XryMetaKey.values()) {
|
||||||
if(normalizedName.equals(keyChoice.name)) {
|
if (normalizedName.equals(keyChoice.name)) {
|
||||||
return keyChoice;
|
return keyChoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,11 +254,11 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Message-SMS report artifacts can span multiple XRY entities and their
|
* Message-SMS report artifacts can span multiple XRY entities and their
|
||||||
* attributes can span multiple lines. The "Text" and "Message" keys are the only known key
|
* attributes can span multiple lines. The "Text" and "Message" keys are the
|
||||||
* value pair that can span multiple lines. Messages can be segmented,
|
* only known key value pair that can span multiple lines. Messages can be
|
||||||
* meaning that their "Text" and "Message" content can appear in multiple XRY entities.
|
* segmented, meaning that their "Text" and "Message" content can appear in
|
||||||
* Our goal for a segmented message is to aggregate all of the text pieces and
|
* multiple XRY entities. Our goal for a segmented message is to aggregate
|
||||||
* create 1 artifact.
|
* all of the text pieces and create 1 artifact.
|
||||||
*
|
*
|
||||||
* This parse implementation assumes that segments are contiguous and that
|
* This parse implementation assumes that segments are contiguous and that
|
||||||
* they ascend incrementally. There are checks in place to verify this
|
* they ascend incrementally. There are checks in place to verify this
|
||||||
@ -283,7 +284,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
String xryEntity = reader.nextEntity();
|
String xryEntity = reader.nextEntity();
|
||||||
List<BlackboardAttribute> attributes = getBlackboardAttributes(xryEntity, reader, referenceNumbersSeen);
|
List<BlackboardAttribute> attributes = getBlackboardAttributes(xryEntity, reader, referenceNumbersSeen);
|
||||||
//Only create artifacts with non-empty attributes.
|
//Only create artifacts with non-empty attributes.
|
||||||
if(!attributes.isEmpty()) {
|
if (!attributes.isEmpty()) {
|
||||||
BlackboardArtifact artifact = parent.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE);
|
BlackboardArtifact artifact = parent.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE);
|
||||||
artifact.addAttributes(attributes);
|
artifact.addAttributes(attributes);
|
||||||
}
|
}
|
||||||
@ -291,12 +292,8 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Extracts all blackboard attributes from the XRY Entity. This function will
|
||||||
* @param xryEntity
|
* unify any segmented text, if need be.
|
||||||
* @param reader
|
|
||||||
* @param referenceValues
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
private List<BlackboardAttribute> getBlackboardAttributes(String xryEntity,
|
private List<BlackboardAttribute> getBlackboardAttributes(String xryEntity,
|
||||||
XRYFileReader reader, Set<Integer> referenceValues) throws IOException {
|
XRYFileReader reader, Set<Integer> referenceValues) throws IOException {
|
||||||
@ -307,7 +304,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
List<BlackboardAttribute> attributes = new ArrayList<>();
|
List<BlackboardAttribute> attributes = new ArrayList<>();
|
||||||
|
|
||||||
//Count the key value pairs in the XRY entity.
|
//Count the key value pairs in the XRY entity.
|
||||||
int keyCount = countKeys(xryLines);
|
int keyCount = getCountOfKeyValuePairs(xryLines);
|
||||||
for (int i = 1; i <= keyCount; i++) {
|
for (int i = 1; i <= keyCount; i++) {
|
||||||
//Get the ith key value pair in the entity. Always expect to have
|
//Get the ith key value pair in the entity. Always expect to have
|
||||||
//a valid value.
|
//a valid value.
|
||||||
@ -333,8 +330,8 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
|
|
||||||
//Assume text and message are the only fields that can be segmented
|
//Assume text and message are the only fields that can be segmented
|
||||||
//among multiple XRY entities.
|
//among multiple XRY entities.
|
||||||
if (pair.hasKey(XryKey.TEXT.getDisplayName()) ||
|
if (pair.hasKey(XryKey.TEXT.getDisplayName())
|
||||||
pair.hasKey(XryKey.MESSAGE.getDisplayName())) {
|
|| pair.hasKey(XryKey.MESSAGE.getDisplayName())) {
|
||||||
String segmentedText = getSegmentedText(xryLines, reader, referenceValues);
|
String segmentedText = getSegmentedText(xryLines, reader, referenceValues);
|
||||||
pair = new XRYKeyValuePair(pair.getKey(),
|
pair = new XRYKeyValuePair(pair.getKey(),
|
||||||
//Assume text is segmented by word.
|
//Assume text is segmented by word.
|
||||||
@ -353,13 +350,13 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts the key value pairs in an XRY entity.
|
* Counts the key value pairs in an XRY entity. Skips counting the first
|
||||||
* Skips counting the first line as it is assumed to be the title.
|
* line as it is assumed to be the title.
|
||||||
*/
|
*/
|
||||||
private Integer countKeys(String[] xryEntity) {
|
private Integer getCountOfKeyValuePairs(String[] xryEntity) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 1; i < xryEntity.length; i++) {
|
for (int i = 1; i < xryEntity.length; i++) {
|
||||||
if(XRYKeyValuePair.isPair(xryEntity[i])) {
|
if (XRYKeyValuePair.isPair(xryEntity[i])) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,12 +364,12 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds up segmented message entities so that the text is unified in the
|
* Builds up segmented message entities so that the text is unified for a
|
||||||
* artifact.
|
* single artifact.
|
||||||
*
|
*
|
||||||
* @param referenceNumber Reference number that messages are group by
|
* @param reader File reader that is producing XRY entities.
|
||||||
* @param segmentNumber Segment number of the starting segment.
|
* @param referenceNumbersSeen All known references numbers up until this point.
|
||||||
* @param reader
|
* @param xryEntity The source XRY entity.
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -380,7 +377,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
Set<Integer> referenceNumbersSeen) throws IOException {
|
Set<Integer> referenceNumbersSeen) throws IOException {
|
||||||
Optional<Integer> referenceNumber = getMetaKeyValue(xryEntity, XryMetaKey.REFERENCE_NUMBER);
|
Optional<Integer> referenceNumber = getMetaKeyValue(xryEntity, XryMetaKey.REFERENCE_NUMBER);
|
||||||
//Check if there is any segmented text.
|
//Check if there is any segmented text.
|
||||||
if(!referenceNumber.isPresent()) {
|
if (!referenceNumber.isPresent()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +395,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
referenceNumbersSeen.add(referenceNumber.get());
|
referenceNumbersSeen.add(referenceNumber.get());
|
||||||
|
|
||||||
Optional<Integer> segmentNumber = getMetaKeyValue(xryEntity, XryMetaKey.SEGMENT_NUMBER);
|
Optional<Integer> segmentNumber = getMetaKeyValue(xryEntity, XryMetaKey.SEGMENT_NUMBER);
|
||||||
if(!segmentNumber.isPresent()) {
|
if (!segmentNumber.isPresent()) {
|
||||||
logger.log(Level.SEVERE, String.format("No segment "
|
logger.log(Level.SEVERE, String.format("No segment "
|
||||||
+ "number was found on the message entity"
|
+ "number was found on the message entity"
|
||||||
+ "with reference number [%d]", referenceNumber.get()));
|
+ "with reference number [%d]", referenceNumber.get()));
|
||||||
@ -414,8 +411,8 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
String[] nextEntityLines = nextEntity.split("\n");
|
String[] nextEntityLines = nextEntity.split("\n");
|
||||||
Optional<Integer> nextReferenceNumber = getMetaKeyValue(nextEntityLines, XryMetaKey.REFERENCE_NUMBER);
|
Optional<Integer> nextReferenceNumber = getMetaKeyValue(nextEntityLines, XryMetaKey.REFERENCE_NUMBER);
|
||||||
|
|
||||||
if (!nextReferenceNumber.isPresent() ||
|
if (!nextReferenceNumber.isPresent()
|
||||||
!Objects.equals(nextReferenceNumber, referenceNumber)) {
|
|| !Objects.equals(nextReferenceNumber, referenceNumber)) {
|
||||||
//Don't consume the next entity. It is not related
|
//Don't consume the next entity. It is not related
|
||||||
//to the current message thread.
|
//to the current message thread.
|
||||||
break;
|
break;
|
||||||
@ -429,7 +426,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
logger.log(Level.INFO, String.format("[XRY DSP] Processing [ %s ] "
|
logger.log(Level.INFO, String.format("[XRY DSP] Processing [ %s ] "
|
||||||
+ "segment with reference number [ %d ]", nextEntityLines[0], referenceNumber.get()));
|
+ "segment with reference number [ %d ]", nextEntityLines[0], referenceNumber.get()));
|
||||||
|
|
||||||
if(!nextSegmentNumber.isPresent()) {
|
if (!nextSegmentNumber.isPresent()) {
|
||||||
logger.log(Level.SEVERE, String.format("[XRY DSP] Segment with reference"
|
logger.log(Level.SEVERE, String.format("[XRY DSP] Segment with reference"
|
||||||
+ " number [ %d ] did not have a segment number associated with it."
|
+ " number [ %d ] did not have a segment number associated with it."
|
||||||
+ " It cannot be determined if the reconstructed text will be in order.", referenceNumber.get()));
|
+ " It cannot be determined if the reconstructed text will be in order.", referenceNumber.get()));
|
||||||
@ -440,16 +437,16 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
+ "text will be out of order.", nextSegmentNumber.get(), currentSegmentNumber));
|
+ "text will be out of order.", nextSegmentNumber.get(), currentSegmentNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
int keyCount = countKeys(nextEntityLines);
|
int keyCount = getCountOfKeyValuePairs(nextEntityLines);
|
||||||
for (int i = 1; i <= keyCount; i++) {
|
for (int i = 1; i <= keyCount; i++) {
|
||||||
XRYKeyValuePair pair = getKeyValuePairByIndex(nextEntityLines, i).get();
|
XRYKeyValuePair pair = getKeyValuePairByIndex(nextEntityLines, i).get();
|
||||||
if(pair.hasKey(XryKey.TEXT.getDisplayName()) ||
|
if (pair.hasKey(XryKey.TEXT.getDisplayName())
|
||||||
pair.hasKey(XryKey.MESSAGE.getDisplayName())) {
|
|| pair.hasKey(XryKey.MESSAGE.getDisplayName())) {
|
||||||
segmentedText.append(pair.getValue()).append(' ');
|
segmentedText.append(pair.getValue()).append(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nextSegmentNumber.isPresent()) {
|
if (nextSegmentNumber.isPresent()) {
|
||||||
currentSegmentNumber = nextSegmentNumber.get();
|
currentSegmentNumber = nextSegmentNumber.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,9 +460,10 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Extracts the value of the XRY meta key, if any.
|
||||||
*
|
*
|
||||||
* @param xryLines
|
* @param xryLines XRY entity to extract from.
|
||||||
* @param metaKey
|
* @param metaKey The key type to extract.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Optional<Integer> getMetaKeyValue(String[] xryLines, XryMetaKey metaKey) {
|
private Optional<Integer> getMetaKeyValue(String[] xryLines, XryMetaKey metaKey) {
|
||||||
@ -475,7 +473,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
XRYKeyValuePair pair = XRYKeyValuePair.from(xryLine);
|
XRYKeyValuePair pair = XRYKeyValuePair.from(xryLine);
|
||||||
if(pair.hasKey(metaKey.getDisplayName())) {
|
if (pair.hasKey(metaKey.getDisplayName())) {
|
||||||
try {
|
try {
|
||||||
return Optional.of(Integer.parseInt(pair.getValue()));
|
return Optional.of(Integer.parseInt(pair.getValue()));
|
||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
@ -488,9 +486,12 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Extracts the ith XRY Key Value pair in the XRY Entity.
|
||||||
*
|
*
|
||||||
* @param xryLines
|
* The total number of pairs can be determined via getCountOfKeyValuePairs().
|
||||||
* @param index
|
*
|
||||||
|
* @param xryLines XRY entity.
|
||||||
|
* @param index The requested Key Value pair.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Optional<XRYKeyValuePair> getKeyValuePairByIndex(String[] xryLines, int index) {
|
private Optional<XRYKeyValuePair> getKeyValuePairByIndex(String[] xryLines, int index) {
|
||||||
@ -498,12 +499,12 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
String namespace = "";
|
String namespace = "";
|
||||||
for (int i = 1; i < xryLines.length; i++) {
|
for (int i = 1; i < xryLines.length; i++) {
|
||||||
String xryLine = xryLines[i];
|
String xryLine = xryLines[i];
|
||||||
if(XryNamespace.contains(xryLine)) {
|
if (XryNamespace.contains(xryLine)) {
|
||||||
namespace = xryLine.trim();
|
namespace = xryLine.trim();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!XRYKeyValuePair.isPair(xryLine)) {
|
if (!XRYKeyValuePair.isPair(xryLine)) {
|
||||||
logger.log(Level.SEVERE, String.format("[XRY DSP] Expected a key value "
|
logger.log(Level.SEVERE, String.format("[XRY DSP] Expected a key value "
|
||||||
+ "pair on this line (in brackets) [ %s ], but one was not detected."
|
+ "pair on this line (in brackets) [ %s ], but one was not detected."
|
||||||
+ " Discarding...", xryLine));
|
+ " Discarding...", xryLine));
|
||||||
@ -513,17 +514,17 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
XRYKeyValuePair pair = XRYKeyValuePair.from(xryLine);
|
XRYKeyValuePair pair = XRYKeyValuePair.from(xryLine);
|
||||||
String value = pair.getValue();
|
String value = pair.getValue();
|
||||||
//Build up multiple lines.
|
//Build up multiple lines.
|
||||||
for (; (i+1) < xryLines.length
|
for (; (i + 1) < xryLines.length
|
||||||
&& !XRYKeyValuePair.isPair(xryLines[i+1])
|
&& !XRYKeyValuePair.isPair(xryLines[i + 1])
|
||||||
&& !XryNamespace.contains(xryLines[i+1]); i++) {
|
&& !XryNamespace.contains(xryLines[i + 1]); i++) {
|
||||||
String continuedValue = xryLines[i+1].trim();
|
String continuedValue = xryLines[i + 1].trim();
|
||||||
//Assume multi lined values are split by word.
|
//Assume multi lined values are split by word.
|
||||||
value = value + " " + continuedValue;
|
value = value + " " + continuedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair = new XRYKeyValuePair(pair.getKey(), value, namespace);
|
pair = new XRYKeyValuePair(pair.getKey(), value, namespace);
|
||||||
pairsParsed++;
|
pairsParsed++;
|
||||||
if(pairsParsed == index) {
|
if (pairsParsed == index) {
|
||||||
return Optional.of(pair);
|
return Optional.of(pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -534,15 +535,15 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
/**
|
/**
|
||||||
* Creates an attribute from the extracted key value pair.
|
* Creates an attribute from the extracted key value pair.
|
||||||
*
|
*
|
||||||
* @param nameSpace The namespace of this key value pair.
|
* @param nameSpace The namespace of this key value pair. It will have been
|
||||||
* It will have been verified beforehand, otherwise it will be NONE.
|
* verified beforehand, otherwise it will be NONE.
|
||||||
* @param key The recognized XRY key.
|
* @param key The recognized XRY key.
|
||||||
* @param value The value associated with that key.
|
* @param value The value associated with that key.
|
||||||
* @return Corresponding blackboard attribute, if any.
|
* @return Corresponding blackboard attribute, if any.
|
||||||
*/
|
*/
|
||||||
private Optional<BlackboardAttribute> getBlackboardAttribute(XRYKeyValuePair pair) {
|
private Optional<BlackboardAttribute> getBlackboardAttribute(XRYKeyValuePair pair) {
|
||||||
XryNamespace namespace = XryNamespace.NONE;
|
XryNamespace namespace = XryNamespace.NONE;
|
||||||
if(XryNamespace.contains(pair.getNamespace())) {
|
if (XryNamespace.contains(pair.getNamespace())) {
|
||||||
namespace = XryNamespace.fromDisplayName(pair.getNamespace());
|
namespace = XryNamespace.fromDisplayName(pair.getNamespace());
|
||||||
}
|
}
|
||||||
XryKey key = XryKey.fromDisplayName(pair.getKey());
|
XryKey key = XryKey.fromDisplayName(pair.getKey());
|
||||||
@ -620,7 +621,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
default:
|
default:
|
||||||
//Otherwise, the XryKey enum contains the correct BlackboardAttribute
|
//Otherwise, the XryKey enum contains the correct BlackboardAttribute
|
||||||
//type.
|
//type.
|
||||||
if(key.getType() != null) {
|
if (key.getType() != null) {
|
||||||
return Optional.of(new BlackboardAttribute(key.getType(),
|
return Optional.of(new BlackboardAttribute(key.getType(),
|
||||||
PARSER_NAME, pair.getValue()));
|
PARSER_NAME, pair.getValue()));
|
||||||
}
|
}
|
||||||
@ -648,7 +649,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
result = result.substring(0, deviceIndex);
|
result = result.substring(0, deviceIndex);
|
||||||
}
|
}
|
||||||
int networkIndex = result.toLowerCase().indexOf(NETWORK_LOCALE);
|
int networkIndex = result.toLowerCase().indexOf(NETWORK_LOCALE);
|
||||||
if(networkIndex != -1) {
|
if (networkIndex != -1) {
|
||||||
result = result.substring(0, networkIndex);
|
result = result.substring(0, networkIndex);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -667,13 +668,12 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
*
|
*
|
||||||
* 1/3/1990 1:23:54 AM UTC+4
|
* 1/3/1990 1:23:54 AM UTC+4
|
||||||
*
|
*
|
||||||
* In our current version of Java (openjdk-1.8.0.222), there is
|
* In our current version of Java (openjdk-1.8.0.222), there is a bug
|
||||||
* a bug with having the timezone offset (UTC+4 or GMT-7) at the
|
* with having the timezone offset (UTC+4 or GMT-7) at the end of the
|
||||||
* end of the date time input. This is fixed in later versions
|
* date time input. This is fixed in later versions of the JDK (9 and
|
||||||
* of the JDK (9 and beyond).
|
* beyond). https://bugs.openjdk.java.net/browse/JDK-8154050 Rather than
|
||||||
* https://bugs.openjdk.java.net/browse/JDK-8154050
|
* update the JDK to accommodate this, the components of the date time
|
||||||
* Rather than update the JDK to accommodate this, the components of
|
* string are reversed:
|
||||||
* the date time string are reversed:
|
|
||||||
*
|
*
|
||||||
* UTC+4 AM 1:23:54 1/3/1990
|
* UTC+4 AM 1:23:54 1/3/1990
|
||||||
*
|
*
|
||||||
@ -681,11 +681,11 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
*/
|
*/
|
||||||
String reversedDateTime = reverseOrderOfDateTimeComponents(dateTimeWithoutLocale);
|
String reversedDateTime = reverseOrderOfDateTimeComponents(dateTimeWithoutLocale);
|
||||||
/**
|
/**
|
||||||
* Furthermore, the DateTimeFormatter's timezone offset letter ('O') does
|
* Furthermore, the DateTimeFormatter's timezone offset letter ('O')
|
||||||
* not recognize UTC but recognizes GMT. According to
|
* does not recognize UTC but recognizes GMT. According to
|
||||||
* https://en.wikipedia.org/wiki/Coordinated_Universal_Time,
|
* https://en.wikipedia.org/wiki/Coordinated_Universal_Time, GMT only
|
||||||
* GMT only differs from UTC by at most 1 second and so substitution
|
* differs from UTC by at most 1 second and so substitution will only
|
||||||
* will only introduce a trivial amount of error.
|
* introduce a trivial amount of error.
|
||||||
*/
|
*/
|
||||||
String reversedDateTimeWithGMT = reversedDateTime.replace("UTC", "GMT");
|
String reversedDateTimeWithGMT = reversedDateTime.replace("UTC", "GMT");
|
||||||
TemporalAccessor result = DATE_TIME_PARSER.parseBest(reversedDateTimeWithGMT,
|
TemporalAccessor result = DATE_TIME_PARSER.parseBest(reversedDateTimeWithGMT,
|
||||||
@ -693,7 +693,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
LocalDateTime::from,
|
LocalDateTime::from,
|
||||||
OffsetDateTime::from);
|
OffsetDateTime::from);
|
||||||
//Query for the ZoneID
|
//Query for the ZoneID
|
||||||
if(result.query(TemporalQueries.zoneId()) == null) {
|
if (result.query(TemporalQueries.zoneId()) == null) {
|
||||||
//If none, assumed GMT+0.
|
//If none, assumed GMT+0.
|
||||||
return ZonedDateTime.of(LocalDateTime.from(result),
|
return ZonedDateTime.of(LocalDateTime.from(result),
|
||||||
ZoneId.of("GMT")).toEpochSecond();
|
ZoneId.of("GMT")).toEpochSecond();
|
||||||
@ -705,10 +705,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
|
|||||||
/**
|
/**
|
||||||
* Reverses the order of the date time components.
|
* Reverses the order of the date time components.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example: 1/3/1990 1:23:54 AM UTC+4 becomes UTC+4 AM 1:23:54 1/3/1990
|
||||||
* 1/3/1990 1:23:54 AM UTC+4
|
|
||||||
* becomes
|
|
||||||
* UTC+4 AM 1:23:54 1/3/1990
|
|
||||||
*
|
*
|
||||||
* @param dateTime
|
* @param dateTime
|
||||||
* @return
|
* @return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user