Skip to content

Commit

Permalink
Merge branch 'connid-subtypes'
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Mar 9, 2016
2 parents ea7e108 + 044671d commit 9d465a9
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 33 deletions.
Expand Up @@ -360,9 +360,12 @@ static <T> RefinedAttributeDefinition<T> parse(ResourceAttributeDefinition<T> sc
}
}

rAttrDef.matchingRuleQName = schemaAttrDef.getMatchingRuleQName();
if (schemaHandlingAttrDefType != null) {
rAttrDef.fetchStrategy = schemaHandlingAttrDefType.getFetchStrategy();
rAttrDef.matchingRuleQName = schemaHandlingAttrDefType.getMatchingRule();
if (schemaHandlingAttrDefType.getMatchingRule() != null) {
rAttrDef.matchingRuleQName = schemaHandlingAttrDefType.getMatchingRule();
}
}

PropertyLimitations schemaLimitations = getOrCreateLimitations(rAttrDef.limitationsMap, LayerType.SCHEMA);
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013 Evolveum
* Copyright (c) 2010-2016 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 @@ -73,6 +73,7 @@ public class PrismConstants {
public static final QName A_COMPOSITE = new QName(NS_ANNOTATION, "composite");
public static final QName A_DEPRECATED = new QName(NS_ANNOTATION, "deprecated");
public static final QName A_LABEL = new QName(NS_ANNOTATION, "label");
public static final QName A_MATCHING_RULE = new QName(NS_ANNOTATION, "matchingRule");

public static final QName SCHEMA_DOCUMENTATION = new QName(W3C_XML_SCHEMA_NS_URI, "documentation");
public static final QName SCHEMA_APP_INFO = new QName(W3C_XML_SCHEMA_NS_URI, "appinfo");
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2015 Evolveum
* Copyright (c) 2010-2016 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 @@ -60,6 +60,7 @@ public class PrismPropertyDefinition<T> extends ItemDefinition<PrismProperty<T>>
private Collection<? extends DisplayableValue<T>> allowedValues;
private Boolean indexed = null;
private T defaultValue;
private QName matchingRuleQName = null;

public PrismPropertyDefinition(QName elementName, QName typeName, PrismContext prismContext) {
super(elementName, typeName, prismContext);
Expand Down Expand Up @@ -121,6 +122,21 @@ public void setIndexed(Boolean indexed) {
this.indexed = indexed;
}

/**
* Returns matching rule name. Matching rules are algorithms that specify
* how to compare, normalize and/or order the values. E.g. there are matching
* rules for case insensitive string comparison, for LDAP DNs, etc.
*
* @return matching rule name
*/
public QName getMatchingRuleQName() {
return matchingRuleQName;
}

public void setMatchingRuleQName(QName matchingRuleQName) {
this.matchingRuleQName = matchingRuleQName;
}

@Override
public PrismProperty<T> instantiate() {
return instantiate(getName());
Expand Down
Expand Up @@ -33,6 +33,7 @@ public static MatchingRuleRegistry createRegistry() {
registry.registerMatchingRule(new ExchangeEmailAddressesMatchingRule());
registry.registerMatchingRule(new DistinguishedNameMatchingRule());
registry.registerMatchingRule(new XmlMatchingRule());
registry.registerMatchingRule(new UuidMatchingRule());

return registry;
}
Expand Down
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2010-2016 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.prism.match;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.namespace.QName;

import org.apache.commons.lang.StringUtils;

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.util.DOMUtil;

/**
* Matching rule for universally unique identifier (UUID).
*
* Currently it is (almost) simple case ignore matching.
*
* @author Radovan Semancik
*
*/
public class UuidMatchingRule implements MatchingRule<String> {

public static final QName NAME = new QName(PrismConstants.NS_MATCHING_RULE, "uuid");

@Override
public QName getName() {
return NAME;
}

@Override
public boolean isSupported(QName xsdType) {
return (DOMUtil.XSD_STRING.equals(xsdType));
}

/* (non-Javadoc)
* @see com.evolveum.midpoint.model.match.MatchingRule#match(java.lang.Object, java.lang.Object)
*/
@Override
public boolean match(String a, String b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
return StringUtils.equalsIgnoreCase(a.trim(), b.trim());
}

/* (non-Javadoc)
* @see com.evolveum.midpoint.prism.match.MatchingRule#normalize(java.lang.Object)
*/
@Override
public String normalize(String original) {
if (original == null) {
return null;
}
return StringUtils.lowerCase(original).trim();
}

@Override
public boolean matchRegex(String a, String regex) {
if (a == null){
return false;
}

Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(a);
return matcher.matches();
}

}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2015 Evolveum
* Copyright (c) 2010-2065 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 @@ -29,6 +29,7 @@
import static com.evolveum.midpoint.prism.PrismConstants.A_HELP;
import static com.evolveum.midpoint.prism.PrismConstants.A_IGNORE;
import static com.evolveum.midpoint.prism.PrismConstants.A_INDEXED;
import static com.evolveum.midpoint.prism.PrismConstants.A_MATCHING_RULE;
import static com.evolveum.midpoint.prism.PrismConstants.A_MAX_OCCURS;
import static com.evolveum.midpoint.prism.PrismConstants.A_OBJECT;
import static com.evolveum.midpoint.prism.PrismConstants.A_OBJECT_REFERENCE;
Expand Down Expand Up @@ -868,6 +869,12 @@ private <T> PrismPropertyDefinition<T> createPropertyDefinition(XSType xsType, Q
propDef.setIndexed(indexable);
}

Element matchingRuleElement = SchemaProcessorUtil.getAnnotationElement(annotation, A_MATCHING_RULE);
if (matchingRuleElement != null) {
QName matchingRule = XmlTypeConverter.toJavaValue(matchingRuleElement, QName.class);
propDef.setMatchingRuleQName(matchingRule);
}

return propDef;
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013 Evolveum
* Copyright (c) 2010-2016 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 @@ -256,6 +256,10 @@ private void addPropertyDefinition(PrismPropertyDefinition definition, Element p
if (definition.isIndexed() != null) {
addAnnotation(A_INDEXED, XmlTypeConverter.toXmlTextContent(definition.isIndexed(), A_INDEXED), appinfo);
}

if (definition.getMatchingRuleQName() != null) {
addAnnotation(A_MATCHING_RULE, definition.getMatchingRuleQName(), appinfo);
}

SchemaDefinitionFactory definitionFactory = getDefinitionFactory();
definitionFactory.addExtraPropertyAnnotations(definition, appinfo, this);
Expand Down
14 changes: 12 additions & 2 deletions infra/prism/src/main/resources/xml/ns/public/annotation-3.xsd
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
~ Copyright (c) 2010-2015 Evolveum
~ Copyright (c) 2010-2016 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,7 +25,7 @@
<xsd:documentation>
Common Prism annotations used in various XSD schemas.

Version: 3.2
Version: 3.4-SNAPSHOT
Default prefix: a
</xsd:documentation>
</xsd:annotation>
Expand Down Expand Up @@ -259,6 +259,16 @@
</xsd:annotation>
</xsd:attribute>

<xsd:attribute name="matchingRule" type="xsd:QName">
<xsd:annotation>
<xsd:documentation>
Matching rules are algorithms that specify
how to compare, normalize and/or order the values. E.g. there are matching
rules for case insensitive string comparison, for LDAP DNs, etc.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>

</xsd:schema>


Expand Up @@ -1161,8 +1161,10 @@ public int synchronize(ResourceShadowDiscriminator shadowCoordinates, PrismPrope
}
}

@SuppressWarnings("rawtypes") boolean processSynchronization(ProvisioningContext ctx, Change<ShadowType> change, OperationResult result) throws SchemaException, ObjectNotFoundException,
@SuppressWarnings("rawtypes")
boolean processSynchronization(ProvisioningContext ctx, Change<ShadowType> change, OperationResult result) throws SchemaException, ObjectNotFoundException,
ObjectAlreadyExistsException, CommunicationException, ConfigurationException {

ResourceObjectShadowChangeDescription shadowChangeDescription = createResourceShadowChangeDescription(
change, ctx.getResource(), ctx.getChannel());

Expand Down Expand Up @@ -1362,7 +1364,7 @@ void processChange(ProvisioningContext ctx, Change<ShadowType> change, PrismObje

}


// TODO: better move this to shadowManager?
private void forceRenameIfNeeded(ProvisioningContext ctx, ShadowType currentShadowType, ShadowType oldShadowType, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException, ConfigurationException, CommunicationException {
Collection<ResourceAttribute<?>> oldSecondaryIdentifiers = ShadowUtil.getSecondaryIdentifiers(oldShadowType);
if (oldSecondaryIdentifiers.isEmpty()){
Expand All @@ -1382,11 +1384,10 @@ private void forceRenameIfNeeded(ProvisioningContext ctx, ShadowType currentShad
Collection newValue = newSecondaryIdentifier.getRealValues();

if (!shadowManager.compareAttribute(ctx.getObjectClassDefinition(), newSecondaryIdentifier, oldSecondaryIdentifier)){
PropertyDelta<?> shadowNameDelta = PropertyDelta.createDelta(new ItemPath(ShadowType.F_ATTRIBUTES, oldSecondaryIdentifier.getElementName()), oldShadowType.asPrismObject().getDefinition());
shadowNameDelta.addValuesToDelete(PrismPropertyValue.cloneCollection((Collection)oldSecondaryIdentifier.getValues()));
shadowManager.normalizeAttributes(currentShadowType.asPrismObject(), ctx.getObjectClassDefinition());
shadowNameDelta.addValuesToAdd(PrismPropertyValue.cloneCollection((Collection)newSecondaryIdentifier.getValues()));
renameDeltas.add(shadowNameDelta);
PropertyDelta<?> propertyDelta = PropertyDelta.createDelta(new ItemPath(ShadowType.F_ATTRIBUTES, oldSecondaryIdentifier.getElementName()), oldShadowType.asPrismObject().getDefinition());
propertyDelta.addValuesToDelete(PrismPropertyValue.cloneCollection((Collection)oldSecondaryIdentifier.getValues()));
propertyDelta.addValuesToAdd(PrismPropertyValue.cloneCollection((Collection)newSecondaryIdentifier.getValues()));
renameDeltas.add(propertyDelta);
}

}
Expand All @@ -1406,6 +1407,7 @@ private void forceRenameIfNeeded(ProvisioningContext ctx, ShadowType currentShad
}
}
if (!renameDeltas.isEmpty()){
shadowManager.normalizeDeltas((Collection)renameDeltas, ctx.getObjectClassDefinition());
ConstraintsChecker.onShadowModifyOperation(renameDeltas);
repositoryService.modifyObject(ShadowType.class, oldShadowType.getOid(), renameDeltas, parentResult);
oldShadowType.setName(new PolyStringType(currentShadowName));
Expand Down
Expand Up @@ -73,6 +73,7 @@
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.crypto.EncryptionException;
import com.evolveum.midpoint.prism.crypto.Protector;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistry;
import com.evolveum.midpoint.prism.schema.PrismSchema;
import com.evolveum.midpoint.provisioning.ucf.api.ConnectorFactory;
import com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance;
Expand Down Expand Up @@ -187,13 +188,13 @@ public class ConnectorFactoryIcfImpl implements ConnectorFactory {
private Set<ConnectorType> localConnectorTypes = null;

@Autowired(required = true)
MidpointConfiguration midpointConfiguration;
private MidpointConfiguration midpointConfiguration;

@Autowired(required = true)
Protector protector;
private Protector protector;

@Autowired(required = true)
PrismContext prismContext;
private PrismContext prismContext;

public ConnectorFactoryIcfImpl() {
}
Expand Down
Expand Up @@ -31,8 +31,6 @@
import javax.xml.namespace.QName;

import com.evolveum.midpoint.common.monitor.InternalMonitor;
import com.evolveum.midpoint.prism.path.ItemPathSegment;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.prism.query.ObjectPaging;
import com.evolveum.midpoint.prism.query.OrderDirection;
import com.evolveum.midpoint.provisioning.impl.StateReporter;
Expand Down Expand Up @@ -109,6 +107,10 @@
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.match.DistinguishedNameMatchingRule;
import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule;
import com.evolveum.midpoint.prism.match.UuidMatchingRule;
import com.evolveum.midpoint.prism.match.XmlMatchingRule;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.ObjectQuery;
Expand Down Expand Up @@ -221,7 +223,7 @@ public class ConnectorInstanceIcfImpl implements ConnectorInstance {
private Boolean legacySchema = null;
private boolean supportsReturnDefaultAttributes = false;

public ConnectorInstanceIcfImpl(ConnectorInfo connectorInfo, ConnectorType connectorType,
ConnectorInstanceIcfImpl(ConnectorInfo connectorInfo, ConnectorType connectorType,
String schemaNamespace, PrismSchema connectorSchema, Protector protector,
PrismContext prismContext) {
this.cinfo = connectorInfo;
Expand Down Expand Up @@ -470,6 +472,27 @@ private boolean isMultivaluedType(Class<?> type) {
// ... unless it is byte[] or char[]
return type.isArray() && !type.equals(byte[].class) && !type.equals(char[].class);
}

private QName icfAttributeInfoToMatchingRule(AttributeInfo attributeInfo) {
String icfSubtype = attributeInfo.getSubtype();
if (icfSubtype == null) {
return null;
}
if (AttributeInfo.Subtypes.STRING_CASE_IGNORE.toString().equals(icfSubtype)) {
return StringIgnoreCaseMatchingRule.NAME;
}
if (AttributeInfo.Subtypes.STRING_LDAP_DN.toString().equals(icfSubtype)) {
return DistinguishedNameMatchingRule.NAME;
}
if (AttributeInfo.Subtypes.STRING_XML.toString().equals(icfSubtype)) {
return XmlMatchingRule.NAME;
}
if (AttributeInfo.Subtypes.STRING_UUID.toString().equals(icfSubtype)) {
return UuidMatchingRule.NAME;
}
LOGGER.debug("Unknown subtype {} defined for attribute {}, ignoring (no matching rule definition)", icfSubtype, attributeInfo.getName());
return null;
}

@Override
public void initialize(ResourceSchema resourceSchema, Collection<Object> capabilities, boolean caseIgnoreAttributeNames, OperationResult parentResult) throws CommunicationException,
Expand Down Expand Up @@ -750,6 +773,7 @@ private void parseResourceSchema(org.identityconnectors.framework.common.objects
ResourceAttributeDefinition attrDef = new ResourceAttributeDefinition(
attrXsdName, attrXsdType, prismContext);

attrDef.setMatchingRuleQName(icfAttributeInfoToMatchingRule(attributeInfo));

if (Name.NAME.equals(icfName)) {
nameDefinition = attrDef;
Expand Down

0 comments on commit 9d465a9

Please sign in to comment.