/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.common.refinery;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.common.ResourceObjectPattern;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.ResourceShadowDiscriminator;
import com.evolveum.midpoint.schema.processor.*;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.PagedSearchCapabilityType;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import org.jetbrains.annotations.NotNull;
/**
* @author semancik
* @author mederly
*
* Work in-progress.
*
*/
public class LayerRefinedObjectClassDefinitionImpl implements LayerRefinedObjectClassDefinition {
private RefinedObjectClassDefinition refinedObjectClassDefinition;
private LayerType layer;
/**
* Keeps layer-specific information on resource object attributes.
* This list is lazily evaluated.
*/
private List<LayerRefinedAttributeDefinition<?>> layerRefinedAttributeDefinitions;
private LayerRefinedObjectClassDefinitionImpl(RefinedObjectClassDefinition refinedAccountDefinition, LayerType layer) {
this.refinedObjectClassDefinition = refinedAccountDefinition;
this.layer = layer;
}
static LayerRefinedObjectClassDefinition wrap(RefinedObjectClassDefinition rOCD, LayerType layer) {
if (rOCD == null) {
return null;
}
return new LayerRefinedObjectClassDefinitionImpl(rOCD, layer);
}
static List<? extends LayerRefinedObjectClassDefinition> wrapCollection(Collection<? extends RefinedObjectClassDefinition> rOCDs, LayerType layer) {
return(rOCDs.stream()
.map(rAccountDef -> wrap(rAccountDef, layer))
.collect(Collectors.toCollection(() -> new ArrayList<>(rOCDs.size()))));
}
@Override
public LayerType getLayer() {
return layer;
}
@NotNull
@Override
public QName getTypeName() {
return refinedObjectClassDefinition.getTypeName();
}
@Override
public boolean isIgnored() {
return refinedObjectClassDefinition.isIgnored();
}
public boolean isEmphasized() {
return refinedObjectClassDefinition.isEmphasized();
}
@Override
public <X> LayerRefinedAttributeDefinition<X> getDescriptionAttribute() {
// TODO optimize
return substituteLayerRefinedAttributeDefinition(refinedObjectClassDefinition.getDescriptionAttribute());
}
@Override
@NotNull
public List<String> getIgnoredNamespaces() {
return refinedObjectClassDefinition.getIgnoredNamespaces();
}
private <X> LayerRefinedAttributeDefinition<X> substituteLayerRefinedAttributeDefinition(ResourceAttributeDefinition<?> attributeDef) {
return findAttributeDefinition(attributeDef.getName());
}
private Collection<LayerRefinedAttributeDefinition<?>> substituteLayerRefinedAttributeDefinitionCollection(Collection<? extends RefinedAttributeDefinition<?>> attributes) {
return attributes.stream()
.map(this::substituteLayerRefinedAttributeDefinition)
.collect(Collectors.toList());
}
@Override
public <X> LayerRefinedAttributeDefinition<X> getNamingAttribute() {
return substituteLayerRefinedAttributeDefinition(refinedObjectClassDefinition.getNamingAttribute());
}
@Override
public String getNativeObjectClass() {
return refinedObjectClassDefinition.getNativeObjectClass();
}
@Override
public boolean isAuxiliary() {
return refinedObjectClassDefinition.isAuxiliary();
}
@Override
public Integer getDisplayOrder() {
return refinedObjectClassDefinition.getDisplayOrder();
}
// TODO - doesn't return layered definition (should it?)
@Override
public <ID extends ItemDefinition> ID findItemDefinition(@NotNull ItemPath path,
@NotNull Class<ID> clazz) {
return refinedObjectClassDefinition.findItemDefinition(path, clazz);
}
// TODO - doesn't return layered definition (should it?)
@Override
public <ID extends ItemDefinition> ID findNamedItemDefinition(@NotNull QName firstName, @NotNull ItemPath rest,
@NotNull Class<ID> clazz) {
return refinedObjectClassDefinition.findNamedItemDefinition(firstName, rest, clazz);
}
@Override
public boolean isDefaultInAKind() {
return refinedObjectClassDefinition.isDefaultInAKind();
}
@Override
public ShadowKindType getKind() {
return refinedObjectClassDefinition.getKind();
}
@Override
public AttributeFetchStrategyType getPasswordFetchStrategy() {
return refinedObjectClassDefinition.getPasswordFetchStrategy();
}
@Override
public String getIntent() {
return refinedObjectClassDefinition.getIntent();
}
@Override
public LayerRefinedObjectClassDefinition forLayer(@NotNull LayerType layerType) {
return refinedObjectClassDefinition.forLayer(layerType);
}
@Override
public <X> LayerRefinedAttributeDefinition<X> getDisplayNameAttribute() {
return substituteLayerRefinedAttributeDefinition(refinedObjectClassDefinition.getDisplayNameAttribute());
}
@Override
public String getHelp() {
return refinedObjectClassDefinition.getHelp();
}
@NotNull
@Override
public Collection<? extends LayerRefinedAttributeDefinition<?>> getPrimaryIdentifiers() {
return substituteLayerRefinedAttributeDefinitionCollection(refinedObjectClassDefinition.getPrimaryIdentifiers());
}
@Override
public Collection<? extends LayerRefinedAttributeDefinition<?>> getAllIdentifiers() {
return substituteLayerRefinedAttributeDefinitionCollection(refinedObjectClassDefinition.getAllIdentifiers());
}
@NotNull
@Override
public Collection<? extends LayerRefinedAttributeDefinition<?>> getSecondaryIdentifiers() {
return LayerRefinedAttributeDefinitionImpl.wrapCollection(refinedObjectClassDefinition.getSecondaryIdentifiers(), layer);
}
@Override
public Class getTypeClass() {
return refinedObjectClassDefinition.getTypeClass();
}
@Override
public Collection<ResourceObjectPattern> getProtectedObjectPatterns() {
return refinedObjectClassDefinition.getProtectedObjectPatterns();
}
@Override
public void merge(ComplexTypeDefinition otherComplexTypeDef) {
refinedObjectClassDefinition.merge(otherComplexTypeDef);
}
@Override
public PrismContext getPrismContext() {
return refinedObjectClassDefinition.getPrismContext();
}
@Override
public ResourceAttributeContainer instantiate(QName name) {
return ObjectClassComplexTypeDefinitionImpl.instantiate(name, this);
}
// @Override
// public <T> PrismPropertyDefinition<T> findPropertyDefinition(@NotNull QName name) {
// LayerRefinedAttributeDefinition<T> def = findAttributeDefinition(name);
// if (def != null) {
// return def;
// } else {
// return LayerRefinedAttributeDefinitionImpl.wrap((RefinedAttributeDefinition<T>) refinedObjectClassDefinition.findPropertyDefinition(name), layer);
// }
// }
@Override
public <X> LayerRefinedAttributeDefinition<X> findAttributeDefinition(@NotNull QName elementQName) {
for (LayerRefinedAttributeDefinition definition : getAttributeDefinitions()) {
if (QNameUtil.match(definition.getName(), elementQName)) {
return definition;
}
}
return null;
}
@Override
public LayerRefinedAttributeDefinition<?> findAttributeDefinition(String elementLocalname) {
return findAttributeDefinition(new QName(getResourceNamespace(), elementLocalname)); // todo or should we use ns-less matching?
}
@Override
public String getDisplayName() {
return refinedObjectClassDefinition.getDisplayName();
}
@NotNull
@Override
public List<? extends ItemDefinition> getDefinitions() {
return getAttributeDefinitions();
}
@Override
public String getDescription() {
return refinedObjectClassDefinition.getDescription();
}
@Override
public boolean isDefault() {
return refinedObjectClassDefinition.isDefault();
}
@Override
public ObjectClassComplexTypeDefinition getObjectClassDefinition() {
return refinedObjectClassDefinition.getObjectClassDefinition();
}
@NotNull
@Override
public List<? extends LayerRefinedAttributeDefinition<?>> getAttributeDefinitions() {
if (layerRefinedAttributeDefinitions == null) {
layerRefinedAttributeDefinitions = LayerRefinedAttributeDefinitionImpl.wrapCollection(refinedObjectClassDefinition.getAttributeDefinitions(), layer);
}
return layerRefinedAttributeDefinitions;
}
@Override
public boolean containsAttributeDefinition(ItemPathType pathType) {
return refinedObjectClassDefinition.containsAttributeDefinition(pathType);
}
@Override
public ResourceType getResourceType() {
return refinedObjectClassDefinition.getResourceType();
}
@Override
public PrismObjectDefinition<ShadowType> getObjectDefinition() {
return refinedObjectClassDefinition.getObjectDefinition();
}
@Override
public boolean containsAttributeDefinition(QName attributeName) {
return refinedObjectClassDefinition.containsAttributeDefinition(attributeName);
}
@Override
public boolean isEmpty() {
return refinedObjectClassDefinition.isEmpty();
}
@Override
public PrismObject<ShadowType> createBlankShadow(RefinedObjectClassDefinition definition) {
return refinedObjectClassDefinition.createBlankShadow(definition);
}
@Override
public ResourceShadowDiscriminator getShadowDiscriminator() {
return refinedObjectClassDefinition.getShadowDiscriminator();
}
@Override
public Collection<? extends QName> getNamesOfAttributesWithOutboundExpressions() {
return refinedObjectClassDefinition.getNamesOfAttributesWithOutboundExpressions();
}
@Override
public Collection<? extends QName> getNamesOfAttributesWithInboundExpressions() {
return refinedObjectClassDefinition.getNamesOfAttributesWithInboundExpressions();
}
@Override
public List<MappingType> getPasswordInbound() {
return refinedObjectClassDefinition.getPasswordInbound();
}
@Override
public List<MappingType> getPasswordOutbound() {
return refinedObjectClassDefinition.getPasswordOutbound();
}
@Override
public ObjectReferenceType getPasswordPolicy() {
return refinedObjectClassDefinition.getPasswordPolicy();
}
@Override
public ResourcePasswordDefinitionType getPasswordDefinition() {
return refinedObjectClassDefinition.getPasswordDefinition();
}
@Override
public Class<?> getCompileTimeClass() {
return refinedObjectClassDefinition.getCompileTimeClass();
}
@Override
public QName getExtensionForType() {
return refinedObjectClassDefinition.getExtensionForType();
}
@Override
public boolean isContainerMarker() {
return refinedObjectClassDefinition.isContainerMarker();
}
@Override
public boolean isPrimaryIdentifier(QName attrName) {
return refinedObjectClassDefinition.isPrimaryIdentifier(attrName);
}
@Override
public boolean isObjectMarker() {
return refinedObjectClassDefinition.isObjectMarker();
}
@Override
public boolean isXsdAnyMarker() {
return refinedObjectClassDefinition.isXsdAnyMarker();
}
@Override
public boolean isListMarker() {
return refinedObjectClassDefinition.isListMarker();
}
@Override
public QName getSuperType() {
return refinedObjectClassDefinition.getSuperType();
}
@Override
public boolean isSecondaryIdentifier(QName attrName) {
return refinedObjectClassDefinition.isSecondaryIdentifier(attrName);
}
@Override
public boolean isRuntimeSchema() {
return refinedObjectClassDefinition.isRuntimeSchema();
}
@NotNull
@Override
public Collection<RefinedAssociationDefinition> getAssociationDefinitions() {
return refinedObjectClassDefinition.getAssociationDefinitions();
}
@Override
public Collection<RefinedAssociationDefinition> getAssociationDefinitions(ShadowKindType kind) {
return refinedObjectClassDefinition.getAssociationDefinitions(kind);
}
@Override
public Collection<QName> getNamesOfAssociations() {
return refinedObjectClassDefinition.getNamesOfAssociations();
}
@Override
public ResourceActivationDefinitionType getActivationSchemaHandling() {
return refinedObjectClassDefinition.getActivationSchemaHandling();
}
@Override
public ResourceBidirectionalMappingType getActivationBidirectionalMappingType(QName propertyName) {
return refinedObjectClassDefinition.getActivationBidirectionalMappingType(propertyName);
}
@Override
public AttributeFetchStrategyType getActivationFetchStrategy(QName propertyName) {
return refinedObjectClassDefinition.getActivationFetchStrategy(propertyName);
}
@Override
public <T extends CapabilityType> T getEffectiveCapability(Class<T> capabilityClass) {
return (T) refinedObjectClassDefinition.getEffectiveCapability(capabilityClass);
}
@Override
public PagedSearchCapabilityType getPagedSearches() {
return refinedObjectClassDefinition.getPagedSearches();
}
@Override
public boolean isPagedSearchEnabled() {
return refinedObjectClassDefinition.isPagedSearchEnabled();
}
@Override
public boolean isObjectCountingEnabled() {
return refinedObjectClassDefinition.isObjectCountingEnabled();
}
@Override
public Collection<RefinedAssociationDefinition> getEntitlementAssociationDefinitions() {
return refinedObjectClassDefinition.getEntitlementAssociationDefinitions();
}
@Override
public boolean isAbstract() {
return refinedObjectClassDefinition.isAbstract();
}
@Override
public boolean isDeprecated() {
return refinedObjectClassDefinition.isDeprecated();
}
@Override
public String getDocumentation() {
return refinedObjectClassDefinition.getDocumentation();
}
@Override
public String getDocumentationPreview() {
return refinedObjectClassDefinition.getDocumentationPreview();
}
@Override
public RefinedAssociationDefinition findAssociationDefinition(QName name) {
return refinedObjectClassDefinition.findAssociationDefinition(name);
}
@Override
public <ID extends ItemDefinition> ID findItemDefinition(@NotNull QName name, @NotNull Class<ID> clazz,
boolean caseInsensitive) {
ID def = refinedObjectClassDefinition.findItemDefinition(name, clazz, caseInsensitive);
return (ID) LayerRefinedAttributeDefinitionImpl.wrap((RefinedAttributeDefinition) def, layer);
}
@Override
public RefinedAssociationDefinition findEntitlementAssociationDefinition(QName name) {
return refinedObjectClassDefinition.findEntitlementAssociationDefinition(name);
}
@Override
public Collection<? extends QName> getNamesOfAssociationsWithOutboundExpressions() {
return refinedObjectClassDefinition.getNamesOfAssociationsWithOutboundExpressions();
}
@Override
public boolean matches(ShadowType shadowType) {
return refinedObjectClassDefinition.matches(shadowType);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((layer == null) ? 0 : layer.hashCode());
result = prime * result + ((refinedObjectClassDefinition == null) ? 0 : refinedObjectClassDefinition.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
// if (!super.equals(obj))
// return false;
if (getClass() != obj.getClass())
return false;
LayerRefinedObjectClassDefinitionImpl other = (LayerRefinedObjectClassDefinitionImpl) obj;
if (layer != other.layer)
return false;
if (refinedObjectClassDefinition == null) {
if (other.refinedObjectClassDefinition != null)
return false;
} else if (!refinedObjectClassDefinition.equals(other.refinedObjectClassDefinition))
return false;
return true;
}
@Override
public String debugDump() {
return debugDump(0);
}
@Override
public String getDefaultNamespace() {
return refinedObjectClassDefinition.getDefaultNamespace();
}
@Override
public String debugDump(int indent) {
return RefinedObjectClassDefinitionImpl.debugDump(indent, layer, this);
}
// Do NOT override&delegate debugDump(int indent, LayerType layer) here.
// We want to use code in the context of this class so things like
// getDebugDumpClassName() will be correct.
/**
* Return a human readable name of this class suitable for logs.
*/
public String getDebugDumpClassName() {
return "LRObjectClassDef";
}
@Override
public String getHumanReadableName() {
return refinedObjectClassDefinition.getHumanReadableName();
}
@NotNull
@Override
public LayerRefinedObjectClassDefinition clone() {
return wrap(refinedObjectClassDefinition.clone(), this.layer);
}
@NotNull
@Override
public RefinedObjectClassDefinition deepClone(Map<QName, ComplexTypeDefinition> ctdMap) {
return new LayerRefinedObjectClassDefinitionImpl(refinedObjectClassDefinition.deepClone(ctdMap), layer);
}
@Override
public String getResourceNamespace() {
return refinedObjectClassDefinition.getResourceNamespace();
}
@Override
public ResourceObjectReferenceType getBaseContext() {
return refinedObjectClassDefinition.getBaseContext();
}
@Override
public ResourceObjectVolatilityType getVolatility() {
return refinedObjectClassDefinition.getVolatility();
}
@Override
public Class getTypeClassIfKnown() {
return refinedObjectClassDefinition.getTypeClassIfKnown();
}
@NotNull
@Override
public Collection<RefinedObjectClassDefinition> getAuxiliaryObjectClassDefinitions() {
return refinedObjectClassDefinition.getAuxiliaryObjectClassDefinitions();
}
@Override
public boolean hasAuxiliaryObjectClass(QName expectedObjectClassName) {
return refinedObjectClassDefinition.hasAuxiliaryObjectClass(expectedObjectClassName);
}
@Override
public ObjectQuery createShadowSearchQuery(String resourceOid) throws SchemaException {
return refinedObjectClassDefinition.createShadowSearchQuery(resourceOid);
}
@Override
public void revive(PrismContext prismContext) {
refinedObjectClassDefinition.revive(prismContext);
}
}