package com.constellio.app.services.importExport.settings; import static com.constellio.model.entities.schemas.MetadataValueType.REFERENCE; import static java.util.Arrays.asList; import static org.apache.commons.lang3.StringUtils.substringAfterLast; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.StringUtils; import org.jdom2.Document; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import com.constellio.app.entities.schemasDisplay.MetadataDisplayConfig; import com.constellio.app.entities.schemasDisplay.SchemaDisplayConfig; import com.constellio.app.entities.schemasDisplay.SchemaTypeDisplayConfig; import com.constellio.app.modules.rm.model.labelTemplate.LabelTemplateManager; import com.constellio.app.modules.rm.services.ValueListItemSchemaTypeBuilder; import com.constellio.app.modules.rm.services.ValueListItemSchemaTypeBuilder.ValueListItemSchemaTypeBuilderOptions; import com.constellio.app.modules.rm.services.ValueListServices; import com.constellio.app.services.factories.AppLayerFactory; import com.constellio.app.services.importExport.settings.model.ImportedCollectionSettings; import com.constellio.app.services.importExport.settings.model.ImportedConfig; import com.constellio.app.services.importExport.settings.model.ImportedDataEntry; import com.constellio.app.services.importExport.settings.model.ImportedLabelTemplate; import com.constellio.app.services.importExport.settings.model.ImportedMetadata; import com.constellio.app.services.importExport.settings.model.ImportedMetadata.ListType; import com.constellio.app.services.importExport.settings.model.ImportedMetadataSchema; import com.constellio.app.services.importExport.settings.model.ImportedSequence; import com.constellio.app.services.importExport.settings.model.ImportedSettings; import com.constellio.app.services.importExport.settings.model.ImportedTab; import com.constellio.app.services.importExport.settings.model.ImportedTaxonomy; import com.constellio.app.services.importExport.settings.model.ImportedType; import com.constellio.app.services.importExport.settings.model.ImportedValueList; import com.constellio.app.services.schemasDisplay.SchemaTypesDisplayTransactionBuilder; import com.constellio.app.services.schemasDisplay.SchemasDisplayManager; import com.constellio.data.dao.services.sequence.SequencesManager; import com.constellio.data.utils.ImpossibleRuntimeException; import com.constellio.data.utils.KeyListMap; import com.constellio.model.entities.Language; import com.constellio.model.entities.Taxonomy; import com.constellio.model.entities.configs.SystemConfiguration; import com.constellio.model.entities.configs.SystemConfigurationType; import com.constellio.model.entities.schemas.Metadata; import com.constellio.model.entities.schemas.MetadataSchema; import com.constellio.model.entities.schemas.MetadataSchemaType; import com.constellio.model.entities.schemas.MetadataSchemaTypes; import com.constellio.model.entities.schemas.MetadataValueType; import com.constellio.model.frameworks.validation.ValidationErrors; import com.constellio.model.frameworks.validation.ValidationException; import com.constellio.model.services.configs.SystemConfigurationsManager; import com.constellio.model.services.schemas.MetadataSchemaTypesAlteration; import com.constellio.model.services.schemas.MetadataSchemasManager; import com.constellio.model.services.schemas.builders.MetadataBuilder; import com.constellio.model.services.schemas.builders.MetadataSchemaBuilder; import com.constellio.model.services.schemas.builders.MetadataSchemaBuilderRuntimeException; import com.constellio.model.services.schemas.builders.MetadataSchemaTypeBuilder; import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder; public class SettingsImportServices { static final String CLASSIFIED_IN_GROUP_LABEL = "classifiedInGroupLabel"; static final String TAXO_PREFIX = "taxo"; static final String TYPE = "Type"; static final String TAXO_SUFFIX = TYPE; static final String TITLE_FR = "title_fr"; static final String TITLE_EN = "title_en"; static final String TAXO = "taxo"; static final String CONFIG = "config"; static final String VALUE = "value"; static final String INVALID_COLLECTION_CODE = "invalidCollectionCode"; static final String COLLECTION_CODE_NOT_FOUND = "collectionCodeNotFound"; static final String CODE = "code"; static final String INVALID_VALUE_LIST_CODE = "InvalidValueListCode"; static final String EMPTY_TAXONOMY_CODE = "EmptyTaxonomyCode"; static final String INVALID_TAXONOMY_CODE_PREFIX = "InvalidTaxonomyCodePrefix"; static final String INVALID_TAXONOMY_CODE_SUFFIX = "InvalidTaxonomyCodeSuffix"; static final String DDV_PREFIX = "ddvUSR"; static final String INVALID_CONFIGURATION_VALUE = "invalidConfigurationValue"; static final String CONFIGURATION_NOT_FOUND = "configurationNotFound"; static final String EMPTY_TYPE_CODE = "emptyTypeCode"; static final String EMPTY_TAB_CODE = "emptyTabCode"; static final String NULL_DEFAULT_SCHEMA = "nullDefaultSchema"; static final String INVALID_SCHEMA_CODE = "invalidSchemaCode"; static final String DUPLICATE_SCHEMA_CODE = "duplicateSchemaCode"; static final String SEQUENCE_VALUE_NOT_NUMERICAL = "sequenceValueNotNumerical"; static final String SEQUENCE_ID_NOT_NUMERICAL = "sequenceIdNotNumerical"; static final String SEQUENCE_ID_NULL_OR_EMPTY = "sequenceIdNullOrEmpty"; AppLayerFactory appLayerFactory; SystemConfigurationsManager systemConfigurationsManager; MetadataSchemasManager schemasManager; ValueListServices valueListServices; public SettingsImportServices(AppLayerFactory appLayerFactory) { this.appLayerFactory = appLayerFactory; } public void importSettings(ImportedSettings settings) throws ValidationException { ValidationErrors validationErrors = new ValidationErrors(); systemConfigurationsManager = appLayerFactory.getModelLayerFactory().getSystemConfigurationsManager(); schemasManager = appLayerFactory.getModelLayerFactory().getMetadataSchemasManager(); validate(settings, validationErrors); run(settings); } private void run(ImportedSettings settings) throws ValidationException { importLabelTemplates(settings); importGlobalConfigurations(settings); importSequences(settings); for (final ImportedCollectionSettings collectionSettings : settings.getCollectionsSettings()) { importCollectionConfigurations(collectionSettings); } } private void importLabelTemplates(ImportedSettings settings) { LabelTemplateManager labelTemplateManager = appLayerFactory.getLabelTemplateManager(); for (ImportedLabelTemplate template : settings.getImportedLabelTemplates()) { try { Document document = new SAXBuilder().build(new StringReader(template.getXml())); labelTemplateManager.addUpdateLabelTemplate(document); } catch (JDOMException | IOException e) { throw new RuntimeException(e); } } } private void importCollectionConfigurations(final ImportedCollectionSettings collectionSettings) { final String collectionCode = collectionSettings.getCode(); final MetadataSchemaTypes schemaTypes = schemasManager.getSchemaTypes(collectionCode); importCollectionsValueLists(collectionSettings, collectionCode, schemaTypes); importCollectionTaxonomies(collectionSettings, collectionCode, schemaTypes); importCollectionTypes(collectionSettings, collectionCode, schemaTypes); } private Map<Language, String> asLabelsMapOnlyContainingSystemLanguageLabel(String label) { Map<Language, String> labels = new HashMap<Language, String>(); labels.put(Language.French, label); return labels; } private void importCollectionTypes(final ImportedCollectionSettings settings, String collection, final MetadataSchemaTypes schemaTypes) { final KeyListMap<String, String> newMetadatas = new KeyListMap<>(); schemasManager.modify(collection, new MetadataSchemaTypesAlteration() { @Override public void alter(MetadataSchemaTypesBuilder types) { for (ImportedType importedType : settings.getTypes()) { MetadataSchemaTypeBuilder typeBuilder; if (!schemaTypes.hasType(importedType.getCode())) { typeBuilder = types.createNewSchemaType(importedType.getCode()); } else { typeBuilder = types.getSchemaType(importedType.getCode()); } if (importedType.getLabel() != null) { typeBuilder.setLabels(asLabelsMapOnlyContainingSystemLanguageLabel(importedType.getLabel())); } MetadataSchemaBuilder defaultSchemaBuilder = typeBuilder.getDefaultSchema(); ImportedMetadataSchema importedDefaultSchema = importedType.getDefaultSchema(); if (importedType.getDefaultSchema() != null && importedType.getDefaultSchema().getLabel() != null) { typeBuilder.getDefaultSchema().setLabels(asLabelsMapOnlyContainingSystemLanguageLabel( importedType.getDefaultSchema().getLabel())); } importCustomSchemata(types, importedType.getCustomSchemata(), typeBuilder, newMetadatas); importSchemaMetadatas(typeBuilder, importedType.getDefaultSchema(), defaultSchemaBuilder, types, newMetadatas); importCustomSchemataMetadatas(types, importedType.getCustomSchemata(), typeBuilder, newMetadatas); } } }); MetadataSchemaTypes newSchemaTypes = schemasManager.getSchemaTypes(schemaTypes.getCollection()); updateSettingsMetadata(settings, newSchemaTypes, newMetadatas); } private void applySchemasLists(SchemaTypesDisplayTransactionBuilder transactionBuilder, ImportedMetadataSchema importedSchema, MetadataSchema schema) { SchemaDisplayConfig schemaDisplayConfig = transactionBuilder.updateSchemaDisplayConfig(schema); if (!importedSchema.getFormMetadatas().isEmpty()) { List<String> codes = toCodesAddingEssentials(importedSchema.getFormMetadatas(), schema); schemaDisplayConfig = schemaDisplayConfig.withFormMetadataCodes(codes); } if (!importedSchema.getDisplayMetadatas().isEmpty()) { List<String> codes = toCodes(importedSchema.getDisplayMetadatas(), schema); schemaDisplayConfig = schemaDisplayConfig.withDisplayMetadataCodes(codes); } if (!importedSchema.getSearchMetadatas().isEmpty()) { List<String> codes = toCodes(importedSchema.getSearchMetadatas(), schema); schemaDisplayConfig = schemaDisplayConfig.withSearchResultsMetadataCodes(codes); } if (!importedSchema.getTableMetadatas().isEmpty()) { List<String> codes = toCodes(importedSchema.getTableMetadatas(), schema); schemaDisplayConfig = schemaDisplayConfig.withTableMetadataCodes(codes); } transactionBuilder.addReplacing(schemaDisplayConfig); } private List<String> toCodes(List<String> localCodes, MetadataSchema schema) { List<String> codes = new ArrayList<>(); for (String localCode : localCodes) { if (localCode.contains("_")) { codes.add(schema.getCode() + "_" + substringAfterLast(localCode, "_")); } else { codes.add(schema.getCode() + "_" + localCode); } } return codes; } private List<String> toCodesAddingEssentials(List<String> localCodes, MetadataSchema schema) { List<String> codes = new ArrayList<>(); List<String> requiredEssentialMetadatas = new ArrayList<>(); List<String> facultativeEssentialMetadatas = new ArrayList<>(); List<String> specifiedLocalCodes = toCodes(localCodes, schema); for (Metadata metadata : schema.getMetadatas().onlyEssentialMetadatasAndCodeTitle().onlyNonSystemReserved() .onlyManuals()) { if (!specifiedLocalCodes.contains(metadata.getCode())) { if (metadata.isDefaultRequirement()) { requiredEssentialMetadatas.add(metadata.getCode()); } else { facultativeEssentialMetadatas.add(metadata.getCode()); } } } codes.addAll(specifiedLocalCodes); codes.addAll(requiredEssentialMetadatas); codes.addAll(facultativeEssentialMetadatas); return codes; } private void updateSettingsMetadata(ImportedCollectionSettings settings, MetadataSchemaTypes schemaTypes, KeyListMap<String, String> newMetadatas) { SchemasDisplayManager displayManager = appLayerFactory.getMetadataSchemasDisplayManager(); SchemaTypesDisplayTransactionBuilder transactionBuilder = new SchemaTypesDisplayTransactionBuilder(schemaTypes, displayManager); for (ImportedType importedType : settings.getTypes()) { setupTypeDisplayConfig(transactionBuilder, importedType, schemaTypes.getSchemaType(importedType.getCode()), newMetadatas); } for (ImportedType importedType : settings.getTypes()) { MetadataSchemaType schemaType = schemaTypes.getSchemaType(importedType.getCode()); applySchemasLists(transactionBuilder, importedType.getDefaultSchema(), schemaType.getDefaultSchema()); for (ImportedMetadataSchema customSchema : importedType.getCustomSchemata()) { applySchemasLists(transactionBuilder, customSchema, schemaType.getCustomSchema(customSchema.getCode())); } } displayManager.execute(transactionBuilder.build()); } private void setupTypeDisplayConfig(SchemaTypesDisplayTransactionBuilder transactionBuilder, ImportedType importedType, MetadataSchemaType type, KeyListMap<String, String> newMetadatas) { SchemaTypeDisplayConfig schemaTypeDisplayConfig = transactionBuilder.updateSchemaTypeDisplayConfig(type); Map<String, Map<Language, String>> allTabs = new HashMap<>(schemaTypeDisplayConfig.getMetadataGroup()); Map<String, Map<String, Boolean>> schemaMetasDisplayVisibility, schemaMetasFormVisibility, schemaMetasSearchVisibility, schemaMetasTablesVisibility; schemaMetasDisplayVisibility = getSchemasMetasVisibility(type, importedType, ListType.DISPLAY, newMetadatas); schemaMetasFormVisibility = getSchemasMetasVisibility(type, importedType, ListType.FORM, newMetadatas); schemaMetasSearchVisibility = getSchemasMetasVisibility(type, importedType, ListType.SEARCH, newMetadatas); schemaMetasTablesVisibility = getSchemasMetasVisibility(type, importedType, ListType.TABLES, newMetadatas); for (ImportedMetadata importedMetadata : importedType.getDefaultSchema().getAllMetadata()) { for (MetadataSchema schema : type.getAllSchemas()) { Metadata metadata = schema.getMetadata(importedMetadata.getCode()); configureMetadataDisplay(metadata, importedMetadata, transactionBuilder, allTabs); } } for (ImportedMetadataSchema importedMetadataSchema : importedType.getCustomSchemata()) { for (ImportedMetadata importedMetadata : importedMetadataSchema.getAllMetadata()) { String code = type.getCode() + "_" + importedMetadataSchema.getCode() + "_" + importedMetadata.getCode(); Metadata metadata = type.getMetadata(code); configureMetadataDisplay(metadata, importedMetadata, transactionBuilder, allTabs); } } for (MetadataSchema schema : type.getAllSchemas()) { SchemaDisplayConfig schemaDisplayConfig = transactionBuilder.updateSchemaDisplayConfig(schema); schemaDisplayConfig = schemaDisplayConfig.withDisplayMetadataCodes(apply(schema.getCode(), schemaDisplayConfig.getDisplayMetadataCodes(), schemaMetasDisplayVisibility.get(schema.getLocalCode()))); schemaDisplayConfig = schemaDisplayConfig.withFormMetadataCodes(apply(schema.getCode(), schemaDisplayConfig.getFormMetadataCodes(), schemaMetasFormVisibility.get(schema.getLocalCode()))); schemaDisplayConfig = schemaDisplayConfig.withSearchResultsMetadataCodes(apply(schema.getCode(), schemaDisplayConfig.getSearchResultsMetadataCodes(), schemaMetasSearchVisibility.get(schema.getLocalCode()))); schemaDisplayConfig = schemaDisplayConfig.withTableMetadataCodes(apply(schema.getCode(), schemaDisplayConfig.getTableMetadataCodes(), schemaMetasTablesVisibility.get(schema.getLocalCode()))); transactionBuilder.addReplacing(schemaDisplayConfig); } transactionBuilder.add(schemaTypeDisplayConfig.withMetadataGroup(allTabs)); } private void configureMetadataDisplay(Metadata metadata, ImportedMetadata importedMetadata, SchemaTypesDisplayTransactionBuilder transactionBuilder, Map<String, Map<Language, String>> allTabs) { MetadataDisplayConfig displayConfig = transactionBuilder.updateMetadataDisplayConfig(metadata); String tab = importedMetadata.getTab(); if ("default".equals(tab)) { tab = ""; } if (StringUtils.isNotBlank(importedMetadata.getTab())) { displayConfig = displayConfig.withMetadataGroup(tab); if (!allTabs.containsKey(tab) && StringUtils.isNotBlank(tab)) { Map<Language, String> labels = new HashMap<>(); for (Language language : metadata.getLabels().keySet()) { labels.put(language, tab); } allTabs.put(tab, labels); } } if (importedMetadata.getAdvanceSearchable() != null) { displayConfig = displayConfig.withVisibleInAdvancedSearchStatus(importedMetadata.getAdvanceSearchable()); } transactionBuilder.addReplacing(displayConfig); } private List<String> apply(String schema, List<String> metadatas, Map<String, Boolean> metasVisibility) { if (metasVisibility == null) { return metadatas; } List<String> modifiedMetadatas = new ArrayList<>(metadatas); for (Map.Entry<String, Boolean> entry : metasVisibility.entrySet()) { String code = schema + "_" + entry.getKey(); if (Boolean.TRUE == entry.getValue()) { if (!modifiedMetadatas.contains(code)) { int indexComment = modifiedMetadatas.indexOf(schema + "_comments"); if (indexComment == -1) { modifiedMetadatas.add(code); } else { modifiedMetadatas.add(indexComment - 1, code); } } } else if (Boolean.FALSE == entry.getValue()) { modifiedMetadatas.remove(code); } } return modifiedMetadatas; } private Map<String, Map<String, Boolean>> getSchemasMetasVisibility(MetadataSchemaType type, ImportedType importedType, ListType listType, KeyListMap<String, String> newMetadatas) { Map<String, Map<String, Boolean>> schemasMetadatas = new HashMap<>(); for (Map.Entry<String, List<String>> newMetadataInSchemaEntry : newMetadatas.getMapEntries()) { if (listType == ListType.DISPLAY || listType == ListType.FORM) { if (newMetadataInSchemaEntry.getKey().equals(type.getDefaultSchema().getCode())) { for (MetadataSchema schema : type.getAllSchemas()) { for (String metadataLocalCode : newMetadataInSchemaEntry.getValue()) { Map<String, Boolean> schemaMetadatas = schemasMetadatas.get(schema.getLocalCode()); if (schemaMetadatas == null) { schemaMetadatas = new HashMap<>(); schemasMetadatas.put(schema.getLocalCode(), schemaMetadatas); } schemaMetadatas.put(metadataLocalCode, true); } } } if (newMetadataInSchemaEntry.getKey().startsWith(type.getCode() + "_")) { for (String metadataLocalCode : newMetadataInSchemaEntry.getValue()) { Map<String, Boolean> schemaMetadatas = schemasMetadatas.get(newMetadataInSchemaEntry.getKey()); if (schemaMetadatas == null) { schemaMetadatas = new HashMap<>(); schemasMetadatas.put(newMetadataInSchemaEntry.getKey(), schemaMetadatas); } schemaMetadatas.put(metadataLocalCode, true); } } } } for (ImportedMetadata metadata : importedType.getDefaultSchema().getAllMetadata()) { Boolean visibleInAllSchemas = metadata.getVisible(listType); if (visibleInAllSchemas != null) { for (MetadataSchema schema : type.getAllSchemas()) { Map<String, Boolean> schemaMetadatas = schemasMetadatas.get(schema.getLocalCode()); if (schemaMetadatas == null) { schemaMetadatas = new HashMap<>(); schemasMetadatas.put(schema.getLocalCode(), schemaMetadatas); } schemaMetadatas.put(metadata.getCode(), visibleInAllSchemas); } } else { List<String> visibleInSchemas = metadata.getVisibleInListInSchemas(listType); if (visibleInSchemas != null && visibleInSchemas.size() > 0) { for (MetadataSchema schema : type.getAllSchemas()) { Map<String, Boolean> schemaMetadatas = schemasMetadatas.get(schema.getLocalCode()); if (schemaMetadatas == null) { schemaMetadatas = new HashMap<>(); schemasMetadatas.put(schema.getLocalCode(), schemaMetadatas); } schemaMetadatas.put(metadata.getCode(), visibleInSchemas.contains(schema.getLocalCode())); } } } } for (ImportedMetadataSchema metadataSchema : importedType.getCustomSchemata()) { Map<String, Boolean> schemaMetadatas = schemasMetadatas.get(metadataSchema.getCode()); if (schemaMetadatas == null) { schemaMetadatas = new HashMap<>(); schemasMetadatas.put(metadataSchema.getCode(), schemaMetadatas); } for (ImportedMetadata metadata : metadataSchema.getAllMetadata()) { Boolean visibleInCustomSchemas = metadata.getVisible(listType); if (visibleInCustomSchemas != null) { schemaMetadatas.put(metadata.getCode(), visibleInCustomSchemas); } } } return schemasMetadatas; } private void importCustomSchemata(MetadataSchemaTypesBuilder types, List<ImportedMetadataSchema> importedMetadataSchemata, MetadataSchemaTypeBuilder typeBuilder, KeyListMap<String, String> newMetadatas) { for (ImportedMetadataSchema importedMetadataSchema : importedMetadataSchemata) { importSchema(types, typeBuilder, importedMetadataSchema, newMetadatas); } } private void importCustomSchemataMetadatas(MetadataSchemaTypesBuilder types, List<ImportedMetadataSchema> importedMetadataSchemata, MetadataSchemaTypeBuilder typeBuilder, KeyListMap<String, String> newMetadatas) { for (ImportedMetadataSchema importedMetadataSchema : importedMetadataSchemata) { MetadataSchemaBuilder customSchemaBuilder = typeBuilder.getCustomSchema(importedMetadataSchema.getCode()); importSchemaMetadatas(typeBuilder, importedMetadataSchema, customSchemaBuilder, types, newMetadatas); } } private void importSchema(MetadataSchemaTypesBuilder types, MetadataSchemaTypeBuilder typeBuilder, ImportedMetadataSchema importedMetadataSchema, KeyListMap<String, String> newMetadatas) { MetadataSchemaBuilder schemaBuilder; if (!typeBuilder.hasSchema(importedMetadataSchema.getCode())) { schemaBuilder = typeBuilder.createCustomSchema(importedMetadataSchema.getCode(), new HashMap<String, String>()); } else { schemaBuilder = typeBuilder.getCustomSchema(importedMetadataSchema.getCode()); } if (importedMetadataSchema.getLabel() != null) { schemaBuilder.setLabels(asLabelsMapOnlyContainingSystemLanguageLabel(importedMetadataSchema.getLabel())); } } private void importSchemaMetadatas(MetadataSchemaTypeBuilder typeBuilder, ImportedMetadataSchema importedMetadataSchema, MetadataSchemaBuilder schemaBuilder, MetadataSchemaTypesBuilder typesBuilder, KeyListMap<String, String> newMetadatas) { for (ImportedMetadata importedMetadata : importedMetadataSchema.getAllMetadata()) { createAndAddMetadata(typeBuilder, schemaBuilder, importedMetadata, typesBuilder); newMetadatas.add(schemaBuilder.getCode(), importedMetadata.getCode()); } } private void createAndAddMetadata(MetadataSchemaTypeBuilder typeBuilder, MetadataSchemaBuilder schemaBuilder, ImportedMetadata importedMetadata, MetadataSchemaTypesBuilder typesBuilder) { MetadataBuilder metadataBuilder; try { metadataBuilder = schemaBuilder.get(importedMetadata.getCode()); } catch (MetadataSchemaBuilderRuntimeException.NoSuchMetadata e) { metadataBuilder = schemaBuilder.create(importedMetadata.getCode()); if (metadataBuilder.getInheritance() == null) { MetadataValueType type = EnumUtils.getEnum(MetadataValueType.class, importedMetadata.getType()); metadataBuilder.setType(type); if (type == REFERENCE) { MetadataSchemaTypeBuilder referencedTypeBuilder = typesBuilder .getSchemaType(importedMetadata.getReferencedType()); metadataBuilder.defineReferences().set(referencedTypeBuilder); } } } if (StringUtils.isNotBlank(importedMetadata.getLabel())) { Map<Language, String> labels = new HashMap<>(); labels.put(Language.French, importedMetadata.getLabel()); metadataBuilder.setLabels(labels); } setMetadataDataEntry(typesBuilder, schemaBuilder, importedMetadata, metadataBuilder); if (importedMetadata.getDuplicable() != null) { metadataBuilder.setDuplicable(importedMetadata.getDuplicable()); } if (importedMetadata.getEnabled() != null) { metadataBuilder.setEnabled(importedMetadata.getEnabled()); } if (importedMetadata.getEncrypted() != null) { metadataBuilder.setEncrypted(importedMetadata.getEncrypted()); } if (importedMetadata.getEssential() != null) { metadataBuilder.setEssential(importedMetadata.getEssential()); } if (importedMetadata.getEssentialInSummary() != null) { metadataBuilder.setEssentialInSummary(importedMetadata.getEssentialInSummary()); } metadataBuilder.setInputMask(importedMetadata.getInputMask()); if (importedMetadata.getMultiLingual() != null) { metadataBuilder.setMultiLingual(importedMetadata.getMultiLingual()); } if (importedMetadata.getMultiValue() != null) { metadataBuilder.setMultivalue(importedMetadata.getMultiValue()); } if (importedMetadata.getRecordAutoComplete() != null) { metadataBuilder.setSchemaAutocomplete(importedMetadata.getRecordAutoComplete()); } if (importedMetadata.getRequired() != null) { metadataBuilder.setDefaultRequirement(importedMetadata.getRequired()); } if (importedMetadata.getSearchable() != null) { metadataBuilder.setSearchable(importedMetadata.getSearchable()); } if (importedMetadata.getSortable() != null) { metadataBuilder.setSortable(importedMetadata.getSortable()); } if (importedMetadata.getUnique() != null) { metadataBuilder.setUniqueValue(importedMetadata.getUnique()); } if (importedMetadata.getUnmodifiable() != null) { metadataBuilder.setUnmodifiable(importedMetadata.getUnmodifiable()); } if ("default".equals(schemaBuilder.getCode())) { for (String targetSchema : importedMetadata.getEnabledIn()) { String prefixedSchemaCode = typeBuilder.getCode() + "_" + targetSchema; MetadataSchemaBuilder metadataSchemaBuilder = typesBuilder.getSchema(prefixedSchemaCode); if (metadataSchemaBuilder != null) { MetadataBuilder targetSchemaMetadataBuilder = metadataSchemaBuilder.get(importedMetadata.getCode()); targetSchemaMetadataBuilder.setEnabled(true); if (importedMetadata.getRequiredIn().contains(targetSchema)) { targetSchemaMetadataBuilder.setDefaultRequirement(true); } } } } } private void setMetadataDataEntry(MetadataSchemaTypesBuilder typesBuilder, MetadataSchemaBuilder schemaBuilder, ImportedMetadata importedMetadata, MetadataBuilder metadataBuilder) { ImportedDataEntry dataEntry = importedMetadata.getDataEntry(); if (dataEntry != null) { switch (dataEntry.getType().toLowerCase()) { case "sequence": setSequenceDataEntry(metadataBuilder, dataEntry); break; case "jexl": metadataBuilder.defineDataEntry().asJexlScript(dataEntry.getPattern()); break; case "calculated": metadataBuilder.defineDataEntry().asCalculated(dataEntry.getCalculator()); break; case "copied": if (StringUtils.isNotBlank(dataEntry.getReferencedMetadata())) { MetadataBuilder referenceMetadataBuilder = schemaBuilder.getMetadata(dataEntry.getReferencedMetadata()); MetadataSchemaTypeBuilder referencedSchemaType = typesBuilder .getSchemaType(referenceMetadataBuilder.getAllowedReferencesBuilder().getSchemaType()); MetadataBuilder copiedMetadataBuilder = referencedSchemaType.getDefaultSchema() .getMetadata(dataEntry.getCopiedMetadata()); metadataBuilder.defineDataEntry().asCopied(referenceMetadataBuilder, copiedMetadataBuilder); } break; default: break; } } } private void setSequenceDataEntry(MetadataBuilder metadataBuilder, ImportedDataEntry dataEntry) { if (StringUtils.isNotBlank(dataEntry.getFixedSequenceCode())) { metadataBuilder.defineDataEntry().asFixedSequence(dataEntry.getFixedSequenceCode()); } else { metadataBuilder.defineDataEntry().asSequenceDefinedByMetadata(dataEntry.getMetadataProvidingSequenceCode()); } } private void importCollectionTaxonomies(final ImportedCollectionSettings settings, final String collectionCode, final MetadataSchemaTypes schemaTypes) { final Map<Taxonomy, ImportedTaxonomy> taxonomies = new HashMap<>(); valueListServices = new ValueListServices(appLayerFactory, collectionCode); schemasManager.modify(collectionCode, new MetadataSchemaTypesAlteration() { @Override public void alter(MetadataSchemaTypesBuilder typesBuilder) { for (final ImportedTaxonomy importedTaxonomy : settings.getTaxonomies()) { String typeCode = importedTaxonomy.getCode(); String taxoCode = StringUtils.substringBetween(typeCode, TAXO, TYPE); String title = null; if (StringUtils.isNotBlank(importedTaxonomy.getTitle())) { title = importedTaxonomy.getTitle(); } if (!schemaTypes.hasType(importedTaxonomy.getCode())) { Taxonomy taxonomy = valueListServices.lazyCreateTaxonomy(typesBuilder, taxoCode, title); if (importedTaxonomy.getVisibleOnHomePage() != null) { taxonomy = taxonomy.withVisibleInHomeFlag(importedTaxonomy.getVisibleOnHomePage()); } taxonomy = taxonomy.withTitle(importedTaxonomy.getTitle()) .withUserIds(importedTaxonomy.getUserIds()) .withGroupIds(importedTaxonomy.getGroupIds()); taxonomies.put(taxonomy, importedTaxonomy); } else { Taxonomy taxonomy = getTaxonomyFor(collectionCode, importedTaxonomy); if (StringUtils.isNotBlank(importedTaxonomy.getTitle())) { taxonomy = taxonomy.withTitle(importedTaxonomy.getTitle()); } if (importedTaxonomy.getVisibleOnHomePage() != null) { taxonomy = taxonomy.withVisibleInHomeFlag(importedTaxonomy.getVisibleOnHomePage()); } if (!importedTaxonomy.getGroupIds().isEmpty()) { taxonomy = taxonomy.withGroupIds(importedTaxonomy.getGroupIds()); } if (!importedTaxonomy.getUserIds().isEmpty()) { taxonomy = taxonomy.withUserIds(importedTaxonomy.getUserIds()); } String groupLabel = CLASSIFIED_IN_GROUP_LABEL; List<MetadataSchemaType> classifiedTypes = valueListServices.getClassifiedSchemaTypes(taxonomy); for (String classifiedType : importedTaxonomy.getClassifiedTypes()) { boolean found = false; for (MetadataSchemaType type : classifiedTypes) { if (classifiedType.equals(type.getCode())) { found = true; break; } } if (!found) { valueListServices .createAMultivalueClassificationMetadataInGroup(taxonomy, classifiedType, groupLabel, groupLabel); } } List<MetadataSchemaType> missing = new ArrayList<>(); for (MetadataSchemaType type : classifiedTypes) { if (!importedTaxonomy.getClassifiedTypes().contains(type.getCode())) { missing.add(type); } } appLayerFactory.getModelLayerFactory().getTaxonomiesManager().editTaxonomy(taxonomy); } } } }); for (Map.Entry<Taxonomy, ImportedTaxonomy> entry : taxonomies.entrySet()) { Taxonomy taxonomy = entry.getKey(); ImportedTaxonomy importedTaxonomy = entry.getValue(); appLayerFactory.getModelLayerFactory().getTaxonomiesManager() .addTaxonomy(taxonomy, schemasManager); String groupLabel = CLASSIFIED_IN_GROUP_LABEL; for (String classifiedType : importedTaxonomy.getClassifiedTypes()) { valueListServices .createAMultivalueClassificationMetadataInGroup(taxonomy, classifiedType, groupLabel, groupLabel); } } } private Taxonomy getTaxonomyFor(String collectionCode, ImportedTaxonomy importedTaxonomy) { return appLayerFactory.getModelLayerFactory() .getTaxonomiesManager().getTaxonomyFor(collectionCode, importedTaxonomy.getCode()); } private void importCollectionsValueLists(final ImportedCollectionSettings collectionSettings, final String collectionCode, final MetadataSchemaTypes collectionSchemaTypes) { schemasManager.modify(collectionCode, new MetadataSchemaTypesAlteration() { @Override public void alter(MetadataSchemaTypesBuilder schemaTypesBuilder) { for (final ImportedValueList importedValueList : collectionSettings.getValueLists()) { final String code = importedValueList.getCode(); String codeModeText = importedValueList.getCodeMode(); ValueListItemSchemaTypeBuilder.ValueListItemSchemaTypeCodeMode schemaTypeCodeMode = ValueListItemSchemaTypeBuilder.ValueListItemSchemaTypeCodeMode.REQUIRED_AND_UNIQUE; if (StringUtils.isNotBlank(codeModeText)) { schemaTypeCodeMode = EnumUtils .getEnum(ValueListItemSchemaTypeBuilder.ValueListItemSchemaTypeCodeMode.class, codeModeText); } if (!collectionSchemaTypes.hasType(code)) { ValueListItemSchemaTypeBuilder builder = new ValueListItemSchemaTypeBuilder(schemaTypesBuilder); ; if (importedValueList.getHierarchical() == null || !importedValueList.getHierarchical()) { builder.createValueListItemSchema(code, importedValueList.getTitle(), ValueListItemSchemaTypeBuilderOptions.codeMode(schemaTypeCodeMode)); } else { builder.createHierarchicalValueListItemSchema(code, importedValueList.getTitle(), ValueListItemSchemaTypeBuilderOptions.codeMode(schemaTypeCodeMode)); } } else { MetadataSchemaTypeBuilder builder = schemaTypesBuilder.getSchemaType(importedValueList.getCode()); if (StringUtils.isNotBlank(importedValueList.getTitle())) { Map<Language, String> labels = new HashMap<>(); labels.put(Language.French, importedValueList.getTitle()); builder.setLabels(labels); } if (StringUtils.isNotBlank(codeModeText)) { MetadataBuilder metadataBuilder = builder.getDefaultSchema().getMetadata("code"); if (ValueListItemSchemaTypeBuilder .ValueListItemSchemaTypeCodeMode.DISABLED == schemaTypeCodeMode) { metadataBuilder.setDefaultRequirement(false); metadataBuilder.setUniqueValue(false); metadataBuilder.setEnabled(false); } else if (ValueListItemSchemaTypeBuilder .ValueListItemSchemaTypeCodeMode.FACULTATIVE == schemaTypeCodeMode) { metadataBuilder.setDefaultRequirement(false); metadataBuilder.setUniqueValue(false); metadataBuilder.setEnabled(true); } else if (ValueListItemSchemaTypeBuilder .ValueListItemSchemaTypeCodeMode.REQUIRED_AND_UNIQUE == schemaTypeCodeMode) { metadataBuilder.setEnabled(true); metadataBuilder.setDefaultRequirement(true); metadataBuilder.setUniqueValue(true); } } } } } }); } private void importSequences(ImportedSettings settings) { SequencesManager sequenceManager = appLayerFactory.getModelLayerFactory() .getDataLayerFactory().getSequencesManager(); for (ImportedSequence sequence : settings.getSequences()) { sequenceManager.set(sequence.getKey(), Integer.parseInt(sequence.getValue())); } } private void importGlobalConfigurations(ImportedSettings settings) { for (ImportedConfig importedConfig : settings.getConfigs()) { SystemConfiguration config = systemConfigurationsManager.getConfigurationWithCode(importedConfig.getKey()); if (config != null) { Object convertedValue; if (config.getType() == SystemConfigurationType.BOOLEAN) { convertedValue = Boolean.valueOf(importedConfig.getValue()); } else if (config.getType() == SystemConfigurationType.INTEGER) { int value = Integer.parseInt(importedConfig.getValue()); convertedValue = value; } else if (config.getType() == SystemConfigurationType.STRING) { convertedValue = importedConfig.getValue().trim(); } else if (config.getType() == SystemConfigurationType.ENUM) { convertedValue = Enum.valueOf((Class<? extends Enum>) config.getEnumClass(), importedConfig.getValue()); } else { throw new ImpossibleRuntimeException("Unsupported config import : " + config.getType().name()); } if (config.getDefaultValue() != null && config.getDefaultValue().equals(convertedValue)) { systemConfigurationsManager.reset(config); } else { systemConfigurationsManager.setValue(config, convertedValue); } } } } private void validate(ImportedSettings settings, ValidationErrors validationErrors) throws ValidationException { validateGlobalConfigs(settings, validationErrors); validateSequences(settings, validationErrors); validateCollectionConfigs(settings, validationErrors); if (!validationErrors.isEmpty()) { throw new ValidationException(validationErrors); } } private void validateCollectionConfigs(ImportedSettings settings, ValidationErrors validationErrors) { for (ImportedCollectionSettings collectionSettings : settings.getCollectionsSettings()) { validateCollectionCode(validationErrors, collectionSettings); validateCollectionValueLists(validationErrors, collectionSettings); validateCollectionTaxonomies(validationErrors, collectionSettings); validateCollectionTypes(validationErrors, collectionSettings); } } private void validateCollectionTypes(ValidationErrors errors, ImportedCollectionSettings settings) { for (ImportedType importedType : settings.getTypes()) { validateTypeCode(errors, importedType.getCode()); validateHasDefaultSchema(errors, importedType.getDefaultSchema()); validateTabs(errors, importedType.getTabs()); validateCustomSchemas(errors, importedType.getCustomSchemata()); } } private void validateCustomSchemas(ValidationErrors errors, List<ImportedMetadataSchema> customSchema) { for (ImportedMetadataSchema schema : customSchema) { if (StringUtils.isBlank(schema.getCode())) { Map<String, Object> parameters = new HashMap(); parameters.put(CONFIG, CODE); errors.add(SettingsImportServices.class, INVALID_SCHEMA_CODE, parameters); } } Set<String> codes = new HashSet<>(); for (ImportedMetadataSchema schema : customSchema) { if (schema.getCode() != null) { if (codes.contains(schema.getCode())) { Map<String, Object> parameters = new HashMap(); parameters.put(CONFIG, CODE); parameters.put(VALUE, schema.getCode()); errors.add(SettingsImportServices.class, DUPLICATE_SCHEMA_CODE, parameters); } codes.add(schema.getCode()); } } } private void validateTabs(ValidationErrors errors, List<ImportedTab> importedTabs) { for (ImportedTab tab : importedTabs) { if (StringUtils.isBlank(tab.getCode())) { Map<String, Object> parameters = new HashMap(); parameters.put(CONFIG, CODE); parameters.put(VALUE, tab.getCode()); errors.add(SettingsImportServices.class, EMPTY_TAB_CODE, parameters); } } } private void validateHasDefaultSchema(ValidationErrors errors, ImportedMetadataSchema defaultSchema) { if (defaultSchema == null) { Map<String, Object> parameters = new HashMap(); parameters.put(CONFIG, "default-schema"); parameters.put(VALUE, null); errors.add(SettingsImportServices.class, NULL_DEFAULT_SCHEMA, parameters); } } private void validateTypeCode(ValidationErrors errors, String typeCode) { if (StringUtils.isBlank(typeCode)) { Map<String, Object> parameters = new HashMap(); parameters.put(CONFIG, CODE); parameters.put(VALUE, typeCode); errors.add(SettingsImportServices.class, EMPTY_TYPE_CODE, parameters); } } private void validateCollectionTaxonomies(ValidationErrors validationErrors, ImportedCollectionSettings collectionSettings) { for (ImportedTaxonomy importedTaxonomy : collectionSettings.getTaxonomies()) { validateTaxonomyCode(validationErrors, importedTaxonomy); } } private void validateTaxonomyCode(ValidationErrors validationErrors, ImportedTaxonomy importedTaxonomy) { String code = importedTaxonomy.getCode(); if (StringUtils.isBlank(code)) { Map<String, Object> parameters = new HashMap<>(); parameters.put(CONFIG, CODE); parameters.put(VALUE, importedTaxonomy.getCode()); validationErrors.add(SettingsImportServices.class, EMPTY_TAXONOMY_CODE, parameters); } else if (!code.startsWith(TAXO_PREFIX)) { Map<String, Object> parameters = new HashMap<>(); parameters.put(CONFIG, CODE); parameters.put(VALUE, importedTaxonomy.getCode()); validationErrors.add(SettingsImportServices.class, INVALID_TAXONOMY_CODE_PREFIX, parameters); } else if (!code.endsWith(TAXO_SUFFIX)) { Map<String, Object> parameters = new HashMap<>(); parameters.put(CONFIG, CODE); parameters.put(VALUE, importedTaxonomy.getCode()); validationErrors.add(SettingsImportServices.class, INVALID_TAXONOMY_CODE_SUFFIX, parameters); } } private void validateCollectionValueLists(ValidationErrors validationErrors, ImportedCollectionSettings collectionSettings) { for (ImportedValueList importedValueList : collectionSettings.getValueLists()) { validateValueListCode(validationErrors, importedValueList); } } private void validateCollectionCode(ValidationErrors validationErrors, ImportedCollectionSettings collectionSettings) { String collectionCode = collectionSettings.getCode(); if (StringUtils.isBlank(collectionCode)) { Map<String, Object> parameters = new HashMap<>(); parameters.put(CONFIG, CODE); parameters.put(VALUE, collectionCode); validationErrors.add(SettingsImportServices.class, INVALID_COLLECTION_CODE, parameters); } else { try { schemasManager.getSchemaTypes(collectionCode); } catch (Exception e) { Map<String, Object> parameters = new HashMap<>(); parameters.put(CONFIG, CODE); parameters.put(VALUE, collectionCode); validationErrors.add(SettingsImportServices.class, COLLECTION_CODE_NOT_FOUND, parameters); } } } private void validateValueListCode(ValidationErrors validationErrors, ImportedValueList importedValueList) { if (StringUtils.isBlank(importedValueList.getCode()) || !importedValueList.getCode().startsWith(DDV_PREFIX)) { Map<String, Object> parameters = new HashMap<>(); parameters.put(CONFIG, importedValueList.getCode()); parameters.put(VALUE, importedValueList.getTitle()); validationErrors .add(SettingsImportServices.class, INVALID_VALUE_LIST_CODE, parameters); } } private void validateSequences(ImportedSettings settings, ValidationErrors validationErrors) { for (ImportedSequence importedSequence : settings.getSequences()) { if (StringUtils.isBlank(importedSequence.getKey())) { Map<String, Object> parameters = toParametersMap(importedSequence.getKey(), importedSequence.getValue()); validationErrors.add(SettingsImportServices.class, SEQUENCE_ID_NULL_OR_EMPTY, parameters); } if (isNotNumerical(importedSequence.getKey())) { Map<String, Object> parameters = toParametersMap(importedSequence.getKey(), importedSequence.getValue()); validationErrors.add(SettingsImportServices.class, SEQUENCE_ID_NOT_NUMERICAL, parameters); } if (isNotNumerical(importedSequence.getValue())) { Map<String, Object> parameters = toParametersMap(importedSequence.getKey(), importedSequence.getValue()); validationErrors.add(SettingsImportServices.class, SEQUENCE_VALUE_NOT_NUMERICAL, parameters); } } } private boolean isNotNumerical(String value) { try { Integer.parseInt(value); return false; } catch (NumberFormatException e) { return true; } } private void validateGlobalConfigs(ImportedSettings settings, ValidationErrors validationErrors) { for (ImportedConfig importedConfig : settings.getConfigs()) { SystemConfiguration config = systemConfigurationsManager.getConfigurationWithCode(importedConfig.getKey()); if (config == null) { Map<String, Object> parameters = toParametersMap(importedConfig.getKey(), importedConfig.getValue()); validationErrors.add(SettingsImportServices.class, CONFIGURATION_NOT_FOUND, parameters); } else if (importedConfig.getValue() == null) { Map<String, Object> parameters = toParametersMap(importedConfig.getKey(), importedConfig.getValue()); validationErrors .add(SettingsImportServices.class, INVALID_CONFIGURATION_VALUE, parameters); } else { if (config.getType() == SystemConfigurationType.BOOLEAN) { validateBooleanValueConfig(validationErrors, importedConfig); } else if (config.getType() == SystemConfigurationType.INTEGER) { validateIntegerValueConfig(validationErrors, importedConfig); } else if (config.getType() == SystemConfigurationType.STRING) { validateStringValueConfig(validationErrors, importedConfig); } } } } private void validateBooleanValueConfig(ValidationErrors validationErrors, ImportedConfig importedConfig) { if (!asList("true", "false").contains(String.valueOf(importedConfig.getValue()))) { Map<String, Object> parameters = toParametersMap(importedConfig.getKey(), importedConfig.getValue()); validationErrors.add(SettingsImportServices.class, INVALID_CONFIGURATION_VALUE, parameters); } } private void validateIntegerValueConfig(ValidationErrors validationErrors, ImportedConfig importedConfig) { try { Integer.parseInt(importedConfig.getValue()); } catch (NumberFormatException e) { Map<String, Object> parameters = toParametersMap(importedConfig.getKey(), importedConfig.getValue()); validationErrors.add(SettingsImportServices.class, INVALID_CONFIGURATION_VALUE, parameters); } } private void validateStringValueConfig(ValidationErrors validationErrors, ImportedConfig importedConfig) { if (importedConfig.getValue() == null) { Map<String, Object> parameters = toParametersMap(importedConfig.getKey(), importedConfig.getValue()); validationErrors.add(SettingsImportServices.class, INVALID_CONFIGURATION_VALUE, parameters); } } private Map<String, Object> toParametersMap(String key, Object value) { Map<String, Object> parameters = new HashMap(); parameters.put(CONFIG, key); parameters.put(VALUE, value == null ? "null" : value); return parameters; } }