package com.constellio.model.entities.schemas; import static com.constellio.model.entities.schemas.MetadataValueType.REFERENCE; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; 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.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import com.constellio.model.entities.Language; import com.constellio.model.entities.schemas.MetadataSchemasRuntimeException.InvalidCodeFormat; import com.constellio.model.services.schemas.MetadataList; import com.constellio.model.services.schemas.SchemaUtils; public class MetadataSchemaTypes { private static final String DEFAULT = "default"; private static final String UNDERSCORE = "_"; private final int version; private final String collection; private final List<MetadataSchemaType> schemaTypes; private final Map<String, MetadataSchemaType> schemaTypesMap; private final List<String> schemaTypesSortedByDependency; private List<String> referenceDefaultValues; private MetadataList searchableMetadatas; private final Set<String> typeParentOfOtherTypes; private final List<Language> languages; private final MetadataNetwork metadataNetwork; public MetadataSchemaTypes(String collection, int version, List<MetadataSchemaType> schemaTypes, List<String> schemaTypesSortedByDependency, List<String> referenceDefaultValues, List<Language> languages, MetadataNetwork metadataNetwork) { super(); this.version = version; this.collection = collection; this.schemaTypes = Collections.unmodifiableList(schemaTypes); this.schemaTypesSortedByDependency = schemaTypesSortedByDependency; this.referenceDefaultValues = referenceDefaultValues; this.searchableMetadatas = getSearchableMetadatas(schemaTypes); this.schemaTypesMap = toUnmodifiableMap(schemaTypes); this.languages = Collections.unmodifiableList(languages); this.typeParentOfOtherTypes = buildTypeParentOfOtherTypes(schemaTypes); this.metadataNetwork = metadataNetwork; } private MetadataList getSearchableMetadatas(List<MetadataSchemaType> schemaTypes) { MetadataList searchableMetadatas = new MetadataList(); Set<String> searchableMetadatasDataStoreCodes = new HashSet<>(); for (MetadataSchemaType schemaType : schemaTypes) { for (MetadataSchema schema : schemaType.getAllSchemas()) { for (Metadata metadata : schema.getMetadatas()) { if (metadata.getInheritance() == null && metadata.isSearchable() && !searchableMetadatasDataStoreCodes.contains(metadata.getDataStoreCode())) { searchableMetadatasDataStoreCodes.add(metadata.getDataStoreCode()); searchableMetadatas.add(metadata); } } } } return searchableMetadatas.unModifiable(); } private Set<String> buildTypeParentOfOtherTypes(List<MetadataSchemaType> schemaTypes) { Set<String> typeParentOfOtherTypes = new HashSet<>(); for (MetadataSchemaType type : schemaTypes) { secondFor: for (MetadataSchemaType anotherType : schemaTypes) { for (Metadata metadata : anotherType.getAllMetadatas()) { if (metadata.getType() == REFERENCE && metadata.isChildOfRelationship() && metadata.getAllowedReferences().isAllowed(type)) { typeParentOfOtherTypes.add(type.getCode()); break secondFor; } } } } return Collections.unmodifiableSet(typeParentOfOtherTypes); } private Map<String, MetadataSchemaType> toUnmodifiableMap(List<MetadataSchemaType> schemaTypes) { Map<String, MetadataSchemaType> types = new HashMap<>(); for (MetadataSchemaType type : schemaTypes) { types.put(type.getCode(), type); } return Collections.unmodifiableMap(types); } public MetadataNetwork getMetadataNetwork() { return metadataNetwork; } public String getCollection() { return collection; } public int getVersion() { return version; } public List<Language> getLanguages() { return languages; } public List<MetadataSchemaType> getSchemaTypesWithCode(List<String> codes) { List<MetadataSchemaType> types = new ArrayList<>(); for (String code : codes) { types.add(getSchemaType(code)); } return types; } public List<Metadata> getHighlightedMetadatas() { return searchableMetadatas; } public List<MetadataSchemaType> getSchemaTypes() { return schemaTypes; } public MetadataSchemaType getSchemaType(String schemaTypeCode) { MetadataSchemaType schemaType = schemaTypesMap.get(schemaTypeCode); if (schemaType == null) { throw new MetadataSchemasRuntimeException.NoSuchSchemaType(schemaTypeCode); } return schemaType; } public MetadataSchema getDefaultSchema(String schemaTypeCode) { MetadataSchemaType schemaType = getSchemaType(schemaTypeCode); return schemaType.getDefaultSchema(); } public MetadataSchema getSchema(String code) { String[] parsedCode = SchemaUtils.underscoreSplitWithCache(code); String typeCode; String schemaCode; if (parsedCode.length == 2) { typeCode = parsedCode[0]; schemaCode = parsedCode[1]; } else { throw new InvalidCodeFormat(code); } MetadataSchemaType schemaType = getSchemaType(typeCode); MetadataSchema schema = null; if (schemaCode.equals(DEFAULT)) { schema = schemaType.getDefaultSchema(); } else { schema = schemaType.getCustomSchema(schemaCode); } return schema; } public Metadata getMetadata(String code) { String[] parsedCode = SchemaUtils.underscoreSplitWithCache(code); String typeCode; if (parsedCode.length == 3) { typeCode = parsedCode[0]; } else { throw new InvalidCodeFormat(code); } MetadataSchemaType schemaType = getSchemaType(typeCode); return schemaType.getMetadata(code); } @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this, "metadataNetwork"); } @Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj, "metadataNetwork"); } @Override public String toString() { return "MetadataSchemaTypes [version=" + version + ", schemaTypes=" + schemaTypes + "]"; } public MetadataList getMetadatas(List<String> metadataCompleteCodes) { List<Metadata> metadatas = new ArrayList<>(); for (String metadataCompleteCode : metadataCompleteCodes) { metadatas.add(getMetadata(metadataCompleteCode)); } return new MetadataList(metadatas).unModifiable(); } public List<String> getSchemaTypesSortedByDependency() { return schemaTypesSortedByDependency; } public MetadataList getAllMetadatas() { MetadataList metadatas = new MetadataList(); for (MetadataSchemaType schemaType : schemaTypes) { metadatas.addAll(schemaType.getAllMetadatas()); } return metadatas.unModifiable(); } public MetadataList getAllMetadatasIncludingThoseWithInheritance() { MetadataList metadatas = new MetadataList(); for (MetadataSchemaType schemaType : schemaTypes) { metadatas.addAll(schemaType.getAllMetadatasIncludingThoseWithInheritance()); } return metadatas.unModifiable(); } public MetadataList getAllContentMetadatas() { return getAllMetadatas().onlyWithType(MetadataValueType.CONTENT); } public boolean hasMetadata(String metadataCode) { String schemaCode = new SchemaUtils().getSchemaCode(metadataCode); if (!hasSchema(schemaCode)) { return false; } try { getMetadata(metadataCode); return true; } catch (MetadataSchemasRuntimeException.NoSuchMetadata e) { return false; } } public List<String> getReferenceDefaultValues() { return referenceDefaultValues; } public List<MetadataSchemaType> getSchemaTypesWithCodesSortedByDependency(Set<String> returnedTypeCodes) { List<MetadataSchemaType> returnedMetadataSchemaTypes = new ArrayList<>(); for (String typeCode : getSchemaTypesSortedByDependency()) { if (returnedTypeCodes.contains(typeCode)) { MetadataSchemaType type = getSchemaType(typeCode); returnedMetadataSchemaTypes.add(type); } } return returnedMetadataSchemaTypes; } public List<MetadataSchemaType> getSchemaTypesSortedByLabelsOfLanguage(final Language language) { List<MetadataSchemaType> types = new ArrayList<>(schemaTypes); Collections.sort(types, new Comparator<MetadataSchemaType>() { @Override public int compare(MetadataSchemaType o1, MetadataSchemaType o2) { return o1.getLabel(language).compareTo(o2.getLabel(language)); } }); return Collections.unmodifiableList(types); } public boolean hasType(String schemaType) { return schemaTypesMap.containsKey(schemaType); } public boolean hasSchema(String schemaCode) { try { getSchema(schemaCode); return true; } catch (MetadataSchemasRuntimeException.NoSuchSchema e) { return false; } catch (MetadataSchemasRuntimeException.NoSuchSchemaType e) { return false; } } public List<Metadata> getAllMetadataIncludingInheritedOnes() { List<Metadata> metadatas = new ArrayList<>(); for (MetadataSchemaType schemaType : schemaTypes) { metadatas.addAll(schemaType.getAllMetadataIncludingInheritedOnes()); } return metadatas; } public boolean isRecordTypeMetadata(Metadata metadata) { if ("type".equals(metadata.getCode()) || metadata.getType() == REFERENCE) { MetadataSchema referencedSchema = getDefaultSchema(metadata.getReferencedSchemaType()); return referencedSchema.hasMetadataWithCode("linkedSchema"); } return false; } public Set<String> getTypeParentOfOtherTypes() { return typeParentOfOtherTypes; } }