3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay/*
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay *
c8408fe9c4eb7f97ffa5b6aafcd4157afd478bc8Jon Branch * Copyright 2014-2015 ForgeRock AS
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay *
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * The contents of this file are subject to the terms
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * of the Common Development and Distribution License
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * (the License). You may not use this file except in
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * compliance with the License.
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay *
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * You can obtain a copy of the License at
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * http://forgerock.org/license/CDDLv1.0.html
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * See the License for the specific language governing
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * permission and limitations under the License.
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay *
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * When distributing Covered Code, include this CDDL
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * Header Notice in each file and include the License file
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * at http://forgerock.org/license/CDDLv1.0.html
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * If applicable, add the following below the CDDL Header,
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * with the fields enclosed by brackets [] replaced by
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * your own identifying information:
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay * "Portions Copyrighted [year] [name of copyright owner]"
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay */
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.json.resource.Connection
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.json.resource.NotFoundException
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.json.resource.PatchRequest
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.json.resource.ReadRequest
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.json.resource.Requests
c8408fe9c4eb7f97ffa5b6aafcd4157afd478bc8Jon Branchimport org.forgerock.json.resource.ResourceResponse
c8408fe9c4eb7f97ffa5b6aafcd4157afd478bc8Jon Branchimport org.forgerock.services.context.RootContext
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.json.resource.UpdateRequest
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.openicf.connectors.scriptedcrest.ScriptedCRESTConfiguration
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.forgerock.openicf.misc.scriptedcommon.OperationType
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.common.logging.Log
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.exceptions.ConnectorException
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.exceptions.InvalidAttributeValueException
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.exceptions.UnknownUidException
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.objects.Attribute
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.objects.ObjectClass
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.objects.OperationOptions
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.objects.Schema
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayimport org.identityconnectors.framework.common.objects.Uid
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef operation = operation as OperationType
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef updateAttributes = attributes as Set<Attribute>
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef configuration = configuration as ScriptedCRESTConfiguration
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef connection = connection as Connection
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef id = id as String
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef log = log as Log
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef objectClass = objectClass as ObjectClass
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef options = options as OperationOptions
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef uid = uid as Uid
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemaydef schema = schema as Schema
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemayswitch (operation) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay case OperationType.UPDATE:
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay Map<String, Object> objectClassInfo = configuration.propertyBag[objectClass.objectClassValue];
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (objectClassInfo != null) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (true) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay ReadRequest request = Requests.newReadRequest(objectClassInfo.resourceContainer, uid.uidValue)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay request.addField("/")
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay try {
c8408fe9c4eb7f97ffa5b6aafcd4157afd478bc8Jon Branch ResourceResponse resource = connection.read(new RootContext(), request)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay updateAttributes.each {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay def info = objectClassInfo.attributes[it.name]
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (null != info && info.attributeInfo.isUpdateable()) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (it.value == null) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (null != resource.content.get(info.jsonName)) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.addPermissive(info.jsonName, null)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else if (info.attributeInfo.isMultiValued()) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.remove(info.jsonName)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (it.value.isEmpty()) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.addPermissive(info.jsonName, it.value)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.addPermissive(info.jsonName, it.value.each { a ->
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay CRESTHelper.fromAttributeToJSON(info.attributeInfo, a)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay })
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else if (it.value.size() > 1) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay final StringBuilder msg =
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay new StringBuilder("The ").append(it.name).append(
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay " attribute is not single value attribute.");
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay throw new InvalidAttributeValueException(msg.toString());
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (it.value.isEmpty()) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay if (null != resource.content.get(info.jsonName)) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.addPermissive(info.jsonName, null)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.remove(info.jsonName)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay resource.content.addPermissive(info.jsonName, CRESTHelper.fromAttributeToJSON(info.attributeInfo, it.value.get(0)))
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
e2cd22a6774d3e0685b065c43a4078728bb6e279Jake Feasel UpdateRequest updateRequest = Requests.newUpdateRequest(request.resourcePath, resource.content)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay updateRequest.setRevision(resource.revision)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay updateRequest.addField("_id", "_rev")
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay def r = connection.update(new RootContext(), updateRequest)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay return new Uid(r.getId(), r.getRevision())
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } catch (NotFoundException e) {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay throw new UnknownUidException(uid, objectClass).initCause(e)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay PatchRequest request = Requests.newPatchRequest(objectClassInfo.resourceContainer, uid.uidValue)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay request.addField("_id", "_rev")
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay
c8408fe9c4eb7f97ffa5b6aafcd4157afd478bc8Jon Branch ResourceResponse resource = connection.patch(new RootContext(), request)
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay return new Uid(resource.getId(), resource.getRevision())
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay } else {
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay throw new UnsupportedOperationException(operation.name() + " operation of type:" +
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay objectClass.objectClassValue + " is not supported.")
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay }
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay break
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay case OperationType.ADD_ATTRIBUTE_VALUES:
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay throw new UnsupportedOperationException(operation.name() + " operation of type:" +
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay objectClass.objectClassValue + " is not supported.")
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay case OperationType.REMOVE_ATTRIBUTE_VALUES:
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay throw new UnsupportedOperationException(operation.name() + " operation of type:" +
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay objectClass.objectClassValue + " is not supported.")
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay default:
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay throw new ConnectorException("UpdateScript can not handle operation:" + operation.name())
3b9de50fdf0980762d6930a49e1a0f20b61a6f6bJason Lemay}