Skip to content

Commit

Permalink
Re-allow null intent for dependency specification
Browse files Browse the repository at this point in the history
Making indent in dependency configuration obligatory
(in d62cd32) was not a good idea.

This commit implements handling of null intent there: it is interpreted
as "default in a kind". This means that specialized methods for
dependency lookup have been introduced in DependencyProcessor class.

Also, ResourceObjectTypeDependencyType has been separated from
ShadowDiscriminatorType. Not all fields are relevant, and the
meaning (hence the docs) is different as well.
  • Loading branch information
mederly committed Jun 9, 2022
1 parent f5edba6 commit 36650b9
Show file tree
Hide file tree
Showing 40 changed files with 512 additions and 407 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -700,4 +700,9 @@ public Optional<ItemDefinition<?>> substitution(QName name) {
public @Nullable ResourceObjectTypeDefinition getTypeDefinition() {
return structuralDefinition.getTypeDefinition();
}

@Override
public boolean isDefaultFor(@NotNull ShadowKindType kind) {
return structuralDefinition.isDefaultFor(kind);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -596,4 +596,10 @@ public String getResourceOid() {
public @Nullable ResourceObjectTypeDefinition getTypeDefinition() {
return null;
}

@Override
public boolean isDefaultFor(@NotNull ShadowKindType kind) {
// Normally, object class definitions know nothing about kind/intent. This is the only exception.
return kind == ShadowKindType.ACCOUNT && isDefaultAccountDefinition();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -465,5 +465,18 @@ default boolean matchesObjectClassName(@Nullable QName name) {

/** Is this definition bound to a specific resource type? If yes, this method returns its definition. */
@Nullable ResourceObjectTypeDefinition getTypeDefinition();

/**
* Returns true if this definition can be considered as a default for the specified kind.
*
* Normally, for a type definition it means that it is marked as "default for a kind" and has the specified kind.
* But there is a special case of {@link ResourceObjectClassDefinition} with
* {@link ResourceObjectClassDefinition#isDefaultAccountDefinition()} being `true`. It is considered to be
* the default for {@link ShadowKindType#ACCOUNT}.
*
* Use with care!
*/
@Experimental
boolean isDefaultFor(@NotNull ShadowKindType kind);
//endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ private ResourceObjectTypeDefinitionImpl(
return this;
}

@Override
public boolean isDefaultFor(@NotNull ShadowKindType kind) {
return getKind() == kind
&& isDefaultForKind();
}

@Override
public @NotNull ResourceObjectClassDefinition getObjectClassDefinition() {
return refinedObjectClassDefinition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,9 @@ default ResourceObjectTypeIdentification getTypeIdentification() {
default ResourceObjectTypeDefinition getTypeDefinition() {
return delegate().getTypeDefinition();
}

@Override
default boolean isDefaultFor(@NotNull ShadowKindType kind) {
return delegate().isDefaultFor(kind);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,9 @@ default ResourceAttributeContainer instantiate(ItemName elementName) {
default @NotNull ResourceObjectTypeDefinition getTypeDefinition() {
return delegate().getTypeDefinition();
}

@Override
default boolean isDefaultFor(@NotNull ShadowKindType kind) {
return delegate().isDefaultFor(kind);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2010-2022 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.schema.util;

import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDependencyStrictnessType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDependencyType;

import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;

import static com.evolveum.midpoint.prism.Referencable.getOid;
import static com.evolveum.midpoint.util.MiscUtil.or0;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDependencyStrictnessType.STRICT;

public class ResourceObjectTypeDependencyTypeUtil {

public static String describe(ResourceObjectTypeDependencyType dependency) {
return describe(dependency, null);
}

public static String describe(ResourceObjectTypeDependencyType dependency, @Nullable String resourceName) {
if (dependency == null) {
return "null";
} else {
String resourceOid = getOid(dependency.getResourceRef());
return String.format("%s/%s on %s; with order=%d",
dependency.getKind(),
dependency.getIntent() != null ? dependency.getIntent() : "(not specified)",
resourceName != null ?
resourceName + " (" + resourceOid + ")" :
resourceOid,
or0(dependency.getOrder()));
}
}

public static @NotNull String getResourceOidRequired(@NotNull ResourceObjectTypeDependencyType dependency) {
return MiscUtil.argNonNull(
getOid(dependency.getResourceRef()),
() -> "No resource OID in dependency [" + describe(dependency) + "]");
}

public static @NotNull ShadowKindType getKindRequired(@NotNull ResourceObjectTypeDependencyType dependency) {
return MiscUtil.argNonNull(
dependency.getKind(),
() -> "No kind in dependency [" + describe(dependency) + "]");
}

public static ResourceObjectTypeDependencyStrictnessType getDependencyStrictness(
ResourceObjectTypeDependencyType dependency) {
return Objects.requireNonNullElse(dependency.getStrictness(), STRICT);
}

public static boolean isStrict(ResourceObjectTypeDependencyType dependency) {
return getDependencyStrictness(dependency) == STRICT;
}

public static boolean isForceLoadDependentShadow(ResourceObjectTypeDependencyType dependency) {
return Boolean.TRUE.equals(dependency.isForceLoad());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

import static com.evolveum.midpoint.schema.SchemaConstantsGenerated.ICF_C_RESULTS_HANDLER_CONFIGURATION;
import static com.evolveum.midpoint.schema.constants.SchemaConstants.ICF_CONFIGURATION_PROPERTIES;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDependencyStrictnessType.STRICT;

/**
* Methods that would belong to the ResourceType class but cannot go there
Expand Down Expand Up @@ -458,23 +457,6 @@ public static PrismContainer<ConnectorConfigurationType> getConfigurationContain
return resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION);
}

public static int getDependencyOrder(ResourceObjectTypeDependencyType dependency) {
if (dependency.getOrder() == 0) {
return 0;
} else {
return dependency.getOrder();
}
}

public static ResourceObjectTypeDependencyStrictnessType getDependencyStrictness(
ResourceObjectTypeDependencyType dependency) {
return Objects.requireNonNullElse(dependency.getStrictness(), STRICT);
}

public static boolean isForceLoadDependentShadow(ResourceObjectTypeDependencyType dependency) {
return Boolean.TRUE.equals(dependency.isForceLoad());
}

public static boolean isDown(ResourceType resource) {
return (resource.getOperationalState() != null
&& AvailabilityStatusType.DOWN == resource.getOperationalState().getLastAvailabilityStatus());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,9 @@ public static String prettyPrint(ResourceObjectTypeDependencyType depType) {
sb.append(depType.getKind());
sb.append("/");
sb.append(depType.getIntent());
if (depType.getOrder() != null) {
sb.append("; order ").append(depType.getOrder());
}
sb.append(")");
return sb.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1479,35 +1479,61 @@

<xsd:complexType name="ResourceObjectTypeDependencyType">
<xsd:annotation>
<xsd:documentation>
Describes a dependency of an object type on another object type.
</xsd:documentation>
<xsd:appinfo>
<a:container/>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="tns:ShadowDiscriminatorType">
<xsd:sequence>
<xsd:element name="strictness" type="tns:ResourceObjectTypeDependencyStrictnessType" minOccurs="0"/>
<xsd:element name="order" type="xsd:int" minOccurs="0" default="0">
<xsd:annotation>
<xsd:documentation>
Specifies the order in which the dependency is applied. Lower-order dependencies
are applied before higher-order dependencies. Dependencies with the same order
are applied at the same time. There must be no circular dependency formed from
dependencies of the same order.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="forceLoad" type="xsd:boolean" minOccurs="0" default="false">
<xsd:annotation>
<xsd:documentation>
Specifies if the shadow on which we depend has to be load. By default we do
not force loading full dependent shadow.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
<xsd:sequence>
<xsd:element name="resourceRef" type="c:ObjectReferenceType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
A resource this object type depends on.
If not specified, the current resource is assumed.
</xsd:documentation>
<xsd:appinfo>
<a:objectReferenceTargetType>tns:ResourceType</a:objectReferenceTargetType>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="kind" type="tns:ShadowKindType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The "kind" part of the target object type identification.
If not specified, the kind of the current object type (i.e. the dependent one) is assumed.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="intent" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The "intent" part of the target object type identification.
If not specified, the default type for given kind is assumed. (See "defaultForKind" flag.)
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="strictness" type="tns:ResourceObjectTypeDependencyStrictnessType" minOccurs="0"/>
<xsd:element name="order" type="xsd:int" minOccurs="0" default="0">
<xsd:annotation>
<xsd:documentation>
Specifies the order in which the dependency is applied. Lower-order dependencies
are applied before higher-order dependencies. Dependencies with the same order
are applied at the same time. There must be no circular dependency formed from
dependencies of the same order.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="forceLoad" type="xsd:boolean" minOccurs="0" default="false">
<xsd:annotation>
<xsd:documentation>
Specifies if the shadow on which we depend has to be loaded. By default, we do
not force loading full dependent shadow.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:simpleType name="ResourceObjectTypeDependencyStrictnessType">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ public interface ModelProjectionContext extends ModelElementContext<ShadowType>
}

/**
* Dependencies returned are always complete i.e. their resource OID, kind, and intent are non-null.
* Dependencies returned are "almost complete": resource OID and kind are non-null.
* Intent may be null; in that case, the default value has to be used.
*
* TODO decide what to return if the dependency configuration cannot be obtained; currently it's an empty list
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.io.Serializable;

import com.evolveum.midpoint.util.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDependencyType;

import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.util.annotation.Experimental;
Expand Down Expand Up @@ -71,14 +71,6 @@ public ProjectionContextFilter(
this(resourceOid, kind, intent, null, true, null);
}

public static ProjectionContextFilter fromDependency(ResourceObjectTypeDependencyType bean) {
return new ProjectionContextFilter(
MiscUtil.argNonNull(bean.getResourceRef().getOid(), () -> "No resource OID in " + bean),
MiscUtil.argNonNull(bean.getKind(), () -> "No kind in " + bean),
MiscUtil.argNonNull(bean.getIntent(), () -> "No intent in " + bean),
bean.getTag());
}

public @Nullable String getResourceOid() {
return resourceOid;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,6 @@ public static ProjectionContextKey missing() {
return new WithoutResource(null, null, 0, true);
}

/**
* Bean must be fully specified (resource OID + kind + intent are not null). This is actually the case if it was obtained
* via {@link ModelProjectionContext#getDependencies()} method.
*/
public static ProjectionContextKey fromDependency(@NotNull ResourceObjectTypeDependencyType bean) {
return classified(
MiscUtil.argNonNull(bean.getResourceRef().getOid(), () -> "No resource OID in " + bean),
MiscUtil.argNonNull(bean.getKind(), () -> "No kind in " + bean),
MiscUtil.argNonNull(bean.getIntent(), () -> "No intent in " + bean),
bean.getTag(),
or0(bean.getDiscriminatorOrder()),
Boolean.TRUE.equals(bean.isTombstone()));
}

public static ProjectionContextKey fromCoordinates(@NotNull ResourceShadowCoordinates coordinates) {
return forKnownResource(
MiscUtil.argNonNull(coordinates.getResourceOid(), () -> "No resource OID in " + coordinates),
Expand Down

0 comments on commit 36650b9

Please sign in to comment.