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

Java tutorial

Introduction

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

Source

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

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.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;

import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.directory.AttributeModificationException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
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.authorization.PrivilegeEnum;
import de.fiz.ddb.aas.authorization.Scope;
import de.fiz.ddb.aas.auxiliaryobjects.Email;
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.LDAPEngineUtilityOrganisation;
import de.fiz.ddb.geocoding.GeoAdresse;
import de.fiz.ddb.geocoding.GeoLocationDisplayNameRequest;
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 ThreadOrganisationUpdate extends LDAPEngineUtilityOrganisation
        implements Callable<Organisation>, Authorizable {

    private Boolean _updatingOfLicensedOrgs = null;

    private Boolean _changeOfStatus = null;

    private Organisation _organisation = null;

    private AasPrincipal _performer = null;

    private boolean _privilegesUpdate = false;

    private Organisation _oldOrganisation = null;

    private Future<GeoAdresse> _submit = null;

    private Future<String> _submitGeoLocDisplayName = null;

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

    public ThreadOrganisationUpdate(Organisation pOrganisation, boolean pPrivilegesUpdate, AasPrincipal performer)
            throws IllegalArgumentException, ExecutionException {
        this(performer);
        //check mandatory fields
        if ((pOrganisation == null) || (pOrganisation.getOIDs() == null)) {
            throw new IllegalArgumentException("Illegal argument: Organization = " + pOrganisation);
        }
        if ((pOrganisation.getDisplayName() == null) || (pOrganisation.getDisplayName().length() == 0)) {
            throw new IllegalArgumentException(
                    "Failed for add organization: Mandatory field displayName may not be empty or null");
        }
        // check fundingAgency:
        if ((pOrganisation.getOrgParent() != null) && (pOrganisation.getOrgParent().trim().length() > 0)
                && (pOrganisation.getFundingAgency() != null)
                && (pOrganisation.getFundingAgency().trim().length() > 0)) {
            throw new IllegalArgumentException(
                    "The atrribut 'FundingAgency' for sub-organizations is not permitted");
        }
        //check eMail
        if (StringUtils.isNotBlank(pOrganisation.getEmail())) {
            new Email(pOrganisation.getEmail());
        }

        this._organisation = pOrganisation;
        this._privilegesUpdate = pPrivilegesUpdate;

    }

    public ThreadOrganisationUpdate(CountDownLatch pReadyLatch, Organisation pOrganisation,
            boolean pPrivilegesUpdate, AasPrincipal performer)
            throws AssertionError, IllegalArgumentException, ExecutionException {
        this(pOrganisation, pPrivilegesUpdate, performer);
    }

    // ***************************************************************************
    @PreAuthorize(privileges = { PrivilegeEnum.ADMIN_ORG,
            PrivilegeEnum.ADMIN }, scope = Scope.ORGANIZATION, cacheUpdate = true)
    public Organisation call() throws NameNotFoundException, AASUnauthorizedException,
            AttributeModificationException, ExecutionException {
        try {

            LOG.log(Level.INFO, "Update an organization with ID: ''{0}''", this._organisation.getOIDs());

            ThreadOrganisationRead threadOrganisationRead = new ThreadOrganisationRead(this._organisation.getOIDs(),
                    getPerformer());
            threadOrganisationRead.setLicensedOrgs(isUpdatingOfLicensedOrgs());
            // -- if not found, throw NameNotFoundException:
            _oldOrganisation = threadOrganisationRead.call();

            if (!isChangeOfStatus()) {

                if (!_oldOrganisation.getStatus().equals(_organisation.getStatus())) {
                    LOG.log(Level.WARNING,
                            "It is only an explicit change of status possible! The old value '"
                                    + _oldOrganisation.getStatus() + "' is put back (The new value was: '"
                                    + _organisation.getStatus() + "').");
                    this._organisation.setStatus(_oldOrganisation.getStatus());
                }

                if (_oldOrganisation.getAddress() != null) {

                    // -- wesentliche Adressdaten wurden gendert:
                    boolean vAddressHasBeenChanged = (!_oldOrganisation.getAddress()
                            .equalsWithoutGeocoding(this._organisation.getAddress()));

                    // -- Abfrageforderung:
                    boolean vQueryRequestForGeocoding = ((Math
                            .abs(this._organisation.getAddress().getLatitude()) <= 1e-6)
                            || (Math.abs(this._organisation.getAddress().getLongitude()) <= 1e-6));

                    // -- Die Geokoordinaten sollten - dem Input entsprechend, gendert werden:
                    boolean vGeocodingShouldBeChanged = (Math.abs(this._organisation.getAddress().getLatitude()
                            - _oldOrganisation.getAddress().getLatitude()) >= 1e-6)
                            || (Math.abs(this._organisation.getAddress().getLongitude()
                                    - _oldOrganisation.getAddress().getLongitude()) >= 1e-6);

                    LOG.log(Level.INFO,
                            "AddressHasBeenChanged = {0}, QueryRequestForGeocoding = {1}, GeocodingShouldBeChanged = {2}",
                            new Object[] { vAddressHasBeenChanged, vQueryRequestForGeocoding,
                                    vGeocodingShouldBeChanged });

                    if ((vQueryRequestForGeocoding) || (vAddressHasBeenChanged && !vGeocodingShouldBeChanged)) {
                        try {
                            GeoRequest vGeoRequest = new GeoRequest(new GeoAdresse(this._organisation.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._organisation.getAddress(), ex);
                        }
                    } else if (vGeocodingShouldBeChanged) {
                        try {
                            GeoLocationDisplayNameRequest vGeoLocDisplayNameRequest = new GeoLocationDisplayNameRequest(
                                    this._organisation.getAddress().getLatitude(),
                                    this._organisation.getAddress().getLongitude(),
                                    LDAPConnector.getSingletonInstance().getHttpProxy() //Proxy.NO_PROXY
                            );
                            _submitGeoLocDisplayName = LDAPConnector.getSingletonInstance().getExecutorServiceOne()
                                    .submit(vGeoLocDisplayNameRequest);
                            //LOG.info("Gestartet: '" + vGeoLocDisplayNameRequest.getUrlBase() + "...'");
                        } catch (IllegalAccessException ex) {
                            LOG.log(Level.WARNING, this._organisation.getAddress()
                                    + " without location display name: " + ex.getMessage());
                        }

                    }
                }
            }
            this.updateOrg();
        } catch (AASUnauthorizedException ex) {
            LOG.log(Level.SEVERE, ex.getMessage(), ex);
            throw ex;
        } finally {
            try {
                if ((_submitGeoLocDisplayName != null) && (!_submitGeoLocDisplayName.isDone())
                        && (!_submitGeoLocDisplayName.isCancelled())) {
                    _submitGeoLocDisplayName.cancel(true);
                    _submitGeoLocDisplayName = null;
                }
            } catch (Exception ex) {
            }
            try {
                if ((_submit != null) && (!_submit.isDone()) && (!_submit.isCancelled())) {
                    _submit.cancel(true);
                    _submit = null;
                }
            } catch (Exception ex) {
            }

        }
        return this._organisation;
    }

    // ***************************************************************************
    private void updateOrg() throws NameNotFoundException, AASUnauthorizedException, AttributeModificationException,
            ExecutionException {
        boolean vChange = false;
        InitialLdapContext vCtx = null;
        try {

            if (this._oldOrganisation == null) {
                LOG.log(Level.WARNING, "No such organization ''{0}'' with oid: ''{1}''.",
                        new Object[] { this._organisation.getDisplayName(), this._organisation.getOIDs() });
                throw new NameNotFoundException("No such organization '" + this._organisation.getDisplayName()
                        + "' with oid: '" + this._organisation.getOIDs() + "'.");
            }

            GeoAdresse vGeoAdresse;
            String vLocalDispalyName = null;
            if (_submit != null) { // hier ist "GeoLocationDisplayName" breits ausgefhrt
                try {
                    vGeoAdresse = _submit.get(10, TimeUnit.SECONDS);
                    if (vGeoAdresse.getRequestStatus() == GeoRequestStatus.OK) {
                        this._organisation.getAddress().setLatitude(vGeoAdresse.getLatitude());
                        this._organisation.getAddress().setLongitude(vGeoAdresse.getLongitude());
                        this._organisation.getAddress()
                                .setLocationDisplayName(vGeoAdresse.getLocationDisplayName());
                    } else {
                        LOG.log(Level.WARNING, "GeoRequestStatus: {0}, (organization id: {1})",
                                new Object[] { vGeoAdresse.getRequestStatus(), this._organisation.getOIDs() });
                    }
                } catch (InterruptedException ex) {
                    LOG.log(Level.WARNING,
                            "Geocoding request exeption for organization id: " + this._organisation.getOIDs(), ex);
                } catch (TimeoutException ex) {
                    LOG.log(Level.WARNING,
                            "Geocoding request exeption for organization id: " + this._organisation.getOIDs(), ex);
                }
            } else if (_submitGeoLocDisplayName != null) {
                try {
                    vLocalDispalyName = _submitGeoLocDisplayName.get(5, TimeUnit.SECONDS);
                    this._organisation.getAddress().setLocationDisplayName(vLocalDispalyName);
                    //LOG.info("LocalDisplayName='" + vLocalDispalyName + "'" + vLocalDispalyName + "'");
                } catch (InterruptedException ex) {
                    LOG.log(Level.WARNING,
                            this._organisation.getOIDs() + " without location display name: " + ex.getMessage());
                } catch (ExecutionException ex) {
                    LOG.log(Level.WARNING,
                            this._organisation.getOIDs() + " without location display name: " + ex.getMessage());
                } catch (TimeoutException ex) {
                    LOG.log(Level.WARNING,
                            this._organisation.getOIDs() + " without location display name: " + ex.getMessage());
                }

            }

            LOG.info("newOIDs: '" + this._organisation.getOIDs() + "'");
            LOG.info("oldOIDs: '" + this._oldOrganisation.getOIDs() + "'");

            if (this._organisation.getOrgRDN() == null) {
                // -- Ansonsten eine nicht gesetzte RDN kann zum Knall fhren...
                this._organisation.setOrgRDN(this._oldOrganisation.getOrgRDN());
            } else if (!this._organisation.getOrgRDN().equals(this._oldOrganisation.getOrgRDN())) {
                // -- Hier ist etwas faul...
                LOG.log(Level.WARNING,
                        "The organization ''{0}'' has RDN: ''{1}'', but there exist an organization ''{0}'' with RDN: ''{2}''!",
                        new Object[] { this._organisation.getId(), this._organisation.getOrgRDN(),
                                this._oldOrganisation.getOrgRDN() });
                throw new NameNotFoundException("No such organization '" + this._organisation.getDisplayName()
                        + "' with oid: '" + this._organisation.getOIDs() + "'.");
            }

            if (this.isPrivilegesUpdate()) {
                Set<PrivilegeEnum> removePrivileges = this.privilegeDiff(this._organisation.getPrivilegesSet(),
                        this._oldOrganisation.getPrivilegesSet());
                Set<PrivilegeEnum> addPrivileges = this.privilegeDiff(this._oldOrganisation.getPrivilegesSet(),
                        this._organisation.getPrivilegesSet());
                if (!removePrivileges.isEmpty() || !addPrivileges.isEmpty()) {
                    vChange = true;
                    for (PrivilegeEnum p : removePrivileges) {
                        ThreadSinglePrivilegeDelete threadSinglePrivilegeDelete = new ThreadSinglePrivilegeDelete(p,
                                this._organisation, this._performer);
                        threadSinglePrivilegeDelete.call();
                    }
                    for (PrivilegeEnum p : addPrivileges) {
                        ThreadSinglePrivilegeCreate threadSinglePrivilegeCreate = new ThreadSinglePrivilegeCreate(p,
                                this._organisation, this._performer);
                        threadSinglePrivilegeCreate.call();
                    }
                }
            }

            Attributes orgAttributes = new BasicAttributes(true);
            Attributes orgRemoveAttributes = new BasicAttributes(true);

            if (vChange = this.convertOrganizationToLdapOrgAttrsForUpdate(this._organisation, this._oldOrganisation,
                    orgAttributes, orgRemoveAttributes, getPerformer())) {

                // -- If any changes, the status is set to 'revised'
                //    but not if status will be explicitly changed or by a update operation on Licenses directory
                if (!isChangeOfStatus() && !isUpdatingOfLicensedOrgs()) {
                    if ((ConstEnumOrgStatus.approved.equals(this._organisation.getStatus()))) {
                        // -- ...then go retrospectively into "revised" status:
                        this._organisation.setStatus(ConstEnumOrgStatus.revised);

                        orgAttributes.put(Constants.ldap_ddbOrg_Status,
                                String.valueOf(this._organisation.getStatus().name()));
                    }
                }
            }
            // ---------------------------------------------------------------------
            if (vChange) {

                // -- Save changes to the corresponding directory:
                StringBuilder vOrgEntryDN = (isUpdatingOfLicensedOrgs()
                        ? this.getLicensedOrgsDN(this._organisation.getOIDs())
                        : this.getOrgDN(this._organisation.getOIDs()));
                LOG.log(Level.INFO, "DEBUG-Info: destination OrgEntryDN = '" + vOrgEntryDN + "'");

                vCtx = LDAPConnector.getSingletonInstance().takeCtx();
                if (orgRemoveAttributes.size() > 0) {
                    vCtx.modifyAttributes(vOrgEntryDN.toString(), DirContext.REMOVE_ATTRIBUTE, orgRemoveAttributes);
                }
                vCtx.modifyAttributes(vOrgEntryDN.toString(), DirContext.REPLACE_ATTRIBUTE, orgAttributes);
            } else {
                throw new AttributeModificationException(
                        "Not modified: oid = '" + this._organisation.getOIDs() + "'");
            }

        } catch (RejectedExecutionException ex) {
            LOG.log(Level.SEVERE, "RejectedExecutionException\n{0}", ex);
            throw new ExecutionException(ex.getMessage(), ex.getCause());
        } catch (IllegalAccessException ex) {
            LOG.log(Level.SEVERE, "Connection-Error\n{0}", ex);
            throw new ExecutionException(ex.getMessage(), ex.getCause());
        } catch (NameNotFoundException ex) {
            LOG.log(Level.WARNING, null, ex);
            throw ex;
        } catch (AttributeModificationException ex) {
            LOG.log(Level.WARNING, "AttributeModificationException\n{0}", ex.getMessage());
            // !!!!AttributeModificationException extends NamingExeption:
            //throw ex;
            throw new AttributeModificationException(ex.getMessage());
        } catch (NamingException ne) {
            LOG.log(Level.SEVERE, "NamingException\n{0}", ne);
            throw new ExecutionException(ne.getMessage(), ne.getCause());
        } finally {
            if (vCtx != null) {
                try {
                    LDAPConnector.getSingletonInstance().putCtx(vCtx);
                } catch (Exception ex) {
                    LOG.log(Level.SEVERE, "Exception", ex);
                }
            }
        }

    }

    // ***************************************************************************
    /**
     * @return the _privilegesUpdate
     */
    public boolean isPrivilegesUpdate() {
        return _privilegesUpdate;
    }

    /**
     * @param privilegesUpdate the _privilegesUpdate to set
     */
    public void setPrivilegesUpdate(boolean privilegesUpdate) {
        this._privilegesUpdate = privilegesUpdate;
    }

    public AasPrincipal getPerformer() {
        return _performer;
    }

    public String getResourceId() {
        if (_organisation != null) {
            return _organisation.getId();
        }
        return null;
    }

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

    /**
     * @param _updatingOfLicensedOrgs the _updatingOfLicensedOrgs to set
     */
    public void setUpdatingOfLicensedOrgs(boolean _updatingOfLicensedOrgs) {
        this._updatingOfLicensedOrgs = _updatingOfLicensedOrgs;
    }

    // ***************************************************************************

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

    /**
     * @param _changeOfStatus the _changeOfStatus to set
     */
    public void setChangeOfStatus(boolean _changeOfStatus) {
        this._changeOfStatus = _changeOfStatus;
    }

}