1212import java .util .Objects ;
1313import java .util .Optional ;
1414import java .util .stream .Collectors ;
15- import java .util .stream .Stream ;
16- import org .apache .commons .io .FilenameUtils ;
1715import org .apache .commons .lang3 .StringUtils ;
1816import org .apache .commons .lang3 .Validate ;
1917import org .apache .commons .lang3 .builder .EqualsBuilder ;
2220import org .jooq .lambda .Unchecked ;
2321import org .slf4j .Logger ;
2422import org .slf4j .LoggerFactory ;
23+ import com .fasterxml .jackson .databind .DeserializationFeature ;
24+ import com .fasterxml .jackson .databind .ObjectMapper ;
2525import com .helger .genericode .v10 .CodeListDocument ;
2626import com .helger .genericode .v10 .Identification ;
2727import com .helger .genericode .v10 .LongName ;
2828import com .helger .genericode .v10 .Row ;
2929import com .helger .genericode .v10 .SimpleCodeList ;
3030import com .helger .genericode .v10 .Value ;
31+ import eu .europa .ted .eforms .sdk .domain .codelist .CodelistForIndex ;
32+ import eu .europa .ted .eforms .sdk .domain .codelist .CodelistsIndex ;
3133import eu .europa .ted .eforms .sdk .entity .SdkCodelist ;
3234import eu .europa .ted .eforms .sdk .entity .SdkEntityFactory ;
3335import eu .europa .ted .util .GenericodeTools ;
@@ -40,7 +42,7 @@ public class SdkCodelistRepository extends HashMap<String, SdkCodelist> {
4042 private transient Path codelistsDir ;
4143 private String sdkVersion ;
4244
43- private final Map <String , CodeListDocument > codelistContentsByCodelistId ;
45+ private final Map <String , Pair < Path , CodeListDocument >> codelistInfoByCodelistIds ;
4446
4547 @ SuppressWarnings ("unused" )
4648 private SdkCodelistRepository () {
@@ -55,7 +57,7 @@ public SdkCodelistRepository(final String sdkVersion, final Path codelistsDir) {
5557 "Codelists directory [%s] is not found or not a directory" , codelistsDir );
5658
5759 try {
58- this .codelistContentsByCodelistId = getCodelistContentsByCodelistIds (codelistsDir );
60+ this .codelistInfoByCodelistIds = getCodelistInfoByCodelistIds (codelistsDir );
5961 } catch (IOException e ) {
6062 throw new RuntimeException (
6163 MessageFormat .format ("Failed to load codelists from [{0}]" , codelistsDir ), e );
@@ -86,13 +88,15 @@ public SdkCodelist getOrDefault(final Object codelistId, final SdkCodelist defau
8688
8789 private Optional <SdkCodelist > loadSdkCodelist (final String codeListId )
8890 throws InstantiationException {
89- logger .debug ("Loading SDK codelist with ID [{}] for SDK version [{}] from path [{}]" ,
90- codeListId , sdkVersion , codelistsDir );
91+ logger .debug ("Loading SDK codelist with ID [{}] for SDK version [{}]" , codeListId , sdkVersion );
9192
9293 // Find the SDK codelist .gc file that corresponds to the passed reference.
9394 // Stream the data from that file.
9495 final Optional <CodeListDocument > codelist =
95- Optional .ofNullable (codelistContentsByCodelistId .get (codeListId ));
96+ Optional .ofNullable (codelistInfoByCodelistIds .get (codeListId ))
97+ .map (Unchecked .function ((Pair <Path , CodeListDocument > codelistInfo ) -> Optional
98+ .ofNullable (codelistInfo .getValue ())
99+ .orElse (getCodelistContents (codelistInfo .getKey ()))));
96100
97101 if (codelist .isEmpty ()) {
98102 return Optional .empty ();
@@ -127,8 +131,8 @@ private Optional<SdkCodelist> loadSdkCodelist(final String codeListId)
127131 final Optional <SdkCodelist > result = Optional .of (SdkEntityFactory .getSdkCodelist (sdkVersion ,
128132 codeListId , codelistVersion .orElse (null ), codes , parentId ));
129133
130- logger .debug ("Finished loading SDK codelist with ID [{}] for SDK version [{}] from path [{}]" ,
131- codeListId , sdkVersion , codelistsDir );
134+ logger .debug ("Finished loading SDK codelist with ID [{}] for SDK version [{}]" , codeListId ,
135+ sdkVersion );
132136
133137 return result ;
134138 }
@@ -158,69 +162,67 @@ public static Optional<String> extractLongNameWithIdentifier(
158162 }
159163
160164 /**
161- * Loads all of the codelists by reading codelist files under a given a folder.
165+ * Loads the paths of all of the codelists by looking for and reading the codelists index.
166+ * <p>
167+ * The result is a map which associates information (file path and a placeholder for contents) for
168+ * each codelist with its ID.
162169 *
163- * @param codelistsDir The folder containing all codelist files
164- * @return A map of codelist IDs to codelist contents
170+ * @param codelistsDir The folder containing the codelists index and files
171+ * @return A map of codelist IDs to pairs of codelist file paths and contents
165172 * @throws IOException If there are failures when discovering and parsing the files
166173 */
167- private Map <String , CodeListDocument > getCodelistContentsByCodelistIds ( final Path codelistsDir )
168- throws IOException {
174+ private Map <String , Pair < Path , CodeListDocument >> getCodelistInfoByCodelistIds (
175+ final Path codelistsDir ) throws IOException {
169176 Validate .notNull (codelistsDir , "Undefined codelists directory" );
170177 Validate .isTrue (Files .isDirectory (codelistsDir ),
171178 MessageFormat .format ("Not a directory: {0}" , codelistsDir ));
172179
173- logger . debug ( "Getting codelist file paths from directory [{}]" , codelistsDir );
180+ final Path indexFile = Path . of ( codelistsDir . toString (), "codelists.json" );
174181
175- final int depth = 1 ; // Flat folder, not recursive for now.
182+ logger .debug ("Loading codelists index from [{}]" , indexFile );
183+ CodelistsIndex codelistsIndex =
184+ createObjectMapper ().readValue (indexFile .toFile (), CodelistsIndex .class );
185+
186+ final Map <String , Pair <Path , CodeListDocument >> result = new HashMap <>();
187+ codelistsIndex .getCodelists ().stream ().forEach ((CodelistForIndex codelist ) -> {
188+ final String codelistId = codelist .getId ();
189+ final Path codelistPath = Path .of (codelistsDir .toString (), codelist .getFilename ());
190+
191+ logger .trace ("Adding path [{}] for codelist [{}]" , codelistPath , codelistId );
192+ if (!Files .isRegularFile (codelistPath )) {
193+ logger .warn ("Codelist file [{}] not found. Codelist [{}] will be skipped" , codelistPath ,
194+ codelistId );
195+ } else {
196+ // We're only interested in populating the codelist filepaths for now.
197+ // The contents of each document will be populated for each codelist later, on demand.
198+ result .put (codelistId , Pair .of (codelistPath , null ));
199+ }
200+ });
201+
202+ return result ;
176203
177- try (Stream <Path > walk = Files .walk (codelistsDir , depth )) {
178- return walk
179- .filter (this ::isGenericodeFile )
180- .map (Unchecked .function (this ::getCodelistIdAndContents ))
181- .filter (Objects ::nonNull )
182- .collect (Collectors .toMap (Pair ::getKey , Pair ::getValue ));
183- }
184204 }
185205
186206 /**
187- * Gets the codelist ID from a codelist file.
207+ * Gets the codelist contents from a codelist file.
188208 *
189209 * @param codelistPath The codelist file's path
190- * @return The codelist ID and the codelist file's contents as a key/value pair
210+ * @return The codelist file's contents
191211 * @throws FileNotFoundException If the codelist file's path is undefined or not an existing file
192212 */
193- private Pair <String , CodeListDocument > getCodelistIdAndContents (Path codelistPath )
194- throws FileNotFoundException {
213+ private CodeListDocument getCodelistContents (Path codelistPath ) throws FileNotFoundException {
195214 Validate .notNull (codelistPath , "Undefined codelist path" );
196215
197216 if (!Files .isRegularFile (codelistPath )) {
198217 throw new FileNotFoundException (codelistPath .toString ());
199218 }
200219
201- final Optional <CodeListDocument > codelist =
202- Optional .ofNullable (GenericodeTools .getMarshaller ().read (codelistPath ));
203-
204- if (codelist .isPresent ()) {
205- // We use the longName as a ID, PK in the the DB.
206- // But for the filenames we do not always follow this convention.
207- // So we need to map.
208- return codelist
209- .map (CodeListDocument ::getIdentification )
210- .map ((Identification identification ) -> identification .getLongNameAtIndex (0 ))
211- .map (LongName ::getValue )
212- .map ((String longName ) -> Pair .of (longName , codelist .get ()))
213- .orElse (null );
214- }
215-
216- return null ;
220+ logger .debug ("Reading from file [{}]" , codelistPath );
221+ return Optional .ofNullable (GenericodeTools .getMarshaller ().read (codelistPath )).orElse (null );
217222 }
218223
219- private boolean isGenericodeFile (final Path path ) {
220- return path != null
221- && Files .isRegularFile (path )
222- && GenericodeTools .EXTENSION_DOT_GC
223- .equals (MessageFormat .format (".{0}" , FilenameUtils .getExtension (path .toString ())));
224+ private ObjectMapper createObjectMapper () {
225+ return new ObjectMapper ().configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
224226 }
225227
226228 @ Override
0 commit comments