package com.constellio.model.entities.schemas; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import com.constellio.model.entities.Language; import com.constellio.model.entities.Taxonomy; import com.constellio.model.entities.schemas.MetadataSchemasRuntimeException.CannotGetMetadatasOfAnotherSchemaType; import com.constellio.model.entities.schemas.MetadataSchemasRuntimeException.NoSuchSchema; import com.constellio.model.entities.schemas.entries.DataEntryType; import com.constellio.model.services.schemas.MetadataList; import com.constellio.model.services.schemas.SchemaUtils; import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilderRuntimeException; public class MetadataSchemaType { public static final String DEFAULT = "default"; private final String code; private final String collection; private final Map<Language, String> labels; private final MetadataSchema defaultSchema; private final Map<String, MetadataSchema> customSchemasByCode; private final Map<String, MetadataSchema> customSchemasByLocalCode; private final List<MetadataSchema> customSchemas; private final Map<String, Metadata> metadatasByAtomicCode; private final boolean security; private final boolean inTransactionLog; private boolean readOnlyLocked; private final Boolean undeletable; public MetadataSchemaType(String code, String collection, Map<Language, String> labels, List<MetadataSchema> customSchemas, MetadataSchema defaultSchema, Boolean undeletable, boolean security, boolean inTransactionLog, boolean readOnlyLocked) { super(); this.code = code; this.collection = collection; this.labels = Collections.unmodifiableMap(labels); this.customSchemas = Collections.unmodifiableList(customSchemas); this.defaultSchema = defaultSchema; this.undeletable = undeletable; this.security = security; this.inTransactionLog = inTransactionLog; this.readOnlyLocked = readOnlyLocked; this.metadatasByAtomicCode = Collections.unmodifiableMap(new SchemaUtils().buildMetadataByLocalCodeIndex( customSchemas, defaultSchema)); this.customSchemasByCode = buildCustomSchemasByCodeMap(customSchemas); this.customSchemasByLocalCode = buildCustomSchemasByLocalCodeMap(customSchemas); } private Map<String, MetadataSchema> buildCustomSchemasByCodeMap(List<MetadataSchema> customSchemas) { Map<String, MetadataSchema> schemaMap = new HashMap<>(); for (MetadataSchema schema : customSchemas) { schemaMap.put(schema.getCode(), schema); } return Collections.unmodifiableMap(schemaMap); } private Map<String, MetadataSchema> buildCustomSchemasByLocalCodeMap(List<MetadataSchema> customSchemas) { Map<String, MetadataSchema> schemaMap = new HashMap<>(); for (MetadataSchema schema : customSchemas) { schemaMap.put(schema.getLocalCode(), schema); } return Collections.unmodifiableMap(schemaMap); } public boolean isReadOnlyLocked() { return readOnlyLocked; } public String getCollection() { return collection; } public String getCode() { return code; } public Map<Language, String> getLabels() { return labels; } public String getLabel(Language language) { return labels.get(language); } public boolean isInTransactionLog() { return inTransactionLog; } public List<MetadataSchema> getSchemas() { return customSchemas; } public MetadataSchema getDefaultSchema() { return defaultSchema; } public List<MetadataSchema> getAllSchemas() { List<MetadataSchema> allSchemas = new ArrayList<>(); allSchemas.addAll(customSchemas); allSchemas.add(defaultSchema); return allSchemas; } public MetadataSchema getCustomSchema(String code) { MetadataSchema schema = customSchemasByCode.get(code); if (schema == null) { schema = customSchemasByLocalCode.get(code); } if (schema == null) { throw new MetadataSchemasRuntimeException.NoSuchSchema(code); } else { return schema; } } public Metadata getMetadata(String metadataCode) { String[] parsedCode = SchemaUtils.underscoreSplitWithCache(metadataCode); String typeCode = parsedCode[0]; String schemaCode = parsedCode[1]; String localMetadataCode = parsedCode[2]; if (typeCode.equals("global")) { typeCode = code; } if (!code.contains(typeCode)) { throw new CannotGetMetadatasOfAnotherSchemaType(typeCode, code); } Metadata metadata; if (schemaCode.contains("_" + DEFAULT) || schemaCode.equals(DEFAULT)) { metadata = getDefaultSchema().getMetadata(localMetadataCode); } else { metadata = getCustomSchema(schemaCode).getMetadata(localMetadataCode); } if (metadata == null) { throw new MetadataSchemaTypesBuilderRuntimeException.NoSuchMetadata(localMetadataCode); } else { return metadata; } } public List<Metadata> getAutomaticMetadatas() { List<Metadata> automaticMetadatas = new ArrayList<>(); automaticMetadatas.addAll(defaultSchema.getAutomaticMetadatas()); for (MetadataSchema customSchema : customSchemas) { for (Metadata customAutomaticMetadata : customSchema.getAutomaticMetadatas()) { if (customAutomaticMetadata.getInheritance() == null) { automaticMetadatas.add(customAutomaticMetadata); } } } return Collections.unmodifiableList(automaticMetadatas); } public List<Metadata> getCalculatedMetadatas() { List<Metadata> metadatas = new ArrayList<>(); for (Metadata metadata : getAutomaticMetadatas()) { if (metadata.getDataEntry().getType() == DataEntryType.CALCULATED) { metadatas.add(metadata); } } return metadatas; } public List<Metadata> getAllNonParentReferences() { List<Metadata> referenceMetadatas = new ArrayList<>(); referenceMetadatas.addAll(defaultSchema.getNonParentReferences()); for (MetadataSchema customSchema : customSchemas) { for (Metadata customReferenceMetadata : customSchema.getNonParentReferences()) { if (customReferenceMetadata.getInheritance() == null) { referenceMetadatas.add(customReferenceMetadata); } } } return Collections.unmodifiableList(referenceMetadatas); } public List<Metadata> getAllParentReferences() { List<Metadata> parentReferenceMetadatas = new ArrayList<>(); parentReferenceMetadatas.addAll(defaultSchema.getParentReferences()); for (MetadataSchema customSchema : customSchemas) { for (Metadata customParentReferenceMetadata : customSchema.getParentReferences()) { if (customParentReferenceMetadata.getInheritance() == null) { parentReferenceMetadatas.add(customParentReferenceMetadata); } } } return Collections.unmodifiableList(parentReferenceMetadatas); } public List<Metadata> getAllReferencesToTaxonomySchemas(List<Taxonomy> taxonomies) { List<Metadata> taxonomyReferencesMetadatas = new ArrayList<>(); taxonomyReferencesMetadatas.addAll(defaultSchema.getTaxonomyRelationshipReferences(taxonomies)); for (MetadataSchema customSchema : customSchemas) { for (Metadata customParentReferenceMetadata : customSchema.getTaxonomyRelationshipReferences(taxonomies)) { if (customParentReferenceMetadata.getInheritance() == null) { taxonomyReferencesMetadatas.add(customParentReferenceMetadata); } } } return Collections.unmodifiableList(taxonomyReferencesMetadatas); } public List<Metadata> getTaxonomySchemasMetadataWithChildOfRelationship(List<Taxonomy> taxonomies) { List<Metadata> returnedMetadatas = new ArrayList<>(); for (Taxonomy taxonomy : taxonomies) { if (taxonomy.getSchemaTypes().contains(code)) { for (Metadata metadata : getAllParentReferences()) { if (metadata.isChildOfRelationship()) { String typeCode = metadata.getAllowedReferences().getTypeWithAllowedSchemas(); if (taxonomy.getSchemaTypes().contains(typeCode)) { returnedMetadatas.add(metadata); } } } } } return Collections.unmodifiableList(returnedMetadatas); } private MetadataSchema getNullableSchema(String codeOrCode) { MetadataSchema schema = null; try { if (codeOrCode.contains("_")) { schema = getSchemaWithCompleteCode(codeOrCode); } else { schema = getSchemaWithLocalCode(codeOrCode); } } catch (NoSuchSchema e) { return null; } return schema; } public MetadataSchema getSchema(String codeOrCode) { MetadataSchema schema = getNullableSchema(codeOrCode); if (schema == null) { throw new MetadataSchemasRuntimeException.NoSuchSchema(codeOrCode); } else { return schema; } } public boolean hasSchema(String codeOrCode) { MetadataSchema schema = getNullableSchema(codeOrCode); return schema != null; } private MetadataSchema getSchemaWithLocalCode(String code) { return "default".equals(code) ? getDefaultSchema() : getCustomSchema(code); } private MetadataSchema getSchemaWithCompleteCode(String schemaCode) { String[] parsedCode = SchemaUtils.underscoreSplitWithCache(schemaCode); String type = parsedCode[0]; if (!type.equals(code)) { throw new CannotGetMetadatasOfAnotherSchemaType(type, code); } String schemaLocalCode = parsedCode[1]; return getSchemaWithLocalCode(schemaLocalCode); } public Boolean isUndeletable() { return undeletable; } @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } @Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); } @Override public String toString() { return "MetadataSchemaType [code=" + code + ", label=" + labels + ", defaultSchema=" + defaultSchema + ", customSchemas=" + customSchemas + ", undeletable=" + undeletable + "]"; } public List<MetadataSchema> getCustomSchemas() { return Collections.unmodifiableList(customSchemas); } public Metadata getMetadataWithAtomicCode(String localCode) { try { return metadatasByAtomicCode.get(localCode); } catch (RuntimeException e) { throw new MetadataSchemasRuntimeException.NoSuchMetadataWithAtomicCode(localCode, e); } } public Metadata getMetadataWithDataStoreCode(String dataStoreCode) { String localCode = new SchemaUtils().getLocalCodeFromDataStoreCode(dataStoreCode); Metadata metadata = metadatasByAtomicCode.get(localCode); if (metadata == null) { throw new MetadataSchemasRuntimeException.NoSuchMetadataWithDatastoreCodeInSchemaType(dataStoreCode, code); } return metadata; } public MetadataList getAllMetadatas() { MetadataList metadatas = new MetadataList(); metadatas.addAll(defaultSchema.getMetadatas()); for (MetadataSchema customSchema : customSchemas) { for (Metadata customParentReferenceMetadata : customSchema.getMetadatas()) { if (customParentReferenceMetadata.getInheritance() == null) { metadatas.add(customParentReferenceMetadata); } } } return metadatas.unModifiable(); } public MetadataList getAllMetadatasIncludingThoseWithInheritance() { MetadataList metadatas = new MetadataList(); metadatas.addAll(defaultSchema.getMetadatas()); for (MetadataSchema customSchema : customSchemas) { for (Metadata customParentReferenceMetadata : customSchema.getMetadatas()) { metadatas.add(customParentReferenceMetadata); } } return metadatas.unModifiable(); } public boolean hasSecurity() { return security; } public List<Metadata> getAllMetadataIncludingInheritedOnes() { List<Metadata> metadatas = new ArrayList<>(); metadatas.addAll(defaultSchema.getMetadatas()); for (MetadataSchema customSchema : customSchemas) { for (Metadata customParentReferenceMetadata : customSchema.getMetadatas()) { metadatas.add(customParentReferenceMetadata); } } return metadatas; } public List<MetadataSchema> getAllSchemasSortedByCode() { List<MetadataSchema> schemas = new ArrayList<>(getAllSchemas()); Collections.sort(schemas, new Comparator<MetadataSchema>() { @Override public int compare(MetadataSchema o1, MetadataSchema o2) { return o1.getCode().compareTo(o2.getCode()); } }); return schemas; } public boolean isParentOfOtherRecords(String typeCode) { return false; } }