Skip to content

Commit

Permalink
Support native midPoint associations
Browse files Browse the repository at this point in the history
The main goal of this commit is to support native midPoint associations.
They were added into ConnId in 652bf46b0b8625817ce6a67634b592b217f65842;
their support into prism in 12808dc91f4ea358dda3666cd0b01eba7d08300c.

Main change:

Instead of ResourceSchema that somehow contained both raw and refined
(native and complete, in more modern terms) definitions, now we have
the following structures:

- NativeResourceSchema and its components: NativeObjectClassDefinition,
  NativeShadowItemDefinition (with subtypes for attributes and
  associations), and very experimental NativeAssociationClassDefinition.

  They contain information obtained from the connector or specified
  manually via XSD; and nothing more. These are not even prism
  definitions.

- ResourceSchema and its components (as before):
  ResourceObjectDefinition (for both object classes and object types),
  ShadowItemDefinition (for attributes and associations), and so on.

  These can be used in midPoint as they are regular prism definitions.
  Note that CompleteResourceSchema contains the full information known
  from ResourceType; whereas BareResourceSchema is the old "raw" one,
  that is suitable mainly for testing and diagnostics.
  The CompleteResourceSchema should be used in the code. Maybe we'll
  find a better name in the future.

Only the native definitions can be transformed into XSD. Only the
adopted ones (ResourceSchema) can be meaningfully used in midPoint.

Other changes:

1. The background change in prism was quite massive. Many places
in midPoint code had to be adapted to it.

2. (Unrelated change) ConnectorSchema was revived, and is used to store
connector configuration schemas. Creation and use of these objects was
simplified. Please use it (instead of PrismSchema) for connectors.

3. Subject-bound association definition style is back, at least for now.

4. Removed support for obsolete ref-style schema annotations like
<r:identifier ref="icfs:uid"/>. They weren't used since 2.0.

5. Dropped support for a:documentation for manually-entered resource
XSD schemas (ConnId does not support that anyway). But this is to be
reconsidered.

Work in progress.
  • Loading branch information
mederly committed Mar 26, 2024
1 parent 9239a14 commit 01f2f78
Show file tree
Hide file tree
Showing 346 changed files with 9,122 additions and 7,926 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.util.Map;

import com.evolveum.midpoint.gui.impl.util.ProvisioningObjectsUtil;
import com.evolveum.midpoint.schema.processor.ShadowAssociationDefinition;
import com.evolveum.midpoint.schema.processor.*;
import com.evolveum.midpoint.util.exception.ConfigurationException;

import org.apache.commons.collections4.CollectionUtils;
Expand All @@ -34,9 +34,6 @@
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.processor.ResourceObjectTypeDefinition;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.processor.ResourceSchemaFactory;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ default <O extends ObjectType> String getDisplayNameFromExpression(

try {
ExpressionFactory factory = locator.getExpressionFactory();
PrismPropertyDefinition<String> outputDefinition = PrismContext.get().definitionFactory().createPropertyDefinition(
PrismPropertyDefinition<String> outputDefinition = PrismContext.get().definitionFactory().newPropertyDefinition(
ExpressionConstants.OUTPUT_ELEMENT_NAME, DOMUtil.XSD_STRING);

Expression<PrismPropertyValue<String>, PrismPropertyDefinition<String>> expression =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class WrapperContext {
private ResourceShadowCoordinates coordinates;

//Association related attributes
private Collection<ShadowAssociationDefinition> shadowAssociationDefinitions;
private Collection<? extends ShadowAssociationDefinition> shadowAssociationDefinitions;

//used e.g. for metadata - opertionsla attributes but want to create wrappers for them
private boolean createOperational;
Expand Down Expand Up @@ -122,11 +122,11 @@ public void setResource(ResourceType resource) {
this.resource = resource;
}

public Collection<ShadowAssociationDefinition> getRefinedAssociationDefinitions() {
public Collection<? extends ShadowAssociationDefinition> getRefinedAssociationDefinitions() {
return shadowAssociationDefinitions;
}

public void setRefinedAssociationDefinitions(Collection<ShadowAssociationDefinition> shadowAssociationDefinitions) {
public void setRefinedAssociationDefinitions(Collection<? extends ShadowAssociationDefinition> shadowAssociationDefinitions) {
this.shadowAssociationDefinitions = shadowAssociationDefinitions;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ private OperationResult executeResultScriptHook(OperationResult result) {
OperationResult topResult = task.getResult();
try {
ExpressionFactory factory = getExpressionFactory();
PrismPropertyDefinition<OperationResultType> outputDefinition = getPrismContext().definitionFactory().createPropertyDefinition(
PrismPropertyDefinition<OperationResultType> outputDefinition = getPrismContext().definitionFactory().newPropertyDefinition(
ExpressionConstants.OUTPUT_ELEMENT_NAME, OperationResultType.COMPLEX_TYPE);
Expression<PrismPropertyValue<OperationResultType>, PrismPropertyDefinition<OperationResultType>> expression = factory.makeExpression(expressionType, outputDefinition, MiscSchemaUtil.getExpressionProfile(), contextDesc, task, topResult);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType;
Expand Down Expand Up @@ -146,7 +145,7 @@ public ObjectFilter createFilter(Class type, PageBase pageBase, VariablesMap var
SearchFilterType filter = null;
ExpressionType filterExpression = getFilterExpression();
if (filterExpression != null) {
ItemDefinition<?> outputDefinition = PrismContext.get().definitionFactory().createPropertyDefinition(
ItemDefinition<?> outputDefinition = PrismContext.get().definitionFactory().newPropertyDefinition(
ExpressionConstants.OUTPUT_ELEMENT_NAME, SearchFilterType.COMPLEX_TYPE);
Task task = pageBase.createSimpleTask("evaluate filter expression");
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ private List<ItemName> getChoicesList(PrismPropertyPanelContext<ItemPathType> ct
}

if (ConstructionType.F_ASSOCIATION.equivalent(attributeWrapper.getItemName())) {
Collection<ShadowAssociationDefinition> associationDefs = rOcd.getAssociationDefinitions();
return associationDefs.stream()
return rOcd.getAssociationDefinitions().stream()
.map(ShadowAssociationDefinition::getItemName)
.collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,24 @@

package com.evolveum.midpoint.gui.impl.factory.wrapper;

import java.util.ArrayList;
import java.util.List;

import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext;
import com.evolveum.midpoint.gui.api.prism.ItemStatus;
import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.schema.PrismSchema;
import com.evolveum.midpoint.schema.util.ConnectorTypeUtil;
import com.evolveum.midpoint.util.exception.SchemaException;

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.ConnectorType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;

import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;

import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper;
Expand Down Expand Up @@ -99,19 +94,14 @@ public PrismContainerWrapper<ConnectorConfigurationType> createWrapper(PrismCont

if (connector != null) {
ConnectorType connectorType = connector.asObjectable();
PrismSchema schema = ConnectorTypeUtil.parseConnectorSchema(connectorType);
PrismContainerDefinition<ConnectorConfigurationType> definition =
ConnectorTypeUtil.findConfigurationContainerDefinitionRequired(connectorType, schema);
// Fixing (errorneously) set maxOccurs = unbounded. See MID-2317 and related issues.
PrismContainerDefinition<ConnectorConfigurationType> definitionFixed = definition.clone();
definitionFixed.toMutable().setMaxOccurs(1);
var schema = ConnectorTypeUtil.parseConnectorSchema(connectorType);

if (childItem == null) {
childItem = parent.getNewValue().findOrCreateContainer(name);
}

// childItem = definitionFixed.instantiate();
childItem.applyDefinition(definitionFixed);
childItem.applyDefinition(schema.getConnectorConfigurationContainerDefinition());
// parent.getNewValue().addReplaceExisting(childItem);
}
} catch (Exception e) {
Expand All @@ -130,8 +120,8 @@ public PrismContainerWrapper<ConnectorConfigurationType> createWrapper(PrismCont
protected void addItemWrapper(ItemDefinition<?> def, PrismContainerValueWrapper<?> containerValueWrapper,
WrapperContext context, List<ItemWrapper<?,?>> wrappers) throws SchemaException {
if (def.isMandatory()) {
def.toMutable().toMutable().setEmphasized(true);
def.toMutable().setDisplayOrder(50);
def.mutator().setEmphasized(true);
def.mutator().setDisplayOrder(50);
}

ItemWrapper<?,?> wrapper = createChildWrapper(def, containerValueWrapper, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,30 +130,31 @@ public PrismContainerValueWrapper<O> createValueWrapper(PrismContainerWrapper<O>
continue;
}

MutableComplexTypeDefinition mCtd = getPrismContext().definitionFactory().createComplexTypeDefinition(VIRTUAL_CONTAINER_COMPLEX_TYPE);
ComplexTypeDefinition mCtd = getPrismContext().definitionFactory().newComplexTypeDefinition(VIRTUAL_CONTAINER_COMPLEX_TYPE);
DisplayType display = virtualContainer.getDisplay();

//TODO: support full polystring -> translations could be defined directly there.
if (display == null || display.getLabel() == null) {
mCtd.setDisplayName("N/A");
mCtd.mutator().setDisplayName("N/A");
} else {
mCtd.setDisplayName(WebComponentUtil.getOrigStringFromPoly(display.getLabel()));
mCtd.setHelp(WebComponentUtil.getOrigStringFromPoly(display.getHelp()));
mCtd.mutator().setDisplayName(WebComponentUtil.getOrigStringFromPoly(display.getLabel()));
mCtd.mutator().setHelp(WebComponentUtil.getOrigStringFromPoly(display.getHelp()));
}

mCtd.setRuntimeSchema(true);
mCtd.mutator().setRuntimeSchema(true);

MutablePrismContainerDefinition<?> def = getPrismContext().definitionFactory().createContainerDefinition(VIRTUAL_CONTAINER, mCtd);
def.setMaxOccurs(1);
PrismContainerDefinition<?> def =
getPrismContext().definitionFactory().newContainerDefinition(VIRTUAL_CONTAINER, mCtd);
def.mutator().setMaxOccurs(1);
if (display != null && display.getLabel() != null) {
if (display.getLabel().getTranslation() != null && StringUtils.isNotEmpty(display.getLabel().getTranslation().getKey())) {
def.setDisplayName(display.getLabel().getTranslation().getKey());
def.mutator().setDisplayName(display.getLabel().getTranslation().getKey());
} else {
def.setDisplayName(WebComponentUtil.getTranslatedPolyString(display.getLabel()));
def.mutator().setDisplayName(WebComponentUtil.getTranslatedPolyString(display.getLabel()));
}
}
def.setDynamic(true);
def.setRuntimeSchema(true);
def.mutator().setDynamic(true);
def.mutator().setRuntimeSchema(true);

ItemWrapperFactory<?, ?, ?> factory = getRegistry().findWrapperFactory(def, null);
if (factory == null) {
Expand All @@ -172,8 +173,7 @@ public PrismContainerValueWrapper<O> createValueWrapper(PrismContainerWrapper<O>
continue;
}

if (iw instanceof PrismContainerWrapper) {
PrismContainerWrapper<?> cw = (PrismContainerWrapper<?>) iw;
if (iw instanceof PrismContainerWrapper<?> cw) {
cw.setIdentifier(virtualContainer.getIdentifier());
cw.setVirtual(true);
if (virtualContainer.isExpanded() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,18 @@
import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper;
import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismContainerValueWrapperImpl;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.report.api.ReportConstants;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.prism.ValueStatus;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportParameterType;

import com.evolveum.prism.xml.ns._public.types_3.RawType;

import org.springframework.stereotype.Component;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -54,13 +50,13 @@ protected List<? extends ItemDefinition> getItemDefinitions(
if (item.getDefinition() == null && item.getRealValue() instanceof RawType) {
try {
((RawType) item.getRealValue()).getParsedRealValue(ObjectReferenceType.class);
MutablePrismReferenceDefinition def = getPrismContext().definitionFactory().createReferenceDefinition(
var def = getPrismContext().definitionFactory().newReferenceDefinition(
item.getElementName(), ObjectReferenceType.COMPLEX_TYPE);
def.setDynamic(true);
def.setRuntimeSchema(true);
def.setMaxOccurs(1);
def.setMinOccurs(0);
def.setReadOnly();
def.mutator().setDynamic(true);
def.mutator().setRuntimeSchema(true);
def.mutator().setMaxOccurs(1);
def.mutator().setMinOccurs(0);
def.mutator().setReadOnly();
defs.add(def);
} catch (SchemaException e) {
LOGGER.error("Couldn't parse ObjectReferenceType from raw type. " + item.getRealValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.util.List;

/**
Expand All @@ -45,7 +44,7 @@ public int getOrder() {
@Override
protected void addItemWrapper(ItemDefinition<?> def, PrismContainerValueWrapper<?> containerValueWrapper, WrapperContext context, List<ItemWrapper<?, ?>> wrappers) throws SchemaException {
if (ResourceType.F_DESCRIPTION.equivalent(def.getItemName())) {
def.toMutable().setEmphasized(true);
def.mutator().setEmphasized(true);
}
super.addItemWrapper(def, containerValueWrapper, context, wrappers);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@
import java.util.Collections;
import java.util.List;

import com.evolveum.midpoint.schema.processor.ShadowAssociationDefinition;
import com.evolveum.midpoint.schema.processor.*;
import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext;

import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper;
import com.evolveum.midpoint.schema.processor.ResourceObjectDefinition;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.processor.ResourceSchemaFactory;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.web.component.prism.ValueStatus;

Expand Down Expand Up @@ -89,8 +86,7 @@ protected PrismContainerWrapper<ShadowAssociationValueType> createWrapperInterna
return super.createWrapperInternal(parent, childContainer, status, ctx);
}


Collection<ShadowAssociationDefinition> shadowAssociationDefinitions = loadRefinedAssociationDefinitions(resource, shadow, parentResult);
var shadowAssociationDefinitions = loadRefinedAssociationDefinitions(resource, shadow, parentResult);

if (shadowAssociationDefinitions == null) {
return super.createWrapperInternal(parent, childContainer, status, ctx);
Expand All @@ -109,11 +105,10 @@ protected PrismContainerWrapper<ShadowAssociationValueType> createWrapperInterna
}

private PrismReferenceDefinition createShadowAssocationDef(ShadowAssociationDefinition shadowAssociationDefinitions) {
MutablePrismReferenceDefinition shadowRefDef = getPrismContext()
.definitionFactory().createReferenceDefinition(shadowAssociationDefinitions.getItemName(), ObjectReferenceType.COMPLEX_TYPE);
shadowRefDef.toMutable().setMaxOccurs(-1);
shadowRefDef.setDisplayName(shadowAssociationDefinitions.getDisplayName());
shadowRefDef.setTargetTypeName(ShadowType.COMPLEX_TYPE);
PrismReferenceDefinition shadowRefDef = getPrismContext().definitionFactory().newReferenceDefinition(
shadowAssociationDefinitions.getItemName(), ObjectReferenceType.COMPLEX_TYPE, 0, -1);
shadowRefDef.mutator().setDisplayName(shadowAssociationDefinitions.getDisplayName());
shadowRefDef.mutator().setTargetTypeName(ShadowType.COMPLEX_TYPE);
return shadowRefDef;

}
Expand Down Expand Up @@ -142,7 +137,7 @@ private PrismObject<ResourceType> loadResource(ShadowType shadow, WrapperContext

}

private Collection<ShadowAssociationDefinition> loadRefinedAssociationDefinitions(PrismObject<ResourceType> resource, ShadowType shadow, OperationResult parentResult) {
private Collection<? extends ShadowAssociationDefinition> loadRefinedAssociationDefinitions(PrismObject<ResourceType> resource, ShadowType shadow, OperationResult parentResult) {
OperationResult result = parentResult.createMinorSubresult(CREATE_ASSOCIATION_WRAPPER);
ResourceSchema refinedResourceSchema;
try {
Expand All @@ -167,7 +162,7 @@ private Collection<ShadowAssociationDefinition> loadRefinedAssociationDefinition
result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Association for " + kind + "/" + shadowIntent + " not supported by resource " + resource);
return null;
}
Collection<ShadowAssociationDefinition> shadowAssociationDefinitions = objectDefinition.getAssociationDefinitions();
var shadowAssociationDefinitions = objectDefinition.getAssociationDefinitions();

if (CollectionUtils.isEmpty(shadowAssociationDefinitions)) {
result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Association for " + kind + "/" + shadowIntent + " not supported by resource " + resource);
Expand Down Expand Up @@ -202,7 +197,7 @@ private ShadowAssociationWrapperImpl createShadowAssociationWrapper(PrismContain

ResourceType resource = ctx.getResource();
PrismContainerDefinition<ShadowAssociationValueType> associationDefinition = childContainer.getDefinition().clone();
associationDefinition.toMutable().setMaxOccurs(1);
associationDefinition.mutator().setMaxOccurs(1);
PrismContainer associationTransformed;
try {
associationTransformed = associationDefinition.instantiate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ private String getExpressionValue(ExpressionType expressionType, String contextD

C object = model.getObject();
ExpressionFactory expressionFactory = serviceLocator.getExpressionFactory();
PrismPropertyDefinition<String> outputDefinition = PrismContext.get().definitionFactory().createPropertyDefinition(ExpressionConstants.OUTPUT_ELEMENT_NAME,
DOMUtil.XSD_STRING);
PrismPropertyDefinition<String> outputDefinition = PrismContext.get().definitionFactory().newPropertyDefinition(
ExpressionConstants.OUTPUT_ELEMENT_NAME, DOMUtil.XSD_STRING);
Expression<PrismPropertyValue<String>, PrismPropertyDefinition<String>> expression = expressionFactory.makeExpression(expressionType, outputDefinition, MiscSchemaUtil.getExpressionProfile(), contextDesc, task, result);
VariablesMap variables = new VariablesMap();
variables.put(ExpressionConstants.VAR_OBJECT, object, object.asPrismContainerValue().getDefinition());
Expand Down

0 comments on commit 01f2f78

Please sign in to comment.