/*
* 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.model.impl.lens;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition;
import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition;
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl;
import com.evolveum.midpoint.model.common.expression.ExpressionUtil;
import com.evolveum.midpoint.model.common.expression.ExpressionVariables;
import com.evolveum.midpoint.model.common.mapping.Mapping;
import com.evolveum.midpoint.model.common.mapping.MappingFactory;
import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator;
import com.evolveum.midpoint.model.impl.util.Utils;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.OriginType;
import com.evolveum.midpoint.prism.PrismContainerDefinition;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple;
import com.evolveum.midpoint.prism.marshaller.QueryConvertor;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.util.ItemPathUtil;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionStrengthType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LayerType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceAttributeDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectAssociationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
/**
* Live class that contains "construction" - a definition how to construct a
* resource object. It in fact reflects the definition of ConstructionType but
* it also contains "live" objects and can evaluate the construction. It also
* contains intermediary and side results of the evaluation.
*
* @author Radovan Semancik
*
* This class is Serializable but it is not in fact serializable. It
* implements Serializable interface only to be storable in the
* PrismPropertyValue.
*/
public class Construction<F extends FocusType> extends AbstractConstruction<F,ConstructionType> {
private static final Trace LOGGER = TraceManager.getTrace(Construction.class);
private ObjectType orderOneObject;
private ResourceType resource;
private MappingFactory mappingFactory;
private MappingEvaluator mappingEvaluator;
private Collection<Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>>> attributeMappings;
private Collection<Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> associationMappings;
private RefinedObjectClassDefinition refinedObjectClassDefinition;
private List<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions;
private AssignmentPathVariables assignmentPathVariables = null;
private PrismContainerDefinition<ShadowAssociationType> associationContainerDefinition;
private PrismObject<SystemConfigurationType> systemConfiguration; // only to
// provide
// $configuration
// variable
// (MID-2372)
public Construction(ConstructionType constructionType, ObjectType source) {
super(constructionType, source);
this.attributeMappings = null;
}
public ObjectType getOrderOneObject() {
return orderOneObject;
}
public void setOrderOneObject(ObjectType orderOneObject) {
this.orderOneObject = orderOneObject;
}
public MappingFactory getMappingFactory() {
return mappingFactory;
}
public void setMappingFactory(MappingFactory mappingFactory) {
this.mappingFactory = mappingFactory;
}
public MappingEvaluator getMappingEvaluator() {
return mappingEvaluator;
}
public void setMappingEvaluator(MappingEvaluator mappingEvaluator) {
this.mappingEvaluator = mappingEvaluator;
}
public PrismObject<SystemConfigurationType> getSystemConfiguration() {
return systemConfiguration;
}
public void setSystemConfiguration(PrismObject<SystemConfigurationType> systemConfiguration) {
this.systemConfiguration = systemConfiguration;
}
public RefinedObjectClassDefinition getRefinedObjectClassDefinition() {
return refinedObjectClassDefinition;
}
public void setRefinedObjectClassDefinition(RefinedObjectClassDefinition refinedObjectClassDefinition) {
this.refinedObjectClassDefinition = refinedObjectClassDefinition;
}
public List<RefinedObjectClassDefinition> getAuxiliaryObjectClassDefinitions() {
return auxiliaryObjectClassDefinitions;
}
public void addAuxiliaryObjectClassDefinition(
RefinedObjectClassDefinition auxiliaryObjectClassDefinition) {
if (auxiliaryObjectClassDefinitions == null) {
auxiliaryObjectClassDefinitions = new ArrayList<>();
}
auxiliaryObjectClassDefinitions.add(auxiliaryObjectClassDefinition);
}
public ShadowKindType getKind() {
if (refinedObjectClassDefinition == null) {
throw new IllegalStateException("Kind can only be fetched from evaluated Construction");
}
return refinedObjectClassDefinition.getKind();
}
public String getIntent() {
if (refinedObjectClassDefinition == null) {
throw new IllegalStateException("Intent can only be fetched from evaluated Construction");
}
return refinedObjectClassDefinition.getIntent();
}
public Collection<Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>>> getAttributeMappings() {
if (attributeMappings == null) {
attributeMappings = new ArrayList<>();
}
return attributeMappings;
}
public Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>> getAttributeMapping(
QName attrName) {
for (Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>> myVc : getAttributeMappings()) {
if (myVc.getItemName().equals(attrName)) {
return myVc;
}
}
return null;
}
public void addAttributeMapping(
Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>> mapping) {
getAttributeMappings().add(mapping);
}
public boolean containsAttributeMapping(QName attributeName) {
for (Mapping<?, ?> mapping : getAttributeMappings()) {
if (attributeName.equals(mapping.getItemName())) {
return true;
}
}
return false;
}
public Collection<Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> getAssociationMappings() {
if (associationMappings == null) {
associationMappings = new ArrayList<Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>();
}
return associationMappings;
}
public void addAssociationMapping(
Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> mapping) {
getAssociationMappings().add(mapping);
}
public boolean containsAssociationMapping(QName assocName) {
for (Mapping<?, ?> mapping : getAssociationMappings()) {
if (assocName.equals(mapping.getItemName())) {
return true;
}
}
return false;
}
private ResourceType resolveTarget(String sourceDescription, Task task, OperationResult result)
throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException,
CommunicationException, ConfigurationException, SecurityViolationException {
// SearchFilterType filter = targetRef.getFilter();
ExpressionVariables variables = Utils
.getDefaultExpressionVariables(getFocusOdo().getNewObject().asObjectable(), null, null, null);
if (assignmentPathVariables == null) {
assignmentPathVariables = LensUtil.computeAssignmentPathVariables(getAssignmentPath());
}
Utils.addAssignmentPathVariables(assignmentPathVariables, variables);
LOGGER.info("Expression variables for filter evaluation: {}", variables);
ObjectFilter origFilter = QueryConvertor.parseFilter(getConstructionType().getResourceRef().getFilter(),
ResourceType.class, getPrismContext());
LOGGER.info("Orig filter {}", origFilter);
ObjectFilter evaluatedFilter = ExpressionUtil.evaluateFilterExpressions(origFilter, variables,
getMappingFactory().getExpressionFactory(), getPrismContext(),
" evaluating resource filter expression ", task, result);
LOGGER.info("evaluatedFilter filter {}", evaluatedFilter);
if (evaluatedFilter == null) {
throw new SchemaException(
"The OID is null and filter could not be evaluated in assignment targetRef in " + getSource());
}
final Collection<PrismObject<ResourceType>> results = new ArrayList<>();
ResultHandler<ResourceType> handler = (object, parentResult) -> {
LOGGER.info("Found object {}", object);
return results.add(object);
};
getObjectResolver().searchIterative(ResourceType.class, ObjectQuery.createObjectQuery(evaluatedFilter),
null, handler, task, result);
if (org.apache.commons.collections.CollectionUtils.isEmpty(results)) {
throw new IllegalArgumentException("Got no target from repository, filter:" + evaluatedFilter
+ ", class:" + ResourceType.class + " in " + sourceDescription);
}
if (results.size() > 1) {
throw new IllegalArgumentException("Got more than one target from repository, filter:"
+ evaluatedFilter + ", class:" + ResourceType.class + " in " + sourceDescription);
}
PrismObject<ResourceType> target = results.iterator().next();
// assignmentType.getTargetRef().setOid(target.getOid());
return target.asObjectable();
}
public ResourceType getResource(Task task, OperationResult result)
throws ObjectNotFoundException, SchemaException {
if (resource == null) {
if (getConstructionType().getResource() != null) {
resource = getConstructionType().getResource();
} else if (getConstructionType().getResourceRef() != null) {
try {
if (getConstructionType().getResourceRef().getOid() == null) {
resource = resolveTarget(" resolving resource ", task, result);
} else {
resource = LensUtil.getResourceReadOnly(getLensContext(),
getConstructionType().getResourceRef().getOid(), getObjectResolver(), task, result);
}
} catch (ObjectNotFoundException e) {
throw new ObjectNotFoundException(
"Resource reference seems to be invalid in account construction in " + getSource()
+ ": " + e.getMessage(),
e);
} catch (SecurityViolationException | CommunicationException | ConfigurationException e) {
throw new SystemException("Couldn't fetch the resource in account construction in "
+ getSource() + ": " + e.getMessage(), e);
} catch (ExpressionEvaluationException e) {
throw new SystemException(
"Couldn't evaluate filter expression for the resource in account construction in "
+ getSource() + ": " + e.getMessage(),
e);
}
}
if (resource == null) {
throw new SchemaException("No resource set in account construction in " + getSource()
+ ", resource : " + getConstructionType().getResource() + ", resourceRef: "
+ getConstructionType().getResourceRef());
}
getConstructionType().getResourceRef().setOid(resource.getOid());
}
return resource;
}
public void evaluate(Task task, OperationResult result)
throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException {
assignmentPathVariables = LensUtil.computeAssignmentPathVariables(getAssignmentPath());
evaluateKindIntentObjectClass(task, result);
evaluateAttributes(task, result);
evaluateAssociations(task, result);
}
private void evaluateKindIntentObjectClass(Task task, OperationResult result)
throws SchemaException, ObjectNotFoundException {
String resourceOid = null;
if (getConstructionType().getResourceRef() != null) {
resourceOid = getConstructionType().getResourceRef().getOid();
}
if (getConstructionType().getResource() != null) {
resourceOid = getConstructionType().getResource().getOid();
}
ResourceType resource = getResource(task, result);
if (resourceOid != null && !resource.getOid().equals(resourceOid)) {
throw new IllegalStateException(
"The specified resource and the resource in construction does not match");
}
RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource,
LayerType.MODEL, getPrismContext());
if (refinedSchema == null) {
// Refined schema may be null in some error-related border cases
throw new SchemaException("No (refined) schema for " + resource);
}
ShadowKindType kind = getConstructionType().getKind();
if (kind == null) {
kind = ShadowKindType.ACCOUNT;
}
refinedObjectClassDefinition = refinedSchema.getRefinedDefinition(kind, getConstructionType().getIntent());
if (refinedObjectClassDefinition == null) {
if (getConstructionType().getIntent() != null) {
throw new SchemaException(
"No " + kind + " type '" + getConstructionType().getIntent() + "' found in "
+ getResource(task, result) + " as specified in construction in " + getSource());
} else {
throw new SchemaException("No default " + kind + " type found in " + resource
+ " as specified in construction in " + getSource());
}
}
auxiliaryObjectClassDefinitions = new ArrayList<>(getConstructionType().getAuxiliaryObjectClass().size());
for (QName auxiliaryObjectClassName : getConstructionType().getAuxiliaryObjectClass()) {
RefinedObjectClassDefinition auxOcDef = refinedSchema
.getRefinedDefinition(auxiliaryObjectClassName);
if (auxOcDef == null) {
throw new SchemaException(
"No auxiliary object class " + auxiliaryObjectClassName + " found in "
+ getResource(task, result) + " as specified in construction in " + getSource());
}
auxiliaryObjectClassDefinitions.add(auxOcDef);
}
}
private void evaluateAttributes(Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
attributeMappings = new ArrayList<>();
// LOGGER.trace("Assignments used for account construction for {} ({}):
// {}", new Object[]{this.resource,
// assignments.size(), assignments});
for (ResourceAttributeDefinitionType attribudeDefinitionType : getConstructionType().getAttribute()) {
QName attrName = ItemPathUtil.getOnlySegmentQName(attribudeDefinitionType.getRef());
if (attrName == null) {
throw new SchemaException(
"No attribute name (ref) in attribute definition in account construction in "
+ getSource());
}
if (!attribudeDefinitionType.getInbound().isEmpty()) {
throw new SchemaException("Cannot process inbound section in definition of attribute "
+ attrName + " in account construction in " + getSource());
}
MappingType outboundMappingType = attribudeDefinitionType.getOutbound();
if (outboundMappingType == null) {
throw new SchemaException("No outbound section in definition of attribute " + attrName
+ " in account construction in " + getSource());
}
Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>> attributeMapping = evaluateAttribute(
attribudeDefinitionType, task, result);
if (attributeMapping != null) {
attributeMappings.add(attributeMapping);
}
}
}
private <T> Mapping<PrismPropertyValue<T>, ResourceAttributeDefinition<T>> evaluateAttribute(
ResourceAttributeDefinitionType attribudeDefinitionType, Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
QName attrName = ItemPathUtil.getOnlySegmentQName(attribudeDefinitionType.getRef());
if (attrName == null) {
throw new SchemaException("Missing 'ref' in attribute construction in account construction in "
+ getSource());
}
if (!attribudeDefinitionType.getInbound().isEmpty()) {
throw new SchemaException("Cannot process inbound section in definition of attribute " + attrName
+ " in account construction in " + getSource());
}
MappingType outboundMappingType = attribudeDefinitionType.getOutbound();
if (outboundMappingType == null) {
throw new SchemaException("No outbound section in definition of attribute " + attrName
+ " in account construction in " + getSource());
}
ResourceAttributeDefinition<T> outputDefinition = findAttributeDefinition(attrName);
if (outputDefinition == null) {
throw new SchemaException("Attribute " + attrName + " not found in schema for account type "
+ getIntent() + ", " + getResource(task, result)
+ " as definied in " + getSource(), attrName);
}
Mapping.Builder<PrismPropertyValue<T>, ResourceAttributeDefinition<T>> builder = mappingFactory.createMappingBuilder(
outboundMappingType,
"for attribute " + PrettyPrinter.prettyPrint(attrName) + " in " + getSource());
Mapping<PrismPropertyValue<T>, ResourceAttributeDefinition<T>> evaluatedMapping = evaluateMapping(
builder, attrName, outputDefinition, null, task, result);
LOGGER.trace("Evaluated mapping for attribute " + attrName + ": " + evaluatedMapping);
return evaluatedMapping;
}
public <T> RefinedAttributeDefinition<T> findAttributeDefinition(QName attributeName) {
if (refinedObjectClassDefinition == null) {
throw new IllegalStateException(
"Construction " + this + " was not evaluated:\n" + this.debugDump());
}
RefinedAttributeDefinition<T> attrDef = refinedObjectClassDefinition
.findAttributeDefinition(attributeName);
if (attrDef != null) {
return attrDef;
}
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
attrDef = auxiliaryObjectClassDefinition.findAttributeDefinition(attributeName);
if (attrDef != null) {
return attrDef;
}
}
return null;
}
public boolean hasValueForAttribute(QName attributeName) {
for (Mapping<? extends PrismPropertyValue<?>, ? extends PrismPropertyDefinition<?>> attributeConstruction : attributeMappings) {
if (attributeName.equals(attributeConstruction.getItemName())) {
PrismValueDeltaSetTriple<? extends PrismPropertyValue<?>> outputTriple = attributeConstruction
.getOutputTriple();
if (outputTriple != null && !outputTriple.isEmpty()) {
return true;
}
}
}
return false;
}
private void evaluateAssociations(Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
associationMappings = new ArrayList<>();
for (ResourceObjectAssociationType associationDefinitionType : getConstructionType().getAssociation()) {
QName assocName = ItemPathUtil.getOnlySegmentQName(associationDefinitionType.getRef());
if (assocName == null) {
throw new SchemaException(
"No association name (ref) in association definition in construction in " + getSource());
}
MappingType outboundMappingType = associationDefinitionType.getOutbound();
if (outboundMappingType == null) {
throw new SchemaException("No outbound section in definition of association " + assocName
+ " in construction in " + getSource());
}
Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> assocMapping =
evaluateAssociation(associationDefinitionType, task, result);
if (assocMapping != null) {
associationMappings.add(assocMapping);
}
}
}
private Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluateAssociation(
ResourceObjectAssociationType associationDefinitionType, Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
QName assocName = ItemPathUtil.getOnlySegmentQName(associationDefinitionType.getRef());
if (assocName == null) {
throw new SchemaException("Missing 'ref' in association in construction in " + getSource());
}
MappingType outboundMappingType = associationDefinitionType.getOutbound();
if (outboundMappingType == null) {
throw new SchemaException("No outbound section in definition of association " + assocName
+ " in construction in " + getSource());
}
PrismContainerDefinition<ShadowAssociationType> outputDefinition = getAssociationContainerDefinition();
Mapping.Builder<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> mappingBuilder =
mappingFactory.<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>createMappingBuilder()
.mappingType(outboundMappingType)
.contextDescription("for association " + PrettyPrinter.prettyPrint(assocName) + " in " + getSource())
.originType(OriginType.ASSIGNMENTS)
.originObject(getSource());
RefinedAssociationDefinition rAssocDef = refinedObjectClassDefinition.findAssociationDefinition(assocName);
if (rAssocDef == null) {
throw new SchemaException("No association " + assocName + " in object class "
+ refinedObjectClassDefinition.getHumanReadableName() + " in construction in " + getSource());
}
Mapping<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> evaluatedMapping = evaluateMapping(
mappingBuilder, assocName, outputDefinition, rAssocDef.getAssociationTarget(), task, result);
LOGGER.trace("Evaluated mapping for association " + assocName + ": " + evaluatedMapping);
return evaluatedMapping;
}
private <V extends PrismValue, D extends ItemDefinition> Mapping<V, D> evaluateMapping(
Mapping.Builder<V, D> builder, QName mappingQName, D outputDefinition,
RefinedObjectClassDefinition assocTargetObjectClassDefinition, Task task, OperationResult result)
throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
if (!builder.isApplicableToChannel(getChannel())) {
return null;
}
builder = builder.mappingQName(mappingQName)
.sourceContext(getFocusOdo())
.defaultTargetDefinition(outputDefinition)
.originType(getOriginType())
.originObject(getSource())
.refinedObjectClassDefinition(refinedObjectClassDefinition)
.rootNode(getFocusOdo())
.addVariableDefinition(ExpressionConstants.VAR_USER, getFocusOdo())
.addVariableDefinition(ExpressionConstants.VAR_FOCUS, getFocusOdo())
.addVariableDefinition(ExpressionConstants.VAR_SOURCE, getSource())
.addVariableDefinition(ExpressionConstants.VAR_CONTAINING_OBJECT, getSource())
.addVariableDefinition(ExpressionConstants.VAR_ORDER_ONE_OBJECT, orderOneObject);
if (assocTargetObjectClassDefinition != null) {
builder = builder.addVariableDefinition(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION,
assocTargetObjectClassDefinition);
}
builder = builder.addVariableDefinition(ExpressionConstants.VAR_RESOURCE, resource);
builder = LensUtil.addAssignmentPathVariables(builder, assignmentPathVariables);
if (getSystemConfiguration() != null) {
builder = builder.addVariableDefinition(ExpressionConstants.VAR_CONFIGURATION, getSystemConfiguration());
}
// TODO: other variables ?
// Set condition masks. There are used as a brakes to avoid evaluating
// to nonsense values in case user is not present
// (e.g. in old values in ADD situations and new values in DELETE
// situations).
if (getFocusOdo().getOldObject() == null) {
builder = builder.conditionMaskOld(false);
}
if (getFocusOdo().getNewObject() == null) {
builder = builder.conditionMaskNew(false);
}
Mapping<V, D> mapping = builder.build();
mappingEvaluator.evaluateMapping(mapping, getLensContext(), task, result);
return mapping;
}
private PrismContainerDefinition<ShadowAssociationType> getAssociationContainerDefinition() {
if (associationContainerDefinition == null) {
PrismObjectDefinition<ShadowType> shadowDefinition = getPrismContext().getSchemaRegistry()
.findObjectDefinitionByCompileTimeClass(ShadowType.class);
associationContainerDefinition = shadowDefinition
.findContainerDefinition(ShadowType.F_ASSOCIATION);
}
return associationContainerDefinition;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result
+ ((assignmentPathVariables == null) ? 0 : assignmentPathVariables.hashCode());
result = prime * result
+ ((associationContainerDefinition == null) ? 0 : associationContainerDefinition.hashCode());
result = prime * result + ((associationMappings == null) ? 0 : associationMappings.hashCode());
result = prime * result + ((attributeMappings == null) ? 0 : attributeMappings.hashCode());
result = prime * result + ((auxiliaryObjectClassDefinitions == null) ? 0
: auxiliaryObjectClassDefinitions.hashCode());
result = prime * result + ((mappingEvaluator == null) ? 0 : mappingEvaluator.hashCode());
result = prime * result + ((mappingFactory == null) ? 0 : mappingFactory.hashCode());
result = prime * result + ((orderOneObject == null) ? 0 : orderOneObject.hashCode());
result = prime * result
+ ((refinedObjectClassDefinition == null) ? 0 : refinedObjectClassDefinition.hashCode());
result = prime * result + ((resource == null) ? 0 : resource.hashCode());
result = prime * result + ((systemConfiguration == null) ? 0 : systemConfiguration.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;
}
Construction other = (Construction) obj;
if (assignmentPathVariables == null) {
if (other.assignmentPathVariables != null) {
return false;
}
} else if (!assignmentPathVariables.equals(other.assignmentPathVariables)) {
return false;
}
if (associationContainerDefinition == null) {
if (other.associationContainerDefinition != null) {
return false;
}
} else if (!associationContainerDefinition.equals(other.associationContainerDefinition)) {
return false;
}
if (associationMappings == null) {
if (other.associationMappings != null) {
return false;
}
} else if (!associationMappings.equals(other.associationMappings)) {
return false;
}
if (attributeMappings == null) {
if (other.attributeMappings != null) {
return false;
}
} else if (!attributeMappings.equals(other.attributeMappings)) {
return false;
}
if (auxiliaryObjectClassDefinitions == null) {
if (other.auxiliaryObjectClassDefinitions != null) {
return false;
}
} else if (!auxiliaryObjectClassDefinitions.equals(other.auxiliaryObjectClassDefinitions)) {
return false;
}
if (mappingEvaluator == null) {
if (other.mappingEvaluator != null) {
return false;
}
} else if (!mappingEvaluator.equals(other.mappingEvaluator)) {
return false;
}
if (mappingFactory == null) {
if (other.mappingFactory != null) {
return false;
}
} else if (!mappingFactory.equals(other.mappingFactory)) {
return false;
}
if (orderOneObject == null) {
if (other.orderOneObject != null) {
return false;
}
} else if (!orderOneObject.equals(other.orderOneObject)) {
return false;
}
if (refinedObjectClassDefinition == null) {
if (other.refinedObjectClassDefinition != null) {
return false;
}
} else if (!refinedObjectClassDefinition.equals(other.refinedObjectClassDefinition)) {
return false;
}
if (resource == null) {
if (other.resource != null) {
return false;
}
} else if (!resource.equals(other.resource)) {
return false;
}
if (systemConfiguration == null) {
if (other.systemConfiguration != null) {
return false;
}
} else if (!systemConfiguration.equals(other.systemConfiguration)) {
return false;
}
return true;
}
@Override
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.debugDumpLabel(sb, "Construction", indent);
if (refinedObjectClassDefinition == null) {
sb.append(" (no object class definition)");
if (getConstructionType() != null && getConstructionType().getResourceRef() != null) { // should
// be
// always
// the
// case
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "resourceRef / kind / intent", indent + 1);
sb.append(" ");
sb.append(ObjectTypeUtil.toShortString(getConstructionType().getResourceRef()));
sb.append(" / ");
sb.append(getConstructionType().getKind());
sb.append(" / ");
sb.append(getConstructionType().getIntent());
}
} else {
sb.append(refinedObjectClassDefinition.getShadowDiscriminator());
}
if (getConstructionType() != null && getConstructionType().getStrength() == ConstructionStrengthType.WEAK) {
sb.append(" weak");
}
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "isValid", isValid(), indent + 1);
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "auxiliary object classes", indent + 1);
if (auxiliaryObjectClassDefinitions == null) {
sb.append(" (null)");
} else if (auxiliaryObjectClassDefinitions.isEmpty()) {
sb.append(" (empty)");
} else {
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 2);
sb.append(auxiliaryObjectClassDefinition.getTypeName());
}
}
if (getConstructionType() != null && getConstructionType().getDescription() != null) {
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "description", indent + 1);
sb.append(" ").append(getConstructionType().getDescription());
}
if (attributeMappings != null && !attributeMappings.isEmpty()) {
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "attribute mappings", indent + 1);
for (Mapping mapping : attributeMappings) {
sb.append("\n");
sb.append(mapping.debugDump(indent + 2));
}
}
if (associationMappings != null && !associationMappings.isEmpty()) {
sb.append("\n");
DebugUtil.debugDumpLabel(sb, "association mappings", indent + 1);
for (Mapping mapping : associationMappings) {
sb.append("\n");
sb.append(mapping.debugDump(indent + 2));
}
}
if (getAssignmentPath() != null) {
sb.append("\n");
sb.append(getAssignmentPath().debugDump(indent + 1));
}
return sb.toString();
}
@Override
public String toString() {
return "Construction(" + (refinedObjectClassDefinition == null ? getConstructionType()
: refinedObjectClassDefinition.getShadowDiscriminator()) + " in " + getSource() + ")";
}
}