use of com.evolveum.midpoint.schema.processor.ResourceAssociationDefinition in project midpoint by Evolveum.
the class ConstructionAssociationPanel method initLayout.
protected void initLayout() {
ListView<ResourceAssociationDefinition> associationsPanel = new ListView<ResourceAssociationDefinition>(ID_ASSOCIATIONS, refinedAssociationDefinitionsModel) {
@Override
protected void populateItem(ListItem<ResourceAssociationDefinition> item) {
GenericMultiValueLabelEditPanel associationReferencesPanel = new GenericMultiValueLabelEditPanel<ObjectReferenceType>(ID_ASSOCIATION_REFERENCE_PANEL, getShadowReferencesModel(item.getModelObject()), Model.of(WebComponentUtil.getAssociationDisplayName(item.getModelObject())), ID_LABEL_SIZE, ID_INPUT_SIZE, true) {
private static final long serialVersionUID = 1L;
@Override
protected boolean isEditButtonEnabled() {
return false;
}
@Override
protected void addValuePerformed(AjaxRequestTarget target) {
addNewShadowRefValuePerformed(target, item.getModelObject());
}
protected void addFirstPerformed(AjaxRequestTarget target) {
addNewShadowRefValuePerformed(target, item.getModelObject());
}
@Override
protected IModel<String> createTextModel(final IModel<ObjectReferenceType> model) {
return new IModel<String>() {
private static final long serialVersionUID = 1L;
@Override
public String getObject() {
ObjectReferenceType obj = model.getObject();
if (obj == null) {
return "";
}
return WebComponentUtil.getDisplayNameOrName(obj, getPageBase(), OPERATION_LOAD_SHADOW_DISPLAY_NAME);
}
};
}
@Override
protected void removeValuePerformed(AjaxRequestTarget target, ListItem<ObjectReferenceType> item) {
try {
ObjectReferenceType removedShadowRef = item.getModelObject();
PrismContainerWrapper<ConstructionType> constructionContainerWrapper = ConstructionAssociationPanel.this.getModelObject();
PrismContainerWrapper<ResourceObjectAssociationType> associationWrapper = constructionContainerWrapper.findContainer(ConstructionType.F_ASSOCIATION);
associationWrapper.getValues().forEach(associationValueWrapper -> {
if (ValueStatus.DELETED.equals(associationValueWrapper.getStatus())) {
return;
}
ResourceObjectAssociationType associationValue = associationValueWrapper.getRealValue();
// ResourceObjectAssociationType assoc = (ResourceObjectAssociationType) associationValue.asContainerable();
if (associationValue == null || associationValue.getOutbound() == null || associationValue.getOutbound().getExpression() == null || ExpressionUtil.getShadowRefValue(associationValue.getOutbound().getExpression(), ConstructionAssociationPanel.this.getPageBase().getPrismContext()) == null) {
return;
}
List<ObjectReferenceType> shadowRefList = ExpressionUtil.getShadowRefValue(associationValue.getOutbound().getExpression(), ConstructionAssociationPanel.this.getPageBase().getPrismContext());
shadowRefList.forEach(shadowRef -> {
if (shadowRef.equals(removedShadowRef)) {
associationValueWrapper.setStatus(ValueStatus.DELETED);
}
});
});
} catch (SchemaException ex) {
LOGGER.error("Couldn't remove association value: {}", ex.getLocalizedMessage());
}
super.removeValuePerformed(target, item);
}
};
associationReferencesPanel.setOutputMarkupId(true);
item.add(associationReferencesPanel);
}
};
associationsPanel.setOutputMarkupId(true);
add(associationsPanel);
}
use of com.evolveum.midpoint.schema.processor.ResourceAssociationDefinition in project midpoint by Evolveum.
the class TestDummyExtra method assertSchemaSanity.
@Override
protected void assertSchemaSanity(ResourceSchema resourceSchema, ResourceType resourceType) throws Exception {
// schema is extended, displayOrders are changed
dummyResourceCtl.assertDummyResourceSchemaSanityExtended(resourceSchema, resourceType, false, 20);
ResourceSchema refinedSchema = ResourceSchemaFactory.getCompleteSchema(resource);
ResourceObjectTypeDefinition accountRDef = refinedSchema.findDefaultOrAnyObjectTypeDefinition(ShadowKindType.ACCOUNT);
Collection<ResourceAssociationDefinition> associationDefinitions = accountRDef.getAssociationDefinitions();
assertEquals("Wrong number of association defs", 3, associationDefinitions.size());
ResourceAssociationDefinition crewAssociationDef = accountRDef.findAssociationDefinition(ASSOCIATION_CREW_NAME);
assertNotNull("No definition for crew association", crewAssociationDef);
}
use of com.evolveum.midpoint.schema.processor.ResourceAssociationDefinition in project midpoint by Evolveum.
the class ReconciliationProcessor method reconcileProjectionAssociations.
private void reconcileProjectionAssociations(LensProjectionContext projCtx, Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations, ResourceObjectDefinition accountDefinition, Task task, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException {
PrismObject<ShadowType> shadowNew = projCtx.getObjectNew();
PrismContainer associationsContainer = shadowNew.findContainer(ShadowType.F_ASSOCIATION);
Collection<QName> associationNames = squeezedAssociations != null ? MiscUtil.union(squeezedAssociations.keySet(), accountDefinition.getNamesOfAssociations()) : accountDefinition.getNamesOfAssociations();
for (QName assocName : associationNames) {
LOGGER.trace("Association reconciliation processing association {}", assocName);
ResourceAssociationDefinition associationDefinition = accountDefinition.findAssociationDefinition(assocName);
if (associationDefinition == null) {
throw new SchemaException("No definition for association " + assocName + " in " + projCtx.getResourceShadowDiscriminator());
}
DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> cvwoTriple = squeezedAssociations != null ? squeezedAssociations.get(assocName) : null;
// note: actually isIgnored is not implemented yet
if (associationDefinition.isIgnored()) {
LOGGER.trace("Skipping reconciliation of association {} because it is ignored", assocName);
continue;
}
// TODO implement limitations
// PropertyLimitations limitations = associationDefinition.getLimitations(LayerType.MODEL);
// if (limitations != null) {
// PropertyAccessType access = limitations.getAccess();
// if (access != null) {
// if (projCtx.isAdd() && (access.isAdd() == null || !access.isAdd())) {
// LOGGER.trace("Skipping reconciliation of attribute {} because it is non-createable",
// attrName);
// continue;
// }
// if (projCtx.isModify() && (access.isModify() == null || !access.isModify())) {
// LOGGER.trace("Skipping reconciliation of attribute {} because it is non-updateable",
// attrName);
// continue;
// }
// }
// }
Collection<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> shouldBeCValues;
if (cvwoTriple == null) {
shouldBeCValues = new HashSet<>();
} else {
shouldBeCValues = new HashSet<>(selectValidValues(cvwoTriple.getNonNegativeValues()));
}
// TODO what about equality checks? There will be probably duplicates there.
// We consider values explicitly requested by user to be among "should be values".
addContainerValuesFromDelta(shouldBeCValues, projCtx.getPrimaryDelta(), assocName);
// But we DO NOT take values from sync delta (because they just reflect what's on the resource),
// nor from secondary delta (because these got there from mappings).
// values in shouldBeCValues are parent-less
// to be able to make Containerable out of them, we provide them a (fake) parent
// (and we clone them not to mess anything)
PrismContainer<ShadowAssociationType> fakeParent = prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(ShadowAssociationType.class).instantiate();
for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> cvwo : shouldBeCValues) {
PrismContainerValue<ShadowAssociationType> cvalue = cvwo.getItemValue().clone();
cvalue.setParent(fakeParent);
cvwo.setItemValue(cvalue);
}
boolean hasStrongShouldBeCValue = false;
for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCValue : shouldBeCValues) {
if (shouldBeCValue.getMapping() != null && shouldBeCValue.getMapping().getStrength() == MappingStrengthType.STRONG) {
hasStrongShouldBeCValue = true;
break;
}
}
Collection<PrismContainerValue<ShadowAssociationType>> areCValues = new HashSet<>();
if (associationsContainer != null) {
for (Object o : associationsContainer.getValues()) {
PrismContainerValue<ShadowAssociationType> existingAssocValue = (PrismContainerValue<ShadowAssociationType>) o;
if (existingAssocValue.getValue().getName().equals(assocName)) {
areCValues.add(existingAssocValue);
}
}
} else {
areCValues = new HashSet<>();
}
// todo comment this logging code out eventually
// if (LOGGER.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// sb.append("Reconciliation\nASSOCIATION: ").append(PrettyPrinter.prettyPrint(assocName));
// sb.append("\n Should be:");
// for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>,PrismContainerDefinition<ShadowAssociationType>> shouldBeCValue : shouldBeCValues) {
// sb.append("\n ");
// sb.append(shouldBeCValue.getItemValue());
// PrismValueDeltaSetTripleProducer<?,?> shouldBeMapping = shouldBeCValue.getMapping();
// if (shouldBeMapping != null && shouldBeMapping.getStrength() == MappingStrengthType.STRONG) {
// sb.append(" STRONG");
// }
// if (shouldBeMapping != null && shouldBeMapping.getStrength() == MappingStrengthType.WEAK) {
// sb.append(" WEAK");
// }
// if (!shouldBeCValue.isValid()) {
// sb.append(" INVALID");
// }
// }
// sb.append("\n Is:");
// for (PrismContainerValue<ShadowAssociationType> isCVal : areCValues) {
// sb.append("\n ");
// sb.append(isCVal);
// }
// LOGGER.trace("{}", sb.toString());
// }
ValueMatcher associationValueMatcher = new ValueMatcher(null) {
// todo is this correct? [med]
@Override
public boolean match(Object realA, Object realB) {
checkType(realA);
checkType(realB);
if (realA == null) {
return realB == null;
} else if (realB == null) {
return false;
} else {
ShadowAssociationType a = (ShadowAssociationType) realA;
ShadowAssociationType b = (ShadowAssociationType) realB;
checkName(a);
checkName(b);
if (!a.getName().equals(b.getName())) {
return false;
}
if (a.getShadowRef() != null && a.getShadowRef().getOid() != null && b.getShadowRef() != null && b.getShadowRef().getOid() != null) {
return a.getShadowRef().getOid().equals(b.getShadowRef().getOid());
}
LOGGER.warn("Comparing association values without shadowRefs: {} and {}", a, b);
return false;
}
}
private void checkName(ShadowAssociationType s) {
if (s.getName() == null) {
throw new IllegalStateException("No name for association " + s);
}
}
@Override
public boolean matches(Object realValue, String regex) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasRealValue(PrismProperty property, PrismPropertyValue pValue) {
throw new UnsupportedOperationException();
}
@Override
public boolean isRealValueToAdd(PropertyDelta delta, PrismPropertyValue pValue) {
throw new UnsupportedOperationException();
}
private void checkType(Object o) {
if (o != null && !(o instanceof ShadowAssociationType)) {
throw new IllegalStateException("Object is not a ShadowAssociationType, it is " + o.getClass() + " instead");
}
}
};
for (ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> shouldBeCvwo : shouldBeCValues) {
PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBeCvwo.getMapping();
if (shouldBeMapping == null) {
continue;
}
if (shouldBeMapping.getStrength() != MappingStrengthType.STRONG && (!areCValues.isEmpty() || hasStrongShouldBeCValue)) {
// changed directly on the projection resource object
continue;
}
ShadowAssociationType shouldBeRealValue = shouldBeCvwo.getItemValue().getValue();
if (shouldBeCvwo.isValid() && !isInAssociationValues(associationValueMatcher, shouldBeRealValue, areCValues)) {
recordAssociationDelta(associationValueMatcher, projCtx, associationDefinition, ModificationType.ADD, shouldBeRealValue, shouldBeCvwo.getSource(), "it is given by a mapping");
}
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(" association {} before decideIfTolerateAssociation:", assocName.getLocalPart());
LOGGER.trace(" areCValues:\n{}", DebugUtil.debugDump(areCValues));
LOGGER.trace(" shouldBeCValues:\n{}", DebugUtil.debugDump(shouldBeCValues));
}
decideIfTolerateAssociation(projCtx, associationDefinition, areCValues, shouldBeCValues, associationValueMatcher, task, result);
}
}
use of com.evolveum.midpoint.schema.processor.ResourceAssociationDefinition in project midpoint by Evolveum.
the class DotModel method exportDot.
public String exportDot() {
StringBuilder sb = new StringBuilder();
sb.append("digraph G {\n");
Set<DataItem> itemsShown = new HashSet<>();
int clusterNumber = 1;
int indent = 1;
for (PrismObject<ResourceType> resource : dataModel.getResources().values()) {
if (subgraphsForResources) {
sb.append(indent(indent)).append("subgraph cluster_").append(clusterNumber++).append(" {\n");
sb.append(indent(indent + 1)).append("label=\"").append(resource.getName()).append("\";\n");
// TODO style for resource label
indent++;
}
ResourceSchema schema = dataModel.getRefinedResourceSchema(resource.getOid());
for (ResourceObjectTypeDefinition def : schema.getObjectTypeDefinitions()) {
StringBuilder sb1 = new StringBuilder();
sb1.append(indent(indent)).append("subgraph cluster_").append(clusterNumber++).append(" {\n");
String typeName = "";
if (!subgraphsForResources && dataModel.getResources().size() > 1) {
typeName = PolyString.getOrig(resource.getName()) + LF;
}
typeName += getObjectTypeName(def, true);
sb1.append(indent(indent + 1)).append("label=\"").append(typeName).append("\";\n");
sb1.append(indent(indent + 1)).append("fontname=\"times-bold\";\n\n");
String previousNodeName = null;
indent++;
for (ResourceAttributeDefinition attrDef : def.getAttributeDefinitions()) {
if (attrDef.isIgnored()) {
continue;
}
ResourceDataItem item = dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), attrDef.getItemName());
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, item);
}
for (ResourceAssociationDefinition assocDef : def.getAssociationDefinitions()) {
if (assocDef.isIgnored()) {
continue;
}
ResourceDataItem item = dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), assocDef.getName());
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, item);
}
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS)));
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), ItemPath.create(ShadowType.F_ACTIVATION, DataModelVisualizerImpl.ACTIVATION_EXISTENCE)));
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_VALID_FROM)));
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_VALID_TO)));
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_LOCKOUT_STATUS)));
previousNodeName = addResourceItem(itemsShown, indent, sb1, previousNodeName, dataModel.findResourceItem(resource.getOid(), def.getKind(), def.getIntent(), getObjectClassName(def), ItemPath.create(ShadowType.F_CREDENTIALS, CredentialsType.F_PASSWORD)));
indent--;
sb1.append(indent(indent)).append("}\n");
if (previousNodeName != null) {
sb.append(sb1.toString());
}
}
if (subgraphsForResources) {
sb.append(indent(indent)).append("}\n");
indent--;
}
}
sb.append("\n");
int mappingNode = 1;
for (Relation relation : dataModel.getRelations()) {
showNodesIfNeeded(sb, indent, itemsShown, relation.getSources());
showNodeIfNeeded(sb, indent, itemsShown, relation.getTarget());
DotRelation dotRelation = getDotRelation(relation);
if (relation.getSources().size() == 1 && relation.getTarget() != null) {
DataItem sourceItem = relation.getSources().get(0);
DataItem targetItem = relation.getTarget();
DotDataItem dotSourceItem = getDotDataItem(sourceItem);
DotDataItem dotTargetItem = getDotDataItem(targetItem);
sb.append(indent(indent)).append(dotSourceItem.getNodeName());
sb.append(" -> ").append(dotTargetItem.getNodeName());
sb.append(" [label=\"").append(dotRelation.getEdgeLabel()).append("\"");
sb.append(", style=").append(dotRelation.getEdgeStyle());
sb.append(", tooltip=\"").append(dotRelation.getEdgeTooltip()).append("\"");
sb.append(", labeltooltip=\"").append(dotRelation.getEdgeTooltip()).append("\"");
sb.append("];").append("\n");
} else {
String mappingName = "m" + (mappingNode++);
String nodeLabel = dotRelation.getNodeLabel(mappingName);
if (nodeLabel != null) {
sb.append(indent(indent)).append(mappingName).append(" [label=\"").append(nodeLabel).append("\"");
String styles = dotRelation.getNodeStyleAttributes();
if (StringUtils.isNotEmpty(styles)) {
sb.append(", ").append(styles);
}
sb.append(", tooltip=\"").append(dotRelation.getNodeTooltip()).append("\"");
sb.append("];\n");
}
for (DataItem src : relation.getSources()) {
DotDataItem dotSrc = getDotDataItem(src);
sb.append(indent(indent)).append(dotSrc.getNodeName()).append(" -> ").append(mappingName).append(" [style=").append(dotRelation.getEdgeStyle()).append("]\n");
}
if (relation.getTarget() != null) {
DotDataItem dotTarget = getDotDataItem(relation.getTarget());
sb.append(indent(indent)).append(mappingName).append(" -> ").append(dotTarget.getNodeName()).append(" [style=").append(dotRelation.getEdgeStyle()).append("]\n");
}
}
}
sb.append("}");
String dot = sb.toString();
LOGGER.debug("Resulting DOT:\n{}", dot);
return dot;
}
use of com.evolveum.midpoint.schema.processor.ResourceAssociationDefinition in project midpoint by Evolveum.
the class MappedItems method createAssociationMappingCreationRequest.
/**
* Creates a mapping creation request for mapping(s) for given association.
*
* The situation is complicated by the fact that all associations are mixed up in `shadow.association` container.
*
* @see #createAttributeMappingCreationRequest(QName)
* @see #createAuxObjClassesMappingCreationRequest()
*/
private void createAssociationMappingCreationRequest(QName associationName) {
// 1. Definitions
ResourceAssociationDefinition associationDefinition = Objects.requireNonNull(source.resourceObjectDefinition.findAssociationDefinition(associationName), () -> "No definition for association " + associationName);
ItemName itemPath = ShadowType.F_ASSOCIATION;
String itemDescription = "association " + associationName;
List<InboundMappingType> mappingBeans = source.filterApplicableMappingBeans(associationDefinition.getInboundMappingTypes());
if (mappingBeans.isEmpty()) {
LOGGER.trace("No applicable beans for this phase");
return;
}
// 2. Values
// TODO Shouldn't we filter the apriori delta for specific association? (Instead of passing any association deltas?)
ItemDelta<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> associationAPrioriDelta = getItemAPrioriDelta(itemPath);
MappedItem.ItemProvider<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>> associationProvider = () -> getCurrentAssociation(associationName);
// 3. Processing source
ProcessingMode processingMode = source.getItemProcessingMode(itemDescription, associationAPrioriDelta, mappingBeans, associationDefinition.isIgnored(LayerType.MODEL), associationDefinition.getLimitations(LayerType.MODEL));
if (processingMode == ProcessingMode.NONE) {
return;
}
// 4. Mapping creation request
mappedItems.add(new MappedItem<>(source, target, context, mappingBeans, // source path (cannot point to specified association name!)
itemPath, itemDescription, // a priori delta for all associations - see TO-DO above
associationAPrioriDelta, lazyAssociationContainerDefinition.get(), // association item provider
associationProvider, // postprocessor
source::resolveInputEntitlements, // so-called variable producer
source::getEntitlementVariableProducer, processingMode));
}
Aggregations