11package edu .kit .datamanager .pit .domain ;
22
33import java .io .IOException ;
4+ import java .time .format .DateTimeFormatter ;
45import java .util .ArrayList ;
56import java .util .Arrays ;
67import java .util .Collection ;
1516import edu .kit .datamanager .pit .typeregistry .AttributeInfo ;
1617import edu .kit .datamanager .pit .typeregistry .ITypeRegistry ;
1718import org .apache .commons .lang3 .stream .Streams ;
18- import org .joda .time .DateTime ;
19- import org .joda .time .format .DateTimeFormatter ;
20- import org .joda .time .format .ISODateTimeFormat ;
19+ import java .time .ZonedDateTime ;
2120
2221/**
2322 * Simple operations on PID records.
24- *
23+ * <p>
2524 * Caches results e.g. for type queries
2625 */
2726public class Operations {
@@ -35,8 +34,8 @@ public class Operations {
3534 "21.T11148/397d831aa3a9d18eb52c"
3635 };
3736
38- private ITypeRegistry typeRegistry ;
39- private IIdentifierSystem identifierSystem ;
37+ private final ITypeRegistry typeRegistry ;
38+ private final IIdentifierSystem identifierSystem ;
4039
4140 public Operations (ITypeRegistry typeRegistry , IIdentifierSystem identifierSystem ) {
4241 this .typeRegistry = typeRegistry ;
@@ -45,133 +44,125 @@ public Operations(ITypeRegistry typeRegistry, IIdentifierSystem identifierSystem
4544
4645 /**
4746 * Tries to get the date when a FAIR DO was created from a PID record.
48- *
47+ * <p>
4948 * Strategy:
5049 * - try to get it from known "dateCreated" types
51- * - as a fallback, try to get it by its human readable name
52- *
50+ * - as a fallback, try to get it by its human- readable name
51+ * <p>
5352 * Semantic reasoning in some sense is planned but not yet supported.
5453 *
5554 * @param pidRecord the record to extract the information from.
56- * @return the date, if it could been extracted.
55+ * @return the date, if it could have been extracted.
5756 * @throws IOException on IO errors regarding resolving types.
5857 */
5958 public Optional <Date > findDateCreated (PIDRecord pidRecord ) throws IOException {
6059 /* try known types */
6160 List <String > knownDateTypes = Arrays .asList (Operations .KNOWN_DATE_CREATED );
6261 Optional <Date > date = knownDateTypes
63- .stream ()
64- .map (pidRecord ::getPropertyValues )
65- .map (Arrays ::asList )
66- .flatMap (List <String >::stream )
67- .map (this ::extractDate )
68- .filter (Optional <Date >::isPresent )
69- .map (Optional <Date >::get )
70- .sorted (Comparator .comparingLong (Date ::getTime ))
71- .findFirst ();
62+ .stream ()
63+ .map (pidRecord ::getPropertyValues )
64+ .map (Arrays ::asList )
65+ .flatMap (List <String >::stream )
66+ .map (this ::extractDate )
67+ .filter (Optional ::isPresent )
68+ .map (Optional ::get )
69+ .min (Comparator .comparingLong (Date ::getTime ));
7270 if (date .isPresent ()) {
7371 return date ;
7472 }
7573
7674 Collection <AttributeInfo > types = new ArrayList <>();
7775 List <CompletableFuture <?>> futures = Streams .failableStream (
7876 pidRecord .getPropertyIdentifiers ().stream ())
79- .filter (attributePid -> this .identifierSystem .isPidRegistered (attributePid ))
80- .map (attributePid -> {
81- return this .typeRegistry
77+ .filter (this .identifierSystem ::isPidRegistered )
78+ .map (attributePid -> this .typeRegistry
8279 .queryAttributeInfo (attributePid )
83- .thenAcceptAsync (types ::add );
84- })
80+ .thenAcceptAsync (types ::add ))
8581 .collect (Collectors .toList ());
8682 CompletableFuture .allOf (futures .toArray (new CompletableFuture [0 ]));
8783
8884 /*
89- * as a last fallback, try find types with human readable names containing
85+ * as a last fallback, try to find types with human- readable names containing
9086 * "dateCreated" or "createdAt" or "creationDate".
9187 *
9288 * This can be removed as soon as we have some default FAIR DO types new type
9389 * definitions can refer to (e.g. "extend" them or declare the same meaning as
9490 * our known types, see above)
9591 */
9692 return types
97- .stream ()
98- .filter (type ->
99- type .name ().equalsIgnoreCase ("dateCreated" )
100- || type .name ().equalsIgnoreCase ("createdAt" )
101- || type .name ().equalsIgnoreCase ("creationDate" ))
102- .map (type -> pidRecord .getPropertyValues (type .pid ()))
103- .map (Arrays ::asList )
104- .flatMap (List <String >::stream )
105- .map (this ::extractDate )
106- .filter (Optional <Date >::isPresent )
107- .map (Optional <Date >::get )
108- .sorted (Comparator .comparingLong (Date ::getTime ))
109- .findFirst ();
93+ .stream ()
94+ .filter (type ->
95+ type .name ().equalsIgnoreCase ("dateCreated" )
96+ || type .name ().equalsIgnoreCase ("createdAt" )
97+ || type .name ().equalsIgnoreCase ("creationDate" ))
98+ .map (type -> pidRecord .getPropertyValues (type .pid ()))
99+ .map (Arrays ::asList )
100+ .flatMap (List <String >::stream )
101+ .map (this ::extractDate )
102+ .filter (Optional ::isPresent )
103+ .map (Optional ::get )
104+ .min (Comparator .comparingLong (Date ::getTime ));
110105 }
111106
112107 /**
113108 * Tries to get the date when a FAIR DO was modified from a PID record.
114- *
109+ * <p>
115110 * Strategy:
116111 * - try to get it from known "dateModified" types
117- * - as a fallback, try to get it by its human readable name
118- *
112+ * - as a fallback, try to get it by its human- readable name
113+ * <p>
119114 * Semantic reasoning in some sense is planned but not yet supported.
120115 *
121116 * @param pidRecord the record to extract the information from.
122- * @return the date, if it could been extracted.
117+ * @return the date, if it could have been extracted.
123118 * @throws IOException on IO errors regarding resolving types.
124119 */
125120 public Optional <Date > findDateModified (PIDRecord pidRecord ) throws IOException {
126121 /* try known types */
127122 List <String > knownDateTypes = Arrays .asList (Operations .KNOWN_DATE_MODIFIED );
128123 Optional <Date > date = knownDateTypes
129- .stream ()
130- .map (pidRecord ::getPropertyValues )
131- .map (Arrays ::asList )
132- .flatMap (List <String >::stream )
133- .map (this ::extractDate )
134- .filter (Optional <Date >::isPresent )
135- .map (Optional <Date >::get )
136- .sorted (Comparator .comparingLong (Date ::getTime ))
137- .findFirst ();
124+ .stream ()
125+ .map (pidRecord ::getPropertyValues )
126+ .map (Arrays ::asList )
127+ .flatMap (List <String >::stream )
128+ .map (this ::extractDate )
129+ .filter (Optional ::isPresent )
130+ .map (Optional ::get )
131+ .min (Comparator .comparingLong (Date ::getTime ));
138132 if (date .isPresent ()) {
139133 return date ;
140134 }
141135
142136 Collection <AttributeInfo > types = new ArrayList <>();
143137 List <CompletableFuture <?>> futures = Streams .failableStream (pidRecord .getPropertyIdentifiers ().stream ())
144- .filter (attributePid -> this .identifierSystem .isPidRegistered (attributePid ))
145- .map (attributePid -> {
146- return this .typeRegistry
138+ .filter (this .identifierSystem ::isPidRegistered )
139+ .map (attributePid -> this .typeRegistry
147140 .queryAttributeInfo (attributePid )
148- .thenAcceptAsync (types ::add );
149- })
141+ .thenAcceptAsync (types ::add ))
150142 .collect (Collectors .toList ());
151143 CompletableFuture .allOf (futures .toArray (new CompletableFuture [0 ]));
152144
153145 /*
154- * as a last fallback, try find types with human readable names containing
146+ * as a last fallback, try to find types with human- readable names containing
155147 * "dateModified" or "lastModified" or "modificationDate".
156148 *
157149 * This can be removed as soon as we have some default FAIR DO types new type
158150 * definitions can refer to (e.g. "extend" them or declare the same meaning as
159151 * our known types, see above)
160152 */
161153 return types
162- .stream ()
163- .filter (type ->
164- type .name ().equalsIgnoreCase ("dateModified" )
165- || type .name ().equalsIgnoreCase ("lastModified" )
166- || type .name ().equalsIgnoreCase ("modificationDate" ))
167- .map (type -> pidRecord .getPropertyValues (type .pid ()))
168- .map (Arrays ::asList )
169- .flatMap (List <String >::stream )
170- .map (this ::extractDate )
171- .filter (Optional <Date >::isPresent )
172- .map (Optional <Date >::get )
173- .sorted (Comparator .comparingLong (Date ::getTime ))
174- .findFirst ();
154+ .stream ()
155+ .filter (type ->
156+ type .name ().equalsIgnoreCase ("dateModified" )
157+ || type .name ().equalsIgnoreCase ("lastModified" )
158+ || type .name ().equalsIgnoreCase ("modificationDate" ))
159+ .map (type -> pidRecord .getPropertyValues (type .pid ()))
160+ .map (Arrays ::asList )
161+ .flatMap (List <String >::stream )
162+ .map (this ::extractDate )
163+ .filter (Optional ::isPresent )
164+ .map (Optional ::get )
165+ .min (Comparator .comparingLong (Date ::getTime ));
175166 }
176167
177168 /**
@@ -181,10 +172,10 @@ public Optional<Date> findDateModified(PIDRecord pidRecord) throws IOException {
181172 * @return the extracted Date object.
182173 */
183174 protected Optional <Date > extractDate (String dateString ) {
184- DateTimeFormatter dateFormatter = ISODateTimeFormat . dateTime () ;
175+ DateTimeFormatter dateFormatter = DateTimeFormatter . ISO_DATE_TIME ;
185176 try {
186- DateTime dateTime = dateFormatter . parseDateTime (dateString );
187- return Optional .of (dateTime .toDate ( ));
177+ ZonedDateTime dateTime = ZonedDateTime . parse (dateString , dateFormatter );
178+ return Optional .of (Date . from ( dateTime .toInstant () ));
188179 } catch (Exception e ) {
189180 return Optional .empty ();
190181 }
0 commit comments