public PrismObject<ShadowType> locateResourceObject(ProvisioningContext ctx,
			Collection<? extends ResourceAttribute<?>> identifiers, OperationResult parentResult) throws ObjectNotFoundException,
			CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException {
		LOGGER.trace("Locating resource object {}", identifiers);
		ConnectorInstance connector = ctx.getConnector(ReadCapabilityType.class, parentResult);
		AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(ctx);
		if (hasAllIdentifiers(identifiers, ctx.getObjectClassDefinition())) {
			return fetchResourceObject(ctx, identifiers, 
					attributesToReturn, true, parentResult);	// todo consider whether it is always necessary to fetch the entitlements
		} else {
			// Search
			Collection<? extends RefinedAttributeDefinition> secondaryIdentifierDefs = ctx.getObjectClassDefinition().getSecondaryIdentifiers();
			// Assume single secondary identifier for simplicity
			if (secondaryIdentifierDefs.size() > 1) {
				throw new UnsupportedOperationException("Composite secondary identifier is not supported yet");
			} else if (secondaryIdentifierDefs.isEmpty()) {
				throw new SchemaException("No secondary identifier defined, cannot search");
			}
			RefinedAttributeDefinition<String> secondaryIdentifierDef = secondaryIdentifierDefs.iterator().next();
			ResourceAttribute<?> secondaryIdentifier = null;
			for (ResourceAttribute<?> identifier: identifiers) {
				if (identifier.getElementName().equals(secondaryIdentifierDef.getName())) {
					secondaryIdentifier = identifier;
				}
			}
			if (secondaryIdentifier == null) {
				throw new SchemaException("No secondary identifier present, cannot search. Identifiers: "+identifiers);
			}
			final ResourceAttribute<?> finalSecondaryIdentifier = secondaryIdentifier;
            List<PrismPropertyValue<String>> secondaryIdentifierValues = (List) secondaryIdentifier.getValues();
            PrismPropertyValue<String> secondaryIdentifierValue;
            if (secondaryIdentifierValues.size() > 1) {
                throw new IllegalStateException("Secondary identifier has more than one value: " + secondaryIdentifier.getValues());
            } else if (secondaryIdentifierValues.size() == 1) {
                secondaryIdentifierValue = secondaryIdentifierValues.get(0).clone();
            } else {
                secondaryIdentifierValue = null;
            }
            ObjectQuery query = prismContext.queryFor(ShadowType.class)
					.itemWithDef(secondaryIdentifierDef, ShadowType.F_ATTRIBUTES, secondaryIdentifierDef.getName()).eq(secondaryIdentifierValue)
					.build();
			final Holder<PrismObject<ShadowType>> shadowHolder = new Holder<>();
			ShadowResultHandler handler = new ShadowResultHandler() {
				@Override
				public boolean handle(PrismObject<ShadowType> shadow) {
					if (!shadowHolder.isEmpty()) {
						throw new IllegalStateException("More than one value found for secondary identifier "+finalSecondaryIdentifier);
					}
					shadowHolder.setValue(shadow);
					return true;
				}
			};
			try {
				connector.search(ctx.getObjectClassDefinition(), query, handler, attributesToReturn, null, null, ctx, parentResult);
				if (shadowHolder.isEmpty()) {
					throw new ObjectNotFoundException("No object found for secondary identifier "+secondaryIdentifier);
				}
				PrismObject<ShadowType> shadow = shadowHolder.getValue();
				PrismObject<ShadowType> finalShadow = postProcessResourceObjectRead(ctx, shadow, true, parentResult);
				LOGGER.trace("Located resource object {}", finalShadow);
				return finalShadow;
			} catch (GenericFrameworkException e) {
				throw new GenericConnectorException(e.getMessage(), e);
			}
		}
	}
public PrismObject<ShadowType> locateResourceObject(ProvisioningContext ctx,
			Collection<? extends ResourceAttribute<?>> identifiers, OperationResult parentResult) throws ObjectNotFoundException,
			CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException {
		LOGGER.trace("Locating resource object {}", identifiers);
		ConnectorInstance connector = ctx.getConnector(ReadCapabilityType.class, parentResult);
		AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(ctx);
		if (hasAllIdentifiers(identifiers, ctx.getObjectClassDefinition())) {
			return fetchResourceObject(ctx, identifiers, 
					attributesToReturn, true, parentResult);
		} else {
		
			Collection<? extends RefinedAttributeDefinition> secondaryIdentifierDefs = ctx.getObjectClassDefinition().getSecondaryIdentifiers();
		
			if (secondaryIdentifierDefs.size() > 1) {
				throw new UnsupportedOperationException("Composite secondary identifier is not supported yet");
			} else if (secondaryIdentifierDefs.isEmpty()) {
				throw new SchemaException("No secondary identifier defined, cannot search");
			}
			RefinedAttributeDefinition<String> secondaryIdentifierDef = secondaryIdentifierDefs.iterator().next();
			ResourceAttribute<?> secondaryIdentifier = null;
			for (ResourceAttribute<?> identifier: identifiers) {
				if (identifier.getElementName().equals(secondaryIdentifierDef.getName())) {
					secondaryIdentifier = identifier;
				}
			}
			if (secondaryIdentifier == null) {
				throw new SchemaException("No secondary identifier present, cannot search. Identifiers: "+identifiers);
			}
			final ResourceAttribute<?> finalSecondaryIdentifier = secondaryIdentifier;
            List<PrismPropertyValue<String>> secondaryIdentifierValues = (List) secondaryIdentifier.getValues();
            PrismPropertyValue<String> secondaryIdentifierValue;
            if (secondaryIdentifierValues.size() > 1) {
                throw new IllegalStateException("Secondary identifier has more than one value: " + secondaryIdentifier.getValues());
            } else if (secondaryIdentifierValues.size() == 1) {
                secondaryIdentifierValue = secondaryIdentifierValues.get(0).clone();
            } else {
                secondaryIdentifierValue = null;
            }
            ObjectQuery query = prismContext.queryFor(ShadowType.class)
					.itemWithDef(secondaryIdentifierDef, ShadowType.F_ATTRIBUTES, secondaryIdentifierDef.getName()).eq(secondaryIdentifierValue)
					.build();
			final Holder<PrismObject<ShadowType>> shadowHolder = new Holder<>();
			ShadowResultHandler handler = new ShadowResultHandler() {
				@Override
				public boolean handle(PrismObject<ShadowType> shadow) {
					if (!shadowHolder.isEmpty()) {
						throw new IllegalStateException("More than one value found for secondary identifier "+finalSecondaryIdentifier);
					}
					shadowHolder.setValue(shadow);
					return true;
				}
			};
			try {
				connector.search(ctx.getObjectClassDefinition(), query, handler, attributesToReturn, null, null, ctx, parentResult);
				if (shadowHolder.isEmpty()) {
					throw new ObjectNotFoundException("No object found for secondary identifier "+secondaryIdentifier);
				}
				PrismObject<ShadowType> shadow = shadowHolder.getValue();
				PrismObject<ShadowType> finalShadow = postProcessResourceObjectRead(ctx, shadow, true, parentResult);
				LOGGER.trace("Located resource object {}", finalShadow);
				return finalShadow;
			} catch (GenericFrameworkException e) {
				throw new GenericConnectorException(e.getMessage(), e);
			}
		}
	}
public prismobject<shadowtype> locateresourceobject(provisioningcontext ctx, collection<? extends resourceattribute<?>> identifiers, operationresult parentresult) throws objectnotfoundexception, communicationexception, schemaexception, configurationexception, securityviolationexception, genericconnectorexception, expressionevaluationexception { logger.trace("locating resource object {}", identifiers); connectorinstance connector = ctx.getconnector(readcapabilitytype.class, parentresult); attributestoreturn attributestoreturn = provisioningutil.createattributestoreturn(ctx); if (hasallidentifiers(identifiers, ctx.getobjectclassdefinition())) { return fetchresourceobject(ctx, identifiers, attributestoreturn, true, parentresult); } else { collection<? extends refinedattributedefinition> secondaryidentifierdefs = ctx.getobjectclassdefinition().getsecondaryidentifiers(); if (secondaryidentifierdefs.size() > 1) { throw new unsupportedoperationexception("composite secondary identifier is not supported yet"); } else if (secondaryidentifierdefs.isempty()) { throw new schemaexception("no secondary identifier defined, cannot search"); } refinedattributedefinition<string> secondaryidentifierdef = secondaryidentifierdefs.iterator().next(); resourceattribute<?> secondaryidentifier = null; for (resourceattribute<?> identifier: identifiers) { if (identifier.getelementname().equals(secondaryidentifierdef.getname())) { secondaryidentifier = identifier; } } if (secondaryidentifier == null) { throw new schemaexception("no secondary identifier present, cannot search. identifiers: "+identifiers); } final resourceattribute<?> finalsecondaryidentifier = secondaryidentifier; list<prismpropertyvalue<string>> secondaryidentifiervalues = (list) secondaryidentifier.getvalues(); prismpropertyvalue<string> secondaryidentifiervalue; if (secondaryidentifiervalues.size() > 1) { throw new illegalstateexception("secondary identifier has more than one value: " + secondaryidentifier.getvalues()); } else if (secondaryidentifiervalues.size() == 1) { secondaryidentifiervalue = secondaryidentifiervalues.get(0).clone(); } else { secondaryidentifiervalue = null; } objectquery query = prismcontext.queryfor(shadowtype.class) .itemwithdef(secondaryidentifierdef, shadowtype.f_attributes, secondaryidentifierdef.getname()).eq(secondaryidentifiervalue) .build(); final holder<prismobject<shadowtype>> shadowholder = new holder<>(); shadowresulthandler handler = new shadowresulthandler() { @override public boolean handle(prismobject<shadowtype> shadow) { if (!shadowholder.isempty()) { throw new illegalstateexception("more than one value found for secondary identifier "+finalsecondaryidentifier); } shadowholder.setvalue(shadow); return true; } }; try { connector.search(ctx.getobjectclassdefinition(), query, handler, attributestoreturn, null, null, ctx, parentresult); if (shadowholder.isempty()) { throw new objectnotfoundexception("no object found for secondary identifier "+secondaryidentifier); } prismobject<shadowtype> shadow = shadowholder.getvalue(); prismobject<shadowtype> finalshadow = postprocessresourceobjectread(ctx, shadow, true, parentresult); logger.trace("located resource object {}", finalshadow); return finalshadow; } catch (genericframeworkexception e) { throw new genericconnectorexception(e.getmessage(), e); } } }