Skip to content

Commit

Permalink
Support for search scope (schemaHandling) (MID-5485)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Jun 26, 2019
1 parent e0bee3d commit ed430c6
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 50 deletions.
2 changes: 1 addition & 1 deletion build-system/pom.xml
Expand Up @@ -657,7 +657,7 @@
<dependency>
<groupId>com.evolveum.polygon</groupId>
<artifactId>connector-ldap</artifactId>
<version>2.3-M1</version>
<version>2.3-SNAPSHOT</version>
</dependency>
<!-- End connectors -->
<dependency>
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2018 Evolveum
* Copyright (c) 2010-2019 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,6 +25,7 @@
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinitionImpl;
import com.evolveum.midpoint.schema.processor.ResourceAttributeContainer;
import com.evolveum.midpoint.schema.processor.SearchHierarchyScope;
import com.evolveum.midpoint.schema.util.SchemaDebugUtil;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.QNameUtil;
Expand Down Expand Up @@ -309,6 +310,11 @@ public ObjectClassComplexTypeDefinition getObjectClassDefinition() {
public ResourceObjectReferenceType getBaseContext() {
return structuralObjectClassDefinition.getBaseContext();
}

@Override
public SearchHierarchyScope getSearchHierarchyScope() {
return structuralObjectClassDefinition.getSearchHierarchyScope();
}

@Override
public ResourceObjectVolatilityType getVolatility() {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2018 Evolveum
* Copyright (c) 2010-2019 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -629,6 +629,11 @@ public RefinedObjectClassDefinition deepClone(Map<QName, ComplexTypeDefinition>
public ResourceObjectReferenceType getBaseContext() {
return refinedObjectClassDefinition.getBaseContext();
}

@Override
public SearchHierarchyScope getSearchHierarchyScope() {
return refinedObjectClassDefinition.getSearchHierarchyScope();
}

@Override
public ResourceObjectVolatilityType getVolatility() {
Expand Down
Expand Up @@ -24,6 +24,7 @@
import com.evolveum.midpoint.prism.util.ItemPathTypeUtil;
import com.evolveum.midpoint.schema.ResourceShadowDiscriminator;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.schema.processor.SearchHierarchyScope;
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;
Expand Down Expand Up @@ -123,6 +124,8 @@ default Collection<? extends RefinedAttributeDefinition<?>> getAllIdentifiers()
boolean isDefault();

ResourceObjectReferenceType getBaseContext();

SearchHierarchyScope getSearchHierarchyScope();

String getHumanReadableName();

Expand Down
Expand Up @@ -78,6 +78,7 @@ public class RefinedObjectClassDefinitionImpl implements RefinedObjectClassDefin
@NotNull private final List<RefinedAttributeDefinition<?>> secondaryIdentifiers = new ArrayList<>();
@NotNull private final List<ResourceObjectPattern> protectedObjectPatterns = new ArrayList<>();
private ResourceObjectReferenceType baseContext;
private SearchHierarchyScope searchHierarchyScope;
private RefinedAttributeDefinition<?> displayNameAttributeDefinition;
private RefinedAttributeDefinition<?> namingAttributeDefinition;
private RefinedAttributeDefinition<?> descriptionAttributeDefinition;
Expand Down Expand Up @@ -288,6 +289,15 @@ public ResourceObjectReferenceType getBaseContext() {
private void setBaseContext(ResourceObjectReferenceType baseContext) {
this.baseContext = baseContext;
}

@Override
public SearchHierarchyScope getSearchHierarchyScope() {
return searchHierarchyScope;
}

public void setSearchHierarchyScope(SearchHierarchyScope searchHierarchyScope) {
this.searchHierarchyScope = searchHierarchyScope;
}

@Override
public String getIntent() {
Expand Down Expand Up @@ -1015,6 +1025,19 @@ private static RefinedObjectClassDefinition parseRefinedObjectClass(ResourceObje
if (rOcDef.schemaHandlingObjectTypeDefinitionType.getBaseContext() != null) {
rOcDef.setBaseContext(rOcDef.schemaHandlingObjectTypeDefinitionType.getBaseContext());
}

if (rOcDef.schemaHandlingObjectTypeDefinitionType.getSearchHierarchyScope() != null) {
switch (rOcDef.schemaHandlingObjectTypeDefinitionType.getSearchHierarchyScope()) {
case ONE:
rOcDef.setSearchHierarchyScope(SearchHierarchyScope.ONE);
break;
case SUB:
rOcDef.setSearchHierarchyScope(SearchHierarchyScope.SUB);
break;
default:
throw new SchemaException("Unknown search hierarchy scope: "+rOcDef.schemaHandlingObjectTypeDefinitionType.getSearchHierarchyScope());
}
}

return rOcDef;
}
Expand Down Expand Up @@ -1224,6 +1247,7 @@ public int hashCode() {
result = prime * result + attributeDefinitions.hashCode();
result = prime * result + auxiliaryObjectClassDefinitions.hashCode();
result = prime * result + ((baseContext == null) ? 0 : baseContext.hashCode());
result = prime * result + ((searchHierarchyScope == null) ? 0 : searchHierarchyScope.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((displayName == null) ? 0 : displayName.hashCode());
result = prime * result
Expand Down Expand Up @@ -1270,6 +1294,13 @@ public boolean equals(Object obj) {
} else if (!baseContext.equals(other.baseContext)) {
return false;
}
if (searchHierarchyScope == null) {
if (other.searchHierarchyScope != null) {
return false;
}
} else if (!searchHierarchyScope.equals(other.searchHierarchyScope)) {
return false;
}
if (description == null) {
if (other.description != null) {
return false;
Expand Down
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2015 Evolveum
* Copyright (c) 2015-2019 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,5 +20,16 @@
*
*/
public enum SearchHierarchyScope {
ONE, SUBTREE;
ONE("one"), SUB("sub");

private final String scopeString;

private SearchHierarchyScope(String scopeString) {
this.scopeString = scopeString;
}

public String getScopeString() {
return scopeString;
}

}
Expand Up @@ -6598,6 +6598,18 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="searchHierarchyScope" type="tns:SearchHierarchyScopeType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Definition of search hierarchy scope. It specifies how "deep" the search should go
into the object hierarchy. It is only applicable to resources that support hierarchical
organization of objects (e.g. LDAP resources).
</xsd:documentation>
<xsd:appinfo>
<a:since>4.0</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="attribute" minOccurs="0" maxOccurs="unbounded"
type="tns:ResourceAttributeDefinitionType">
<xsd:annotation>
Expand Down Expand Up @@ -6712,6 +6724,41 @@
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:simpleType name="SearchHierarchyScopeType">
<xsd:annotation>
<xsd:documentation>
Definition of search hierarchy scope. It specifies how "deep" the search should go
into the object hierarchy. It is only applicable to resources that support hierarchical
organization of objects (e.g. LDAP resources).
</xsd:documentation>
<xsd:appinfo>
<a:since>4.0</a:since>
</xsd:appinfo>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="sub">
<xsd:annotation>
<xsd:documentation>
Subtree search. The search go deep down the hierarchy, as deep as possible.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="SUB"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="one">
<xsd:annotation>
<xsd:documentation>
One-level search. The search is reaching just one level below the base context object.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="ONE"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>

<xsd:complexType name="ResourceConsistencyType">
<xsd:annotation>
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2019 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -239,17 +239,7 @@ private <S extends ShadowType,T> void postProcessEntitlementEntitlementToSubject

AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);

SearchHierarchyConstraints searchHierarchyConstraints = null;
ResourceObjectReferenceType baseContextRef = entitlementDef.getBaseContext();
if (baseContextRef != null) {
// TODO: this should be done once per search. Not in every run of postProcessEntitlementEntitlementToSubject
// this has to go outside of this method
PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx, baseContextRef,
null, "base context specification in "+entitlementDef, parentResult);
RefinedObjectClassDefinition baseContextObjectClassDefinition = subjectCtx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
}
SearchHierarchyConstraints searchHierarchyConstraints = determineSearchHierarchyConstraints(entitlementCtx, parentResult);

ShadowResultHandler handler = new ShadowResultHandler() {
@Override
Expand Down Expand Up @@ -452,15 +442,7 @@ public <T> void collectEntitlementsAsObjectOperationDelete(ProvisioningContext s

AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);

SearchHierarchyConstraints searchHierarchyConstraints = null;
ResourceObjectReferenceType baseContextRef = entitlementOcDef.getBaseContext();
if (baseContextRef != null) {
PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx,
baseContextRef, null, "base context specification in "+entitlementOcDef, parentResult);
RefinedObjectClassDefinition baseContextObjectClassDefinition = subjectCtx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
}
SearchHierarchyConstraints searchHierarchyConstraints = determineSearchHierarchyConstraints(entitlementCtx, parentResult);

ShadowResultHandler handler = new ShadowResultHandler() {
@Override
Expand Down Expand Up @@ -781,5 +763,26 @@ private ResourceAttributeContainer getIdentifiersAttributeContainer(PrismContain
return attributesContainer;
}


// This is perhaps not the best place for this method. It has nothing to do with entitlements.
// But given class dependencies this is a very convenient place. Let's leave it here for now.
public SearchHierarchyConstraints determineSearchHierarchyConstraints(final ProvisioningContext ctx, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException, SecurityViolationException {
RefinedObjectClassDefinition objectClassDef = ctx.getObjectClassDefinition();
SearchHierarchyConstraints searchHierarchyConstraints = null;
ResourceObjectReferenceType baseContextRef = objectClassDef.getBaseContext();
ResourceObjectIdentification baseContextIdentification = null;
if (baseContextRef != null) {
PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(ctx, baseContextRef, null, "base context specification in "+objectClassDef, parentResult);
if (baseContextShadow == null) {
throw new ObjectNotFoundException("No base context defined by "+baseContextRef+" in base context specification in "+objectClassDef);
}
RefinedObjectClassDefinition baseContextObjectClassDefinition = ctx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
}

SearchHierarchyScope scope = objectClassDef.getSearchHierarchyScope();
if (baseContextIdentification == null && scope == null) {
return null;
}
return new SearchHierarchyConstraints(baseContextIdentification, scope);
}
}
Expand Up @@ -1265,17 +1265,7 @@ public SearchResultMetadata searchResourceObjects(final ProvisioningContext ctx,

RefinedObjectClassDefinition objectClassDef = ctx.getObjectClassDefinition();
AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(ctx);
SearchHierarchyConstraints searchHierarchyConstraints = null;
ResourceObjectReferenceType baseContextRef = objectClassDef.getBaseContext();
if (baseContextRef != null) {
PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(ctx, baseContextRef, null, "base context specification in "+objectClassDef, parentResult);
if (baseContextShadow == null) {
throw new ObjectNotFoundException("No base context defined by "+baseContextRef+" in base context specification in "+objectClassDef);
}
RefinedObjectClassDefinition baseContextObjectClassDefinition = ctx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
}
SearchHierarchyConstraints searchHierarchyConstraints = entitlementConverter.determineSearchHierarchyConstraints(ctx, parentResult);

if (InternalsConfig.consistencyChecks && query != null && query.getFilter() != null) {
query.getFilter().checkConsistence(true);
Expand Down
Expand Up @@ -1938,18 +1938,24 @@ public String toString() {
}
if (searchHierarchyConstraints != null) {
ResourceObjectIdentification baseContextIdentification = searchHierarchyConstraints.getBaseContext();
// Only LDAP connector really supports base context. And this one will work better with
// DN. And DN is secondary identifier (__NAME__). This is ugly, but practical. It works around ConnId problems.
ResourceAttribute<?> secondaryIdentifier = baseContextIdentification.getSecondaryIdentifier();
if (secondaryIdentifier == null) {
SchemaException e = new SchemaException("No secondary identifier in base context identification "+baseContextIdentification);
result.recordFatalError(e);
throw e;
if (baseContextIdentification != null) {
// Only LDAP connector really supports base context. And this one will work better with
// DN. And DN is secondary identifier (__NAME__). This is ugly, but practical. It works around ConnId problems.
ResourceAttribute<?> secondaryIdentifier = baseContextIdentification.getSecondaryIdentifier();
if (secondaryIdentifier == null) {
SchemaException e = new SchemaException("No secondary identifier in base context identification "+baseContextIdentification);
result.recordFatalError(e);
throw e;
}
String secondaryIdentifierValue = secondaryIdentifier.getRealValue(String.class);
ObjectClass baseContextIcfObjectClass = connIdNameMapper.objectClassToConnId(baseContextIdentification.getObjectClassDefinition(), getSchemaNamespace(), connectorType, legacySchema);
QualifiedUid containerQualifiedUid = new QualifiedUid(baseContextIcfObjectClass, new Uid(secondaryIdentifierValue));
optionsBuilder.setContainer(containerQualifiedUid);
}
SearchHierarchyScope scope = searchHierarchyConstraints.getScope();
if (scope != null) {
optionsBuilder.setScope(scope.getScopeString());
}
String secondaryIdentifierValue = secondaryIdentifier.getRealValue(String.class);
ObjectClass baseContextIcfObjectClass = connIdNameMapper.objectClassToConnId(baseContextIdentification.getObjectClassDefinition(), getSchemaNamespace(), connectorType, legacySchema);
QualifiedUid containerQualifiedUid = new QualifiedUid(baseContextIcfObjectClass, new Uid(secondaryIdentifierValue));
optionsBuilder.setContainer(containerQualifiedUid);
}

} catch (SchemaException e) {
Expand Down
Expand Up @@ -23,7 +23,7 @@
<name>ICF com.evolveum.polygon.connector.ldap.LdapConnector</name>
<framework>http://midpoint.evolveum.com/xml/ns/public/connector/icf-1</framework>
<connectorType>com.evolveum.polygon.connector.ldap.LdapConnector</connectorType>
<connectorVersion>2.3-M1</connectorVersion>
<connectorVersion>2.3-SNAPSHOT</connectorVersion>
<connectorBundle>com.evolveum.polygon.connector-ldap</connectorBundle>
<namespace>http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.LdapConnector</namespace>
<schema>
Expand Down

0 comments on commit ed430c6

Please sign in to comment.