Package org.apache.syncope.core.rest.data

Source Code of org.apache.syncope.core.rest.data.AbstractAttributableDataBinder

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.syncope.core.rest.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.validation.ValidationException;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.MapContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.apache.syncope.client.mod.AbstractAttributableMod;
import org.apache.syncope.client.mod.AttributeMod;
import org.apache.syncope.client.to.AbstractAttributableTO;
import org.apache.syncope.client.to.AttributeTO;
import org.apache.syncope.client.validation.SyncopeClientCompositeErrorException;
import org.apache.syncope.client.validation.SyncopeClientException;
import org.apache.syncope.core.persistence.beans.AbstractAttr;
import org.apache.syncope.core.persistence.beans.AbstractAttrValue;
import org.apache.syncope.core.persistence.beans.AbstractAttributable;
import org.apache.syncope.core.persistence.beans.AbstractDerAttr;
import org.apache.syncope.core.persistence.beans.AbstractDerSchema;
import org.apache.syncope.core.persistence.beans.AbstractSchema;
import org.apache.syncope.core.persistence.beans.AbstractVirAttr;
import org.apache.syncope.core.persistence.beans.AbstractVirSchema;
import org.apache.syncope.core.persistence.beans.ExternalResource;
import org.apache.syncope.core.persistence.beans.SchemaMapping;
import org.apache.syncope.core.persistence.dao.AttrDAO;
import org.apache.syncope.core.persistence.dao.AttrValueDAO;
import org.apache.syncope.core.persistence.dao.ConfDAO;
import org.apache.syncope.core.persistence.dao.DerAttrDAO;
import org.apache.syncope.core.persistence.dao.DerSchemaDAO;
import org.apache.syncope.core.persistence.dao.MembershipDAO;
import org.apache.syncope.core.persistence.dao.PolicyDAO;
import org.apache.syncope.core.persistence.dao.ResourceDAO;
import org.apache.syncope.core.persistence.dao.RoleDAO;
import org.apache.syncope.core.persistence.dao.SchemaDAO;
import org.apache.syncope.core.persistence.dao.UserDAO;
import org.apache.syncope.core.persistence.dao.VirAttrDAO;
import org.apache.syncope.core.persistence.dao.VirSchemaDAO;
import org.apache.syncope.core.propagation.PropagationByResource;
import org.apache.syncope.core.util.AttributableUtil;
import org.apache.syncope.core.util.jexl.JexlUtil;
import org.apache.syncope.types.AttributableType;
import org.apache.syncope.types.PropagationOperation;
import org.apache.syncope.types.SyncopeClientExceptionType;

public abstract class AbstractAttributableDataBinder {

    /**
     * Logger.
     */
    protected static final Logger LOG = LoggerFactory.getLogger(AbstractAttributableDataBinder.class);

    @Autowired
    protected ConfDAO confDAO;

    @Autowired
    protected RoleDAO roleDAO;

    @Autowired
    protected SchemaDAO schemaDAO;

    @Autowired
    protected DerSchemaDAO derivedSchemaDAO;

    @Autowired
    protected VirSchemaDAO virtualSchemaDAO;

    @Autowired
    protected AttrDAO attributeDAO;

    @Autowired
    protected DerAttrDAO derAttrDAO;

    @Autowired
    protected VirAttrDAO virAttrDAO;

    @Autowired
    protected AttrValueDAO attributeValueDAO;

    @Autowired
    protected UserDAO userDAO;

    @Autowired
    protected ResourceDAO resourceDAO;

    @Autowired
    protected MembershipDAO membershipDAO;

    @Autowired
    protected PolicyDAO policyDAO;

    @Autowired
    private JexlUtil jexlUtil;

    private <T extends AbstractSchema> T getSchema(final String schemaName, final Class<T> reference) {

        T schema = null;
        if (StringUtils.isNotBlank(schemaName)) {
            schema = schemaDAO.find(schemaName, reference);

            // safely ignore invalid schemas from AttributeTO
            // see http://code.google.com/p/syncope/issues/detail?id=17
            if (schema == null) {
                LOG.debug("Ignoring invalid schema {}", schemaName);
            } else if (schema.isReadonly()) {
                schema = null;

                LOG.debug("Ignoring virtual or readonly schema {}", schemaName);
            }
        }

        return schema;
    }

    private <T extends AbstractDerSchema> T getDerivedSchema(final String derSchemaName, final Class<T> reference) {

        T derivedSchema = null;
        if (StringUtils.isNotBlank(derSchemaName)) {
            derivedSchema = derivedSchemaDAO.find(derSchemaName, reference);
            if (derivedSchema == null) {
                LOG.debug("Ignoring invalid derived schema {}", derSchemaName);
            }
        }

        return derivedSchema;
    }

    private <T extends AbstractVirSchema> T getVirtualSchema(final String virSchemaName, final Class<T> reference) {

        T virtualSchema = null;
        if (StringUtils.isNotBlank(virSchemaName)) {
            virtualSchema = virtualSchemaDAO.find(virSchemaName, reference);

            if (virtualSchema == null) {
                LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
            }
        }

        return virtualSchema;
    }

    private ExternalResource getResource(final String resourceName) {
        ExternalResource resource = resourceDAO.find(resourceName);

        if (resource == null) {
            LOG.debug("Ignoring invalid resource {} ", resourceName);
        }

        return resource;
    }

    protected void fillAttribute(final List<String> values, final AttributableUtil attributableUtil,
            final AbstractSchema schema, final AbstractAttr attribute, final SyncopeClientException invalidValues) {

        // if the schema is multivalue, all values are considered for
        // addition, otherwise only the fist one - if provided - is
        // considered
        List<String> valuesProvided = schema.isMultivalue()
                ? values
                : (values.isEmpty()
                ? Collections.EMPTY_LIST
                : Collections.singletonList(values.iterator().next()));

        for (String value : valuesProvided) {
            if (value == null || value.isEmpty()) {
                LOG.debug("Null value for {}, ignoring", schema.getName());
            } else {
                try {
                    attribute.addValue(value, attributableUtil);
                } catch (ValidationException e) {
                    LOG.error("Invalid value for attribute " + schema.getName() + ": " + value, e);

                    invalidValues.addElement(schema.getName() + ": " + value);
                }
            }
        }
    }

    private boolean evaluateMandatoryCondition(final String mandatoryCondition,
            final List<? extends AbstractAttr> attributes) {

        JexlContext jexlContext = new MapContext();
        jexlUtil.addAttrsToContext(attributes, jexlContext);

        return Boolean.parseBoolean(jexlUtil.evaluate(mandatoryCondition, jexlContext));
    }

    private boolean evaluateMandatoryCondition(final ExternalResource resource,
            final List<? extends AbstractAttr> attributes, final String intAttrName,
            final AttributableUtil attributableUtil) {

        boolean result = false;

        for (Iterator<SchemaMapping> itor = resource.getMappings(intAttrName, attributableUtil.intMappingType()).
                iterator(); itor.hasNext() && !result;) {

            SchemaMapping mapping = itor.next();
            result |= evaluateMandatoryCondition(mapping.getMandatoryCondition(), attributes);
        }

        return result;
    }

    private boolean evaluateMandatoryCondition(final Collection<ExternalResource> resources,
            final List<? extends AbstractAttr> attributes, final String intAttrName,
            final AttributableUtil attributableUtil) {

        boolean result = false;

        ExternalResource resource;
        for (Iterator<ExternalResource> itor = resources.iterator(); itor.hasNext() && !result;) {

            resource = itor.next();
            if (resource.isForceMandatoryConstraint()) {
                result |= evaluateMandatoryCondition(resource, attributes, intAttrName, attributableUtil);
            }
        }

        return result;
    }

    private SyncopeClientException checkMandatory(final AttributableUtil attributableUtil,
            final AbstractAttributable attributable) {

        SyncopeClientException requiredValuesMissing = new SyncopeClientException(
                SyncopeClientExceptionType.RequiredValuesMissing);

        LOG.debug("Check mandatory constraint among resources {}", attributable.getResources());
        // Check if there is some mandatory schema defined for which no value
        // has been provided
        List<AbstractSchema> allSchemas = schemaDAO.findAll(attributableUtil.schemaClass());

        for (AbstractSchema schema : allSchemas) {
            if (attributable.getAttribute(schema.getName()) == null
                    && !schema.isReadonly()
                    && (evaluateMandatoryCondition(schema.getMandatoryCondition(), attributable.getAttributes()) || evaluateMandatoryCondition(
                    attributable.getResources(), attributable.getAttributes(), schema.getName(),
                    attributableUtil))) {

                LOG.error("Mandatory schema " + schema.getName() + " not provided with values");
               
                requiredValuesMissing.addElement(schema.getName());
            }
        }

        return requiredValuesMissing;
    }

    public PropagationByResource fillVirtual(final AbstractAttributable attributable,
            final Set<String> vAttrsToBeRemoved, final Set<AttributeMod> vAttrsToBeUpdated,
            final AttributableUtil attributableUtil) {

        PropagationByResource propByRes = new PropagationByResource();

        // 1. virtual attributes to be removed
        for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
            AbstractVirSchema virtualSchema = getVirtualSchema(vAttrToBeRemoved, attributableUtil.virtualSchemaClass());

            if (virtualSchema != null) {
                AbstractVirAttr virtualAttribute = attributable.getVirtualAttribute(virtualSchema.getName());

                if (virtualAttribute == null) {
                    LOG.debug("No virtual attribute found for schema {}", virtualSchema.getName());
                } else {
                    attributable.removeVirtualAttribute(virtualAttribute);
                    virAttrDAO.delete(virtualAttribute);
                }

                for (SchemaMapping mapping : resourceDAO.findAllMappings()) {
                    if (virtualSchema.getName().equals(mapping.getIntAttrName())
                            && mapping.getIntMappingType() == attributableUtil.virtualIntMappingType()
                            && mapping.getResource() != null
                            && attributable.getResources().contains(mapping.getResource())) {

                        propByRes.add(PropagationOperation.UPDATE, mapping.getResource().getName());

                        // TODO: must be avoided to use virtual attribute as AccountId
                        if (mapping.isAccountid() && virtualAttribute != null
                                && !virtualAttribute.getValues().isEmpty()) {

                            propByRes.addOldAccountId(mapping.getResource().getName(), virtualAttribute.getValues().get(
                                    0));
                        }
                    }
                }
            }
        }

        LOG.debug("Virtual attributes to be removed:\n{}", propByRes);

        // 2. virtual attributes to be updated
        for (AttributeMod vAttrToBeUpdated : vAttrsToBeUpdated) {
            AbstractVirSchema virtualSchema = getVirtualSchema(vAttrToBeUpdated.getSchema(), attributableUtil.
                    virtualSchemaClass());

            if (virtualSchema != null) {
                for (SchemaMapping mapping : resourceDAO.findAllMappings()) {
                    if (virtualSchema.getName().equals(mapping.getIntAttrName())
                            && mapping.getIntMappingType() == attributableUtil.virtualIntMappingType()
                            && mapping.getResource() != null
                            && attributable.getResources().contains(mapping.getResource())) {

                        propByRes.add(PropagationOperation.UPDATE, mapping.getResource().getName());
                    }
                }

                AbstractVirAttr virtualAttribute = attributable.getVirtualAttribute(virtualSchema.getName());

                if (virtualAttribute == null) {
                    virtualAttribute = attributableUtil.newVirtualAttribute();
                    virtualAttribute.setVirtualSchema(virtualSchema);
                    attributable.addVirtualAttribute(virtualAttribute);
                }

                final List<String> values = new ArrayList<String>(virtualAttribute.getValues());
                values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
                values.addAll(vAttrToBeUpdated.getValuesToBeAdded());

                virtualAttribute.setValues(values);

                // Owner cannot be specified before otherwise a virtual attribute remove will be invalidated.
                virtualAttribute.setOwner(attributable);
            }
        }

        LOG.debug("Virtual attributes to be added:\n{}", propByRes);

        return propByRes;
    }

    protected PropagationByResource fill(final AbstractAttributable attributable,
            final AbstractAttributableMod attributableMod, final AttributableUtil attributableUtil,
            final SyncopeClientCompositeErrorException compositeErrorException)
            throws SyncopeClientCompositeErrorException {

        PropagationByResource propByRes = new PropagationByResource();

        SyncopeClientException invalidValues = new SyncopeClientException(SyncopeClientExceptionType.InvalidValues);

        // 1. resources to be removed
        ExternalResource resource;
        for (String resourceToBeRemoved : attributableMod.getResourcesToBeRemoved()) {

            resource = getResource(resourceToBeRemoved);

            if (resource != null) {
                propByRes.add(PropagationOperation.DELETE, resource.getName());
                attributable.removeResource(resource);
            }
        }

        LOG.debug("Resources to be removed:\n{}", propByRes);

        // 2. resources to be added
        for (String resourceToBeAdded : attributableMod.getResourcesToBeAdded()) {

            resource = getResource(resourceToBeAdded);

            if (resource != null) {
                propByRes.add(PropagationOperation.CREATE, resource.getName());
                attributable.addResource(resource);
            }
        }

        LOG.debug("Resources to be added:\n{}", propByRes);

        AbstractSchema schema;
        AbstractAttr attribute;
        AbstractDerSchema derivedSchema;
        AbstractDerAttr derivedAttribute;

        // 3. attributes to be removed
        for (String attributeToBeRemoved : attributableMod.getAttributesToBeRemoved()) {

            schema = getSchema(attributeToBeRemoved, attributableUtil.schemaClass());

            if (schema != null) {
                attribute = attributable.getAttribute(schema.getName());

                if (attribute == null) {
                    LOG.debug("No attribute found for schema {}", schema);
                } else {
                    String newValue = null;
                    for (AttributeMod mod : attributableMod.getAttributesToBeUpdated()) {
                        if (schema.getName().equals(mod.getSchema())) {
                            newValue = mod.getValuesToBeAdded().get(0);
                        }
                    }

                    if (!schema.isUniqueConstraint() || (!attribute.getUniqueValue().getStringValue().equals(newValue))) {

                        attributable.removeAttribute(attribute);
                        attributeDAO.delete(attribute.getId(), attributableUtil.attributeClass());
                    }
                }

                for (SchemaMapping mapping : resourceDAO.findAllMappings()) {
                    if (schema.getName().equals(mapping.getIntAttrName())
                            && mapping.getIntMappingType() == attributableUtil.intMappingType()
                            && mapping.getResource() != null
                            && attributable.getResources().contains(mapping.getResource())) {

                        propByRes.add(PropagationOperation.UPDATE, mapping.getResource().getName());

                        if (mapping.isAccountid() && attribute != null && !attribute.getValuesAsStrings().isEmpty()) {

                            propByRes.addOldAccountId(mapping.getResource().getName(), attribute.getValuesAsStrings().
                                    iterator().next());
                        }
                    }
                }
            }
        }

        LOG.debug("Attributes to be removed:\n{}", propByRes);

        // 4. attributes to be updated
        Set<Long> valuesToBeRemoved;
        List<String> valuesToBeAdded;
        for (AttributeMod attributeMod : attributableMod.getAttributesToBeUpdated()) {

            schema = getSchema(attributeMod.getSchema(), attributableUtil.schemaClass());

            if (schema != null) {
                for (SchemaMapping mapping : resourceDAO.findAllMappings()) {
                    if (schema.getName().equals(mapping.getIntAttrName())
                            && mapping.getIntMappingType() == attributableUtil.intMappingType()
                            && mapping.getResource() != null
                            && attributable.getResources().contains(mapping.getResource())) {

                        propByRes.add(PropagationOperation.UPDATE, mapping.getResource().getName());
                    }
                }

                attribute = attributable.getAttribute(schema.getName());
                if (attribute == null) {
                    attribute = attributableUtil.newAttribute();
                    attribute.setSchema(schema);
                    attribute.setOwner(attributable);

                    attributable.addAttribute(attribute);
                }

                // 1.1 remove values
                valuesToBeRemoved = new HashSet<Long>();
                for (String valueToBeRemoved : attributeMod.getValuesToBeRemoved()) {

                    if (attribute.getSchema().isUniqueConstraint()) {
                        if (attribute.getUniqueValue() != null
                                && valueToBeRemoved.equals(attribute.getUniqueValue().getValueAsString())) {

                            valuesToBeRemoved.add(attribute.getUniqueValue().getId());
                        }
                    } else {
                        for (AbstractAttrValue mav : attribute.getValues()) {
                            if (valueToBeRemoved.equals(mav.getValueAsString())) {
                                valuesToBeRemoved.add(mav.getId());
                            }
                        }
                    }
                }
                for (Long attributeValueId : valuesToBeRemoved) {
                    attributeValueDAO.delete(attributeValueId, attributableUtil.attributeValueClass());
                }

                // 1.2 add values
                valuesToBeAdded = attributeMod.getValuesToBeAdded();
                if (valuesToBeAdded != null
                        && !valuesToBeAdded.isEmpty()
                        && (!schema.isUniqueConstraint() || attribute.getUniqueValue() == null || !valuesToBeAdded.
                        iterator().next().equals(attribute.getUniqueValue().getValueAsString()))) {

                    fillAttribute(attributeMod.getValuesToBeAdded(), attributableUtil, schema, attribute, invalidValues);
                }

                // if no values are in, the attribute can be safely removed
                if (attribute.getValuesAsStrings().isEmpty()) {
                    attributeDAO.delete(attribute);
                }
            }
        }

        if (!invalidValues.isEmpty()) {
            compositeErrorException.addException(invalidValues);
        }

        LOG.debug("Attributes to be updated:\n{}", propByRes);

        // 5. derived attributes to be removed
        for (String derivedAttributeToBeRemoved : attributableMod.getDerivedAttributesToBeRemoved()) {

            derivedSchema = getDerivedSchema(derivedAttributeToBeRemoved, attributableUtil.derivedSchemaClass());

            if (derivedSchema != null) {
                derivedAttribute = attributable.getDerivedAttribute(derivedSchema.getName());

                if (derivedAttribute == null) {
                    LOG.debug("No derived attribute found for schema {}", derivedSchema.getName());
                } else {
                    derAttrDAO.delete(derivedAttribute);
                }

                for (SchemaMapping mapping : resourceDAO.findAllMappings()) {
                    if (derivedSchema.getName().equals(mapping.getIntAttrName())
                            && mapping.getIntMappingType() == attributableUtil.derivedIntMappingType()
                            && mapping.getResource() != null
                            && attributable.getResources().contains(mapping.getResource())) {

                        propByRes.add(PropagationOperation.UPDATE, mapping.getResource().getName());

                        if (mapping.isAccountid() && derivedAttribute != null
                                && !derivedAttribute.getValue(attributable.getAttributes()).isEmpty()) {

                            propByRes.addOldAccountId(mapping.getResource().getName(),
                                    derivedAttribute.getValue(attributable.getAttributes()));
                        }
                    }
                }
            }
        }

        LOG.debug("Derived attributes to be removed:\n{}", propByRes);

        // 6. derived attributes to be added
        for (String derivedAttributeToBeAdded : attributableMod.getDerivedAttributesToBeAdded()) {

            derivedSchema = getDerivedSchema(derivedAttributeToBeAdded, attributableUtil.derivedSchemaClass());

            if (derivedSchema != null) {
                for (SchemaMapping mapping : resourceDAO.findAllMappings()) {
                    if (derivedSchema.getName().equals(mapping.getIntAttrName())
                            && mapping.getIntMappingType() == attributableUtil.derivedIntMappingType()
                            && mapping.getResource() != null
                            && attributable.getResources().contains(mapping.getResource())) {

                        propByRes.add(PropagationOperation.UPDATE, mapping.getResource().getName());
                    }
                }

                derivedAttribute = attributableUtil.newDerivedAttribute();
                derivedAttribute.setDerivedSchema(derivedSchema);
                derivedAttribute.setOwner(attributable);
                attributable.addDerivedAttribute(derivedAttribute);
            }
        }

        LOG.debug("Derived attributes to be added:\n{}", propByRes);

        // 7. virtual attributes: for users this is delegated to PropagationManager
        if (AttributableType.USER != attributableUtil.getType()) {
            fillVirtual(attributable, attributableMod.getVirtualAttributesToBeRemoved(), attributableMod.
                    getVirtualAttributesToBeUpdated(), attributableUtil);
        }

        // Finally, check if mandatory values are missing
        SyncopeClientException requiredValuesMissing = checkMandatory(attributableUtil, attributable);
        if (!requiredValuesMissing.isEmpty()) {
            compositeErrorException.addException(requiredValuesMissing);
        }

        // Throw composite exception if there is at least one element set
        // in the composing exceptions
        if (compositeErrorException.hasExceptions()) {
            throw compositeErrorException;
        }

        return propByRes;
    }

    /**
     * Add virtual attributes and specify values to be propagated.
     *
     * @param attributable attributable.
     * @param vAttrs virtual attributes to be added.
     * @param attributableUtil attributable util.
     */
    public void fillVirtual(final AbstractAttributable attributable, final List<AttributeTO> vAttrs,
            final AttributableUtil attributableUtil) {

        for (AttributeTO attributeTO : vAttrs) {
            AbstractVirAttr virtualAttribute = attributable.getVirtualAttribute(attributeTO.getSchema());

            if (virtualAttribute == null) {
                AbstractVirSchema virtualSchema = getVirtualSchema(attributeTO.getSchema(), attributableUtil.
                        virtualSchemaClass());

                if (virtualSchema != null) {
                    virtualAttribute = attributableUtil.newVirtualAttribute();
                    virtualAttribute.setVirtualSchema(virtualSchema);
                    virtualAttribute.setOwner(attributable);
                    attributable.addVirtualAttribute(virtualAttribute);
                    virtualAttribute.setValues(attributeTO.getValues());
                }

            } else {
                virtualAttribute.setValues(attributeTO.getValues());
            }

        }
    }

    protected void fill(final AbstractAttributable attributable, final AbstractAttributableTO attributableTO,
            final AttributableUtil attributableUtil, final SyncopeClientCompositeErrorException compositeErrorException)
            throws SyncopeClientCompositeErrorException {

        // 1. attributes
        SyncopeClientException invalidValues = new SyncopeClientException(SyncopeClientExceptionType.InvalidValues);

        AbstractSchema schema;
        AbstractAttr attribute;

        // Only consider attributeTO with values
        for (AttributeTO attributeTO : attributableTO.getAttributes()) {
            if (attributeTO.getValues() != null && !attributeTO.getValues().isEmpty()) {

                schema = getSchema(attributeTO.getSchema(), attributableUtil.schemaClass());

                if (schema != null) {
                    attribute = attributable.getAttribute(schema.getName());
                    if (attribute == null) {
                        attribute = attributableUtil.newAttribute();
                        attribute.setSchema(schema);
                    }

                    fillAttribute(attributeTO.getValues(), attributableUtil, schema, attribute, invalidValues);

                    if (!attribute.getValuesAsStrings().isEmpty()) {
                        attributable.addAttribute(attribute);
                        attribute.setOwner(attributable);
                    }
                }
            }
        }

        if (!invalidValues.isEmpty()) {
            compositeErrorException.addException(invalidValues);
        }

        // 2. derived attributes
        AbstractDerSchema derivedSchema;
        AbstractDerAttr derivedAttribute;
        for (AttributeTO attributeTO : attributableTO.getDerivedAttributes()) {

            derivedSchema = getDerivedSchema(attributeTO.getSchema(), attributableUtil.derivedSchemaClass());

            if (derivedSchema != null) {
                derivedAttribute = attributableUtil.newDerivedAttribute();
                derivedAttribute.setDerivedSchema(derivedSchema);
                derivedAttribute.setOwner(attributable);
                attributable.addDerivedAttribute(derivedAttribute);
            }
        }

        // 3. user virtual attributes will be valued by the propagation manager only (if needed).
        if (AttributableType.USER == attributableUtil.getType()) {
            for (AttributeTO vattrTO : attributableTO.getVirtualAttributes()) {
                AbstractVirSchema uVirSchema = getVirtualSchema(vattrTO.getSchema(),
                        attributableUtil.virtualSchemaClass());

                if (uVirSchema != null) {
                    AbstractVirAttr vattr = attributableUtil.newVirtualAttribute();
                    vattr.setVirtualSchema(uVirSchema);
                    vattr.setOwner(attributable);
                    attributable.addVirtualAttribute(vattr);
                }
            }
        }

        fillVirtual(attributable, attributableTO.getVirtualAttributes(), attributableUtil);

        // 4. resources
        ExternalResource resource;
        for (String resourceName : attributableTO.getResources()) {
            resource = getResource(resourceName);

            if (resource != null) {
                attributable.addResource(resource);
            }
        }
       
        SyncopeClientException requiredValuesMissing = checkMandatory(attributableUtil, attributable);
        if (!requiredValuesMissing.isEmpty()) {
            compositeErrorException.addException(requiredValuesMissing);
        }

        // Throw composite exception if there is at least one element set
        // in the composing exceptions
        if (compositeErrorException.hasExceptions()) {
            throw compositeErrorException;
        }
    }

    protected void fillTO(final AbstractAttributableTO abstractAttributableTO,
            final Collection<? extends AbstractAttr> attributes,
            final Collection<? extends AbstractDerAttr> derivedAttributes,
            final Collection<? extends AbstractVirAttr> virtualAttributes, final Collection<ExternalResource> resources) {

        AttributeTO attributeTO;
        for (AbstractAttr attribute : attributes) {
            attributeTO = new AttributeTO();
            attributeTO.setSchema(attribute.getSchema().getName());
            attributeTO.setValues(attribute.getValuesAsStrings());
            attributeTO.setReadonly(attribute.getSchema().isReadonly());

            abstractAttributableTO.addAttribute(attributeTO);
        }

        for (AbstractDerAttr derivedAttribute : derivedAttributes) {
            attributeTO = new AttributeTO();
            attributeTO.setSchema(derivedAttribute.getDerivedSchema().getName());
            attributeTO.addValue(derivedAttribute.getValue(attributes));
            attributeTO.setReadonly(true);

            abstractAttributableTO.addDerivedAttribute(attributeTO);
        }

        for (AbstractVirAttr virtualAttribute : virtualAttributes) {
            attributeTO = new AttributeTO();
            attributeTO.setSchema(virtualAttribute.getVirtualSchema().getName());
            attributeTO.setValues(virtualAttribute.getValues());
            attributeTO.setReadonly(false);

            abstractAttributableTO.addVirtualAttribute(attributeTO);
        }

        for (ExternalResource resource : resources) {
            abstractAttributableTO.addResource(resource.getName());
        }
    }
}
TOP

Related Classes of org.apache.syncope.core.rest.data.AbstractAttributableDataBinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.