de.fiz.ddb.aas.auxiliaryoperations.ThreadOrganisationCreate.java Source code

Java tutorial

Introduction

Here is the source code for de.fiz.ddb.aas.auxiliaryoperations.ThreadOrganisationCreate.java

Source

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.fiz.ddb.aas.auxiliaryoperations;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;

import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.InitialLdapContext;

import org.apache.commons.lang.StringUtils;

import de.fiz.ddb.aas.administration.AasPrincipal;
import de.fiz.ddb.aas.administration.ConstEnumOrgStatus;
import de.fiz.ddb.aas.administration.Constants;
import de.fiz.ddb.aas.administration.Organisation;
import de.fiz.ddb.aas.authentication.Action;
import de.fiz.ddb.aas.authorization.PrivilegeEnum;
import de.fiz.ddb.aas.authorization.Scope;
import de.fiz.ddb.aas.auxiliaryobjects.Email;
import de.fiz.ddb.aas.auxiliaryobjects.OIDs;
import de.fiz.ddb.aas.exceptions.AASUnauthorizedException;
import de.fiz.ddb.aas.security.Authorizable;
import de.fiz.ddb.aas.security.PreAuthorize;
import de.fiz.ddb.aas.utils.JsonPropertiesSerializer;
import de.fiz.ddb.aas.utils.LDAPEngineUtilityOrganisation;
import de.fiz.ddb.aas.utils.PropertiesSerializer;
import de.fiz.ddb.geocoding.GeoAdresse;
import de.fiz.ddb.geocoding.GeoLocationType;
import de.fiz.ddb.geocoding.GeoRequest;
import de.fiz.ddb.geocoding.GeoRequestStatus;
import de.fiz.ddb.ldap.connector.LDAPConnector;

/**
 * 
 * @author bk
 */
public class ThreadOrganisationCreate extends LDAPEngineUtilityOrganisation
        implements Callable<Organisation>, Authorizable {

    private Boolean _addToLicensedOrgs = null;

    private Boolean _ingestingOperation = null;

    private CountDownLatch _ready = null;

    private Organisation _orgObj = null;

    private AasPrincipal _performer = null;

    private OIDs _orgParentOIDs = null;

    private Future<GeoAdresse> _submit = null;

    private PropertiesSerializer serializer = new JsonPropertiesSerializer();

    // ***************************************************************************
    private ThreadOrganisationCreate(AasPrincipal pPerformer) {
        this._performer = pPerformer;
        if (pPerformer == null) {
            throw new IllegalArgumentException("The contractor is unknown: Performer == null");
        }
    }

    public ThreadOrganisationCreate(Organisation pOrgObj, AasPrincipal pPerformer)
            throws IllegalArgumentException, ExecutionException {
        this(pPerformer);

        // check mandatory fields
        if ((pOrgObj == null) || (pOrgObj.getOIDs() == null) || (pOrgObj.getId() == null)) {
            throw new IllegalArgumentException(
                    "failed for add organization: the organization is unknown: Organisation = " + pOrgObj);
        }
        if ((pOrgObj.getDisplayName() == null) || (pOrgObj.getDisplayName().length() == 0)) {
            throw new IllegalArgumentException(
                    "Failed for add organization: Mandatory field displayName may not be empty or null");
        }
        // check fundingAgency:
        if ((pOrgObj.getOrgParent() != null) && (pOrgObj.getOrgParent().trim().length() > 0)
                && (pOrgObj.getFundingAgency() != null) && (pOrgObj.getFundingAgency().trim().length() > 0)) {
            throw new IllegalArgumentException(
                    "The atrribut 'FundingAgency' for sub-organizations is not permitted");
        }
        // check eMail
        if (StringUtils.isNotBlank(pOrgObj.getEmail())) {
            new Email(pOrgObj.getEmail());
        }

        this._orgObj = pOrgObj;
    }

    /**
     * 
     * @param pReadyLatch
     *            : CountDownLatch,
     * @param pOrganisation
     * @param pPerformer
     * @throws IllegalArgumentException
     */
    public ThreadOrganisationCreate(CountDownLatch pReadyLatch, Organisation pOrganisation, AasPrincipal pPerformer)
            throws AssertionError, IllegalArgumentException, ExecutionException {
        this(pOrganisation, pPerformer);
        this._ready = pReadyLatch;
    }

    // ***************************************************************************
    /**
     * 
     * @return Organisation
     * @throws AASUnauthorizedException
     * @throws NamingException
     * @throws IOException
     * @throws CloneNotSupportedException
     * @throws IllegalAccessException
     * @throws Exception
     */
    @PreAuthorize(privileges = { PrivilegeEnum.DEFAULT }, scope = Scope.ORGANIZATION)
    public Organisation call() throws AASUnauthorizedException, ExecutionException, NameAlreadyBoundException {
        Organisation vResult = this._orgObj;
        // -- Fr eine Prfung, ob bereits existent:
        //    but only if that is not a copy in the export directory
        if (!this.isAddToLicensedOrgs() && organizationExists(this._orgObj.getOIDs().getOrgName())) {
            throw new NameAlreadyBoundException(
                    "Error: A organization with ID: '" + this._orgObj.getOIDs().getOrgName() + "' already exists!");
        }

        try {
            // -- Ist ein Parent bekannt, muss auch die komplette RDN aufgebaut
            // werden:
            if (!this.isAddToLicensedOrgs()) {
                if ((this._orgObj.getOrgRDN() == null) && (this._orgObj.getOrgParent() != null)
                        && (!this._orgObj.getOrgParent().isEmpty())) {
                    ThreadOIDsRDNComplement threadOIDsRDNComplement = new ThreadOIDsRDNComplement(
                            new OIDs(this._orgObj.getOrgParent(), false), getPerformer());
                    this._orgParentOIDs = threadOIDsRDNComplement.call();

                    if (this._orgParentOIDs != null) {
                        LOG.info("OrgParent = " + this._orgParentOIDs);
                        this._orgObj.setOrgRDN(new StringBuilder(this._orgObj.getId()).append(",")
                                .append(this._orgParentOIDs.getOrgRDN()).toString());
                    } else {
                        throw new IllegalArgumentException("Error: A parent organization with ID: '"
                                + this._orgObj.getOrgParent() + "' not found!");
                    }
                } else {
                    this._orgObj.setOrgRDN(this._orgObj.getId());
                }
            }

            // -- Ask about Geo coordinates but only if that is not a copy in the export directory or Licensed directory
            if (!this.isAddToLicensedOrgs() && !this.isIngestingOperation()) {
                boolean vQueryRequestForGeocoding = ((Math.abs(this._orgObj.getAddress().getLatitude()) <= 1e-6)
                        || (Math.abs(this._orgObj.getAddress().getLongitude()) <= 1e-6));
                if (vQueryRequestForGeocoding) {
                    try {
                        GeoRequest vGeoRequest = new GeoRequest(new GeoAdresse(this._orgObj.getAddress()),
                                LDAPConnector.getSingletonInstance().getHttpProxy());
                        vGeoRequest.setAskForLocation(true);
                        // -- should be set by Properties... change it!
                        vGeoRequest.addAcceptLocationType(GeoLocationType.ROOFTOP,
                                GeoLocationType.RANGE_INTERPOLATED, GeoLocationType.GEOMETRIC_CENTER,
                                GeoLocationType.APPROXIMATE);
                        _submit = LDAPConnector.getSingletonInstance().getExecutorServiceOne().submit(vGeoRequest);
                    } catch (IllegalAccessException ex) {
                        LOG.log(Level.SEVERE, "Error bei Adresse: " + this._orgObj.getAddress(), ex);
                    }
                }
            }

            this.createOrg();
            vResult = this._orgObj;

            // -- The performer gets automatically a member of this organization
            //  X  but only if that is not a copy in the export or licensed directory
            if ((!this.isAddToLicensedOrgs()) && (this._performer != null)) {
                //if ((this._performer != null)) {
                Map<OIDs, Set<PrivilegeEnum>> privileges = new HashMap<OIDs, Set<PrivilegeEnum>>();
                privileges.put(this._orgObj.getOIDs(), new HashSet<PrivilegeEnum>());
                privileges.get(this._orgObj.getOIDs()).add(PrivilegeEnum.ADMIN_ORG);
                ThreadUserOrgPrivilegsOperations threadUserOrgPrivilegsOperations = new ThreadUserOrgPrivilegsOperations(
                        _performer.getUid(), privileges, Action.ADD, this._performer);
                threadUserOrgPrivilegsOperations.call();
            }

        } catch (ExecutionException ex) {
            LOG.log(Level.WARNING, ex.getMessage(), ex.getCause());
            throw ex;
        } catch (NameNotFoundException ex) {
            LOG.log(Level.SEVERE, ex.getMessage());
            throw new ExecutionException(ex.getMessage(), ex);
        } catch (AssertionError ex) {
            LOG.log(Level.SEVERE, ex.getMessage());
            throw new ExecutionException(ex.getMessage(), ex);
        } finally {
            if (this._ready != null) {
                this._ready.countDown();
            }
            if ((_submit != null) && (!_submit.isDone()) && (!_submit.isCancelled())) {
                _submit.cancel(true);
            }
        }
        return vResult;
    }

    // ***************************************************************************
    private void createOrg() throws ExecutionException, IllegalArgumentException, AASUnauthorizedException {
        InitialLdapContext vCtx = null;

        Attributes vOrgAttributes = new BasicAttributes(true);

        BasicAttribute objectClass = new BasicAttribute("objectclass", "top");
        objectClass.add(Constants.ldap_ddbOrg_ObjectClass);
        objectClass.add("organization");

        vOrgAttributes.put(objectClass);

        // ---All this occurs only if that is not a copy in the export directory
        if (!this.isAddToLicensedOrgs()) {

            // -- When creating the status always set on Pending:
            if (!this.isIngestingOperation()) {
                this._orgObj.setStatus(ConstEnumOrgStatus.pending);
                long vTimeStamp = new Date().getTime();
                this._orgObj.setModified(vTimeStamp);
                this._orgObj.setCreated(vTimeStamp);
            }

            if (this._performer != null) {
                this._orgObj.setModifiedBy(this._performer.getUid());
                this._orgObj.setCreatedBy(this._performer.getUid());
            }

            // -- Is null, if it was isIngestingOperation or isAddToLicensedOrgs 
            //    and therefore does not need to be additionally checked
            if (_submit != null) {
                GeoAdresse vGeoAdresse;
                try {
                    vGeoAdresse = _submit.get(50, TimeUnit.SECONDS);
                    if (vGeoAdresse.getRequestStatus() == GeoRequestStatus.OK) {
                        this._orgObj.getAddress().setLatitude(vGeoAdresse.getLatitude());
                        this._orgObj.getAddress().setLongitude(vGeoAdresse.getLongitude());
                        this._orgObj.getAddress().setLocationDisplayName(vGeoAdresse.getLocationDisplayName());
                    } else {
                        LOG.log(Level.WARNING, "GeoRequestStatus: {0}, (organization id: {1})",
                                new Object[] { vGeoAdresse.getRequestStatus(), this._orgObj.getOIDs() });
                    }
                } catch (InterruptedException ex) {
                    LOG.log(Level.WARNING,
                            "Geocoding request exeption for organization id: " + this._orgObj.getOIDs(), ex);
                } catch (TimeoutException ex) {
                    LOG.log(Level.WARNING,
                            "Geocoding request exeption for organization id: " + this._orgObj.getOIDs(), ex);
                }
            }
        }

        // -- Conversion of parameters to LDAP attributes:
        this.convertOrganizationToLdapOrgAttrsForCreate(this._orgObj, vOrgAttributes, getPerformer());

        StringBuilder vEntryDN = (this.isAddToLicensedOrgs() ? this.getLicensedOrgsDN(this._orgObj.getOIDs())
                : this.getOrgDN(this._orgObj.getOIDs()));

        try {
            // put arbitrary (Org) Properties as JSON-String into LDAP.
            if (this._orgObj.getProperties() != null && !this._orgObj.getProperties().isEmpty()) {
                vOrgAttributes.put(new BasicAttribute(Constants.ldap_ddbOrg_Properties,
                        serializer.serialize(this._orgObj.getProperties())));
            }

            // finally bind the entry
            vCtx = LDAPConnector.getSingletonInstance().takeCtx();
            ((InitialDirContext) vCtx).bind(vEntryDN.toString(), vCtx, vOrgAttributes);

            // -- Add default privilege(s) so we can assign performer
            //    but only if that is not a copy in the export directory
            if (!this.isAddToLicensedOrgs()) {
                this._orgObj.getPrivilegesSet().add(PrivilegeEnum.ADMIN_ORG);

                // create org-privileges
                for (PrivilegeEnum p : this._orgObj.getPrivilegesSet()) {
                    ThreadSinglePrivilegeCreate threadSinglePrivilegeCreate = new ThreadSinglePrivilegeCreate(p,
                            this._orgObj, this._performer);
                    threadSinglePrivilegeCreate.call();
                }
                // -- Logging:
                LOG.log(Level.INFO, "One organization with DN: ''{0}'' was created.", new Object[] { vEntryDN });
            } else {
                // -- Logging:
                LOG.log(Level.INFO, "One organization with DN: ''{0}'' was copied to the export directory.",
                        new Object[] { vEntryDN });
            }
        } catch (AssertionError ex) {
            LOG.log(Level.SEVERE, null, ex);
            throw new IllegalArgumentException(ex.getMessage(), ex.getCause());
        } catch (IllegalAccessException ex) {
            LOG.log(Level.SEVERE, null, ex);
            throw new ExecutionException(ex.getMessage(), ex.getCause());
        } catch (NamingException ex) {
            // LDAP: error code 68 - ENTRY_ALREADY_EXISTS: failed for Add
            // Request
            try {
                if (vCtx != null) {
                    vCtx.close();
                    vCtx = null;
                }
            } catch (NamingException ex1) {
                LOG.log(Level.SEVERE, null, ex1);
            }
            try {
                vCtx = LDAPConnector.getSingletonInstance().getDirContext();
            } catch (NamingException ex1) {
                LOG.log(Level.SEVERE, null, ex1);
            } catch (IllegalAccessException ex1) {
                LOG.log(Level.SEVERE, null, ex1);
            }
            throw new IllegalArgumentException(ex.getMessage());
        } finally {
            if (vCtx != null) {
                try {
                    LDAPConnector.getSingletonInstance().putCtx(vCtx);
                } catch (Exception ex) {
                    LOG.log(Level.SEVERE, "Exception", ex);
                }
            }
        }

    }

    public AasPrincipal getPerformer() {
        return _performer;
    }

    public String getResourceId() {
        return null;
    }

    // ***************************************************************************
    /**
     * @return the _copyingOfOrgs
     */
    public boolean isAddToLicensedOrgs() {
        return (_addToLicensedOrgs != null ? _addToLicensedOrgs.booleanValue() : false);
    }

    /**
     * @param pAddToLicensedOrgs the _addToLicensedOrgs to set
     */
    public void setAddToLicensedOrgs(boolean pAddToLicensedOrgs) {
        this._addToLicensedOrgs = pAddToLicensedOrgs;
    }

    // ***************************************************************************
    /**
     * @return the _ingestingOperation
     */
    public boolean isIngestingOperation() {
        return (_ingestingOperation != null ? _ingestingOperation.booleanValue() : false);
    }

    /**
     * @param pIngestingOperation the _ingestingOperation to set
     */
    public void setIngestingOperation(boolean pIngestingOperation) {
        this._ingestingOperation = pIngestingOperation;
    }

}