Example usage for java.text DateFormat getDateTimeInstance

List of usage examples for java.text DateFormat getDateTimeInstance

Introduction

In this page you can find the example usage for java.text DateFormat getDateTimeInstance.

Prototype

public static final DateFormat getDateTimeInstance() 

Source Link

Document

Gets the date/time formatter with the default formatting style for the default java.util.Locale.Category#FORMAT FORMAT locale.

Usage

From source file:op.care.values.PnlValues.java

private JPanel getMenu(final ResValue resValue) {

    final ResValueTypes vtype = resValue.getType();

    JPanel pnlMenu = new JPanel(new VerticalLayout());

    boolean doesNotBelongToResInfos = ResInfoTools.getInfosFor(resValue).isEmpty();

    if (doesNotBelongToResInfos && OPDE.getAppInfo().isAllowedTo(InternalClassACL.UPDATE, internalClassID)) {
        /***/*from w  ww  .  j  a  va2 s.  c o  m*/
         *      _____    _ _ _
         *     | ____|__| (_) |_
         *     |  _| / _` | | __|
         *     | |__| (_| | | |_
         *     |_____\__,_|_|\__|
         *
         */
        final JButton btnEdit = GUITools.createHyperlinkButton("nursingrecords.vitalparameters.btnEdit.tooltip",
                SYSConst.icon22edit3, null);
        btnEdit.setAlignmentX(Component.RIGHT_ALIGNMENT);
        btnEdit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                new DlgValue(resValue.clone(), DlgValue.MODE_EDIT, new Closure() {
                    @Override
                    public void execute(Object o) {
                        if (o != null) {

                            EntityManager em = OPDE.createEM();
                            try {

                                em.getTransaction().begin();
                                em.lock(em.merge(resident), LockModeType.OPTIMISTIC);
                                final ResValue newValue = em.merge((ResValue) o);
                                ResValue oldValue = em.merge(resValue);

                                em.lock(oldValue, LockModeType.OPTIMISTIC);
                                newValue.setReplacementFor(oldValue);

                                for (SYSVAL2FILE oldAssignment : oldValue.getAttachedFilesConnections()) {
                                    em.remove(oldAssignment);
                                }
                                oldValue.getAttachedFilesConnections().clear();
                                for (SYSVAL2PROCESS oldAssignment : oldValue.getAttachedProcessConnections()) {
                                    em.remove(oldAssignment);
                                }
                                oldValue.getAttachedProcessConnections().clear();

                                oldValue.setEditedBy(em.merge(OPDE.getLogin().getUser()));
                                oldValue.setEditDate(new Date());
                                oldValue.setReplacedBy(newValue);

                                em.getTransaction().commit();

                                DateTime dt = new DateTime(newValue.getPit());
                                final String keyType = vtype.getID() + ".xtypes";
                                final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear())
                                        + ".year";

                                synchronized (mapType2Values) {
                                    mapType2Values.get(key).remove(resValue);
                                    mapType2Values.get(key).add(oldValue);
                                    mapType2Values.get(key).add(newValue);
                                    Collections.sort(mapType2Values.get(key));
                                }

                                createCP4Year(vtype, dt.getYear());

                                try {
                                    synchronized (cpMap) {
                                        cpMap.get(keyType).setCollapsed(false);
                                        cpMap.get(key).setCollapsed(false);
                                    }
                                } catch (PropertyVetoException e) {
                                    e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
                                }

                                buildPanel();

                            } catch (OptimisticLockException ole) {
                                OPDE.warn(ole);
                                if (em.getTransaction().isActive()) {
                                    em.getTransaction().rollback();
                                }
                                if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
                                    OPDE.getMainframe().emptyFrame();
                                    OPDE.getMainframe().afterLogin();
                                }
                                OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
                            } catch (Exception e) {
                                if (em.getTransaction().isActive()) {
                                    em.getTransaction().rollback();
                                }
                                OPDE.fatal(e);
                            } finally {
                                em.close();
                            }

                        }
                    }
                });
            }
        });
        btnEdit.setEnabled(!resValue.isObsolete());
        pnlMenu.add(btnEdit);

        /***
         *      ____       _      _
         *     |  _ \  ___| | ___| |_ ___
         *     | | | |/ _ \ |/ _ \ __/ _ \
         *     | |_| |  __/ |  __/ ||  __/
         *     |____/ \___|_|\___|\__\___|
         *
         */
        final JButton btnDelete = GUITools.createHyperlinkButton(
                "nursingrecords.vitalparameters.btnDelete.tooltip", SYSConst.icon22delete, null);
        btnDelete.setAlignmentX(Component.RIGHT_ALIGNMENT);
        btnDelete.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                new DlgYesNo(SYSTools.xx("misc.questions.delete1") + "<br/><i>"
                        + DateFormat.getDateTimeInstance().format(resValue.getPit()) + "</i><br/>"
                        + SYSTools.xx("misc.questions.delete2"), SYSConst.icon48delete, new Closure() {
                            @Override
                            public void execute(Object o) {
                                if (o.equals(JOptionPane.YES_OPTION)) {

                                    EntityManager em = OPDE.createEM();
                                    try {

                                        em.getTransaction().begin();

                                        ResValue myValue = em.merge(resValue);
                                        myValue.setDeletedBy(em.merge(OPDE.getLogin().getUser()));

                                        for (SYSVAL2FILE file : myValue.getAttachedFilesConnections()) {
                                            em.remove(file);
                                        }
                                        myValue.getAttachedFilesConnections().clear();

                                        // Vorgangszuordnungen entfernen
                                        for (SYSVAL2PROCESS connObj : myValue.getAttachedProcessConnections()) {
                                            em.remove(connObj);
                                        }
                                        myValue.getAttachedProcessConnections().clear();
                                        myValue.getAttachedProcesses().clear();
                                        em.getTransaction().commit();

                                        DateTime dt = new DateTime(myValue.getPit());
                                        final String keyType = vtype.getID() + ".xtypes";

                                        final String key = vtype.getID() + ".xtypes."
                                                + Integer.toString(dt.getYear()) + ".year";

                                        synchronized (mapType2Values) {
                                            mapType2Values.get(key).remove(resValue);
                                            mapType2Values.get(key).add(myValue);
                                            Collections.sort(mapType2Values.get(key));
                                        }

                                        createCP4Year(vtype, dt.getYear());

                                        try {
                                            synchronized (cpMap) {
                                                cpMap.get(keyType).setCollapsed(false);
                                                cpMap.get(key).setCollapsed(false);
                                            }
                                        } catch (PropertyVetoException e) {
                                            e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
                                        }

                                        buildPanel();

                                    } catch (OptimisticLockException ole) {
                                        OPDE.warn(ole);
                                        if (em.getTransaction().isActive()) {
                                            em.getTransaction().rollback();
                                        }
                                        if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
                                            OPDE.getMainframe().emptyFrame();
                                            OPDE.getMainframe().afterLogin();
                                        }
                                        OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
                                    } catch (Exception e) {
                                        if (em.getTransaction().isActive()) {
                                            em.getTransaction().rollback();
                                        }
                                        OPDE.fatal(e);
                                    } finally {
                                        em.close();
                                    }

                                }
                            }
                        });
            }
        });
        btnDelete.setEnabled(!resValue.isObsolete());
        pnlMenu.add(btnDelete);

        pnlMenu.add(new JSeparator());
        /***
         *      _     _         _____ _ _
         *     | |__ | |_ _ __ |  ___(_) | ___  ___
         *     | '_ \| __| '_ \| |_  | | |/ _ \/ __|
         *     | |_) | |_| | | |  _| | | |  __/\__ \
         *     |_.__/ \__|_| |_|_|   |_|_|\___||___/
         *
         */

        final JButton btnFiles = GUITools.createHyperlinkButton("misc.btnfiles.tooltip", SYSConst.icon22attach,
                null);
        btnFiles.setAlignmentX(Component.RIGHT_ALIGNMENT);
        btnFiles.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                new DlgFiles(resValue, new Closure() {
                    @Override
                    public void execute(Object o) {
                        EntityManager em = OPDE.createEM();
                        final ResValue myValue = em.find(ResValue.class, resValue.getID());
                        em.close();

                        DateTime dt = new DateTime(myValue.getPit());
                        final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear())
                                + ".year";

                        synchronized (mapType2Values) {
                            mapType2Values.get(key).remove(resValue);
                            mapType2Values.get(key).add(myValue);
                            Collections.sort(mapType2Values.get(key));
                        }

                        buildPanel();
                    }
                });
            }
        });
        btnFiles.setEnabled(!resValue.isObsolete() && OPDE.isFTPworking());
        pnlMenu.add(btnFiles);

        /***
         *      _     _         ____
         *     | |__ | |_ _ __ |  _ \ _ __ ___   ___ ___  ___ ___
         *     | '_ \| __| '_ \| |_) | '__/ _ \ / __/ _ \/ __/ __|
         *     | |_) | |_| | | |  __/| | | (_) | (_|  __/\__ \__ \
         *     |_.__/ \__|_| |_|_|   |_|  \___/ \___\___||___/___/
         *
         */
        final JButton btnProcess = GUITools.createHyperlinkButton("misc.btnprocess.tooltip",
                SYSConst.icon22link, null);
        btnProcess.setAlignmentX(Component.RIGHT_ALIGNMENT);
        btnProcess.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                new DlgProcessAssign(resValue, new Closure() {
                    @Override
                    public void execute(Object o) {
                        if (o == null) {
                            return;
                        }
                        Pair<ArrayList<QProcess>, ArrayList<QProcess>> result = (Pair<ArrayList<QProcess>, ArrayList<QProcess>>) o;

                        ArrayList<QProcess> assigned = result.getFirst();
                        ArrayList<QProcess> unassigned = result.getSecond();

                        EntityManager em = OPDE.createEM();

                        try {
                            em.getTransaction().begin();

                            em.lock(em.merge(resident), LockModeType.OPTIMISTIC);
                            ResValue myValue = em.merge(resValue);
                            em.lock(myValue, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

                            ArrayList<SYSVAL2PROCESS> attached = new ArrayList<SYSVAL2PROCESS>(
                                    resValue.getAttachedProcessConnections());
                            for (SYSVAL2PROCESS linkObject : attached) {
                                if (unassigned.contains(linkObject.getQProcess())) {
                                    linkObject.getQProcess().getAttachedNReportConnections().remove(linkObject);
                                    linkObject.getResValue().getAttachedProcessConnections().remove(linkObject);
                                    em.merge(new PReport(
                                            SYSTools.xx(PReportTools.PREPORT_TEXT_REMOVE_ELEMENT) + ": "
                                                    + myValue.getTitle() + " ID: " + myValue.getID(),
                                            PReportTools.PREPORT_TYPE_REMOVE_ELEMENT,
                                            linkObject.getQProcess()));
                                    em.remove(linkObject);
                                }
                            }
                            attached.clear();

                            for (QProcess qProcess : assigned) {
                                java.util.List<QProcessElement> listElements = qProcess.getElements();
                                if (!listElements.contains(myValue)) {
                                    QProcess myQProcess = em.merge(qProcess);
                                    SYSVAL2PROCESS myLinkObject = em
                                            .merge(new SYSVAL2PROCESS(myQProcess, myValue));
                                    em.merge(new PReport(
                                            SYSTools.xx(PReportTools.PREPORT_TEXT_ASSIGN_ELEMENT) + ": "
                                                    + myValue.getTitle() + " ID: " + myValue.getID(),
                                            PReportTools.PREPORT_TYPE_ASSIGN_ELEMENT, myQProcess));
                                    qProcess.getAttachedResValueConnections().add(myLinkObject);
                                    myValue.getAttachedProcessConnections().add(myLinkObject);
                                }
                            }

                            em.getTransaction().commit();

                            DateTime dt = new DateTime(myValue.getPit());
                            final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear())
                                    + ".year";

                            synchronized (mapType2Values) {
                                mapType2Values.get(key).remove(resValue);
                                mapType2Values.get(key).add(myValue);
                                Collections.sort(mapType2Values.get(key));
                            }

                            createCP4Year(vtype, dt.getYear());

                            buildPanel();
                            //GUITools.flashBackground(contentmap.get(keyMonth), Color.YELLOW, 2);

                        } catch (OptimisticLockException ole) {
                            OPDE.warn(ole);
                            if (em.getTransaction().isActive()) {
                                em.getTransaction().rollback();
                            }
                            if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
                                OPDE.getMainframe().emptyFrame();
                                OPDE.getMainframe().afterLogin();
                            }
                            OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
                        } catch (RollbackException ole) {
                            if (em.getTransaction().isActive()) {
                                em.getTransaction().rollback();
                            }
                            if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
                                OPDE.getMainframe().emptyFrame();
                                OPDE.getMainframe().afterLogin();
                            }
                            OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
                        } catch (Exception e) {
                            if (em.getTransaction().isActive()) {
                                em.getTransaction().rollback();
                            }
                            OPDE.fatal(e);
                        } finally {
                            em.close();
                        }
                    }
                });
            }
        });
        btnProcess.setEnabled(!resValue.isObsolete());
        pnlMenu.add(btnProcess);
    }
    return pnlMenu;
}

From source file:org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.java

/**
 * Synchronizes local groups and users with a {@link UserRegistry} for a particular zone, optionally handling
 * deletions.//from   w  w w  .  j  ava2s  .  c o  m
 * 
 * @param zone
 *            the zone id. This identifier is used to tag all created groups and users, so that in the future we can
 *            tell those that have been deleted from the registry.
 * @param userRegistry
 *            the user registry for the zone.
 * @param forceUpdate
 *            Should the complete set of users and groups be updated / created locally or just those known to have
 *            changed since the last sync? When <code>true</code> then <i>all</i> users and groups are queried from
 *            the user registry and updated locally. When <code>false</code> then each source is only queried for
 *            those users and groups modified since the most recent modification date of all the objects last
 *            queried from that same source.
 * @param isFullSync
 *            Should a complete set of user and group IDs be queried from the user registries in order to determine
 *            deletions? This parameter is independent of <code>force</code> as a separate query is run to process
 *            updates.
 * @param splitTxns
 *            Can the modifications to Alfresco be split across multiple transactions for maximum performance? If
 *            <code>true</code>, users and groups are created/updated in batches for increased performance. If
 *            <code>false</code>, all users and groups are processed in the current transaction. This is required if
 *            calling synchronously (e.g. in response to an authentication event in the same transaction).
 * @param visitedZoneIds
 *            the set of zone ids already processed. These zones have precedence over the current zone when it comes
 *            to group name 'collisions'. If a user or group is queried that already exists locally but is tagged
 *            with one of the zones in this set, then it will be ignored as this zone has lower priority.
 * @param allZoneIds
 *            the set of all zone ids in the authentication chain. Helps us work out whether the zone information
 *            recorded against a user or group is invalid for the current authentication chain and whether the user
 *            or group needs to be 're-zoned'.
 */
private void syncWithPlugin(final String zone, UserRegistry userRegistry, boolean forceUpdate,
        boolean isFullSync, boolean splitTxns, final Set<String> visitedZoneIds, final Set<String> allZoneIds) {
    // Create a prefixed zone ID for use with the authority service
    final String zoneId = AuthorityService.ZONE_AUTH_EXT_PREFIX + zone;

    // Batch Process Names
    final String reservedBatchProcessNames[] = { SyncProcess.GROUP_ANALYSIS.getTitle(zone),
            SyncProcess.USER_CREATION.getTitle(zone), SyncProcess.MISSING_AUTHORITY.getTitle(zone),
            SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone),
            SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone),
            SyncProcess.PERSON_ASSOCIATION.getTitle(zone), SyncProcess.AUTHORITY_DELETION.getTitle(zone) };

    notifySyncDirectoryStart(zone, reservedBatchProcessNames);

    // Ensure that the zoneId exists before multiple threads start using it
    this.transactionService.getRetryingTransactionHelper()
            .doInTransaction(new RetryingTransactionCallback<Void>() {
                @Override
                public Void execute() throws Throwable {
                    authorityService.getOrCreateZone(zoneId);
                    return null;
                }
            }, false, splitTxns);

    // The set of zones we associate with new objects (default plus registry specific)
    final Set<String> zoneSet = getZones(zoneId);

    long lastModifiedMillis = forceUpdate ? -1
            : getMostRecentUpdateTime(ChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId,
                    splitTxns);
    Date lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis);

    if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) {
        if (lastModified == null) {
            ChainingUserRegistrySynchronizer.logger
                    .info("Retrieving all groups from user registry '" + zone + "'");
        } else {
            ChainingUserRegistrySynchronizer.logger.info(
                    "Retrieving groups changed since " + DateFormat.getDateTimeInstance().format(lastModified)
                            + " from user registry '" + zone + "'");
        }
    }

    // First, analyze the group structure. Create maps of authorities to their parents for associations to create
    // and delete. Also deal with 'overlaps' with other zones in the authentication chain.
    final BatchProcessor<NodeDescription> groupProcessor = new BatchProcessor<NodeDescription>(
            SyncProcess.GROUP_ANALYSIS.getTitle(zone), this.transactionService.getRetryingTransactionHelper(),
            userRegistry.getGroups(lastModified), this.workerThreads, 20, this.applicationEventPublisher,
            ChainingUserRegistrySynchronizer.logger, this.loggingInterval);
    class Analyzer extends BaseBatchProcessWorker<NodeDescription> {
        private final Map<String, String> groupsToCreate = new TreeMap<String, String>();
        private final Map<String, Set<String>> personParentAssocsToCreate = newPersonMap();
        private final Map<String, Set<String>> personParentAssocsToDelete = newPersonMap();
        private Map<String, Set<String>> groupParentAssocsToCreate = new TreeMap<String, Set<String>>();
        private final Map<String, Set<String>> groupParentAssocsToDelete = new TreeMap<String, Set<String>>();
        private final Map<String, Set<String>> finalGroupChildAssocs = new TreeMap<String, Set<String>>();
        private List<String> personsProcessed = new LinkedList<String>();
        private Set<String> allZonePersons = Collections.emptySet();
        private Set<String> deletionCandidates;

        private long latestTime;

        public Analyzer(final long latestTime) {
            this.latestTime = latestTime;
        }

        public long getLatestTime() {
            return this.latestTime;
        }

        public Set<String> getDeletionCandidates() {
            return this.deletionCandidates;
        }

        public String getIdentifier(NodeDescription entry) {
            return entry.getSourceId();
        }

        public void process(NodeDescription group) throws Throwable {
            PropertyMap groupProperties = group.getProperties();
            String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME);
            String groupShortName = ChainingUserRegistrySynchronizer.this.authorityService
                    .getShortName(groupName);
            Set<String> groupZones = ChainingUserRegistrySynchronizer.this.authorityService
                    .getAuthorityZones(groupName);

            if (groupZones == null) {
                // The group did not exist at all
                updateGroup(group, false);
            } else {
                // Check whether the group is in any of the authentication chain zones
                Set<String> intersection = new TreeSet<String>(groupZones);
                intersection.retainAll(allZoneIds);
                // Check whether the group is in any of the higher priority authentication chain zones
                Set<String> visited = new TreeSet<String>(intersection);
                visited.retainAll(visitedZoneIds);

                if (groupZones.contains(zoneId)) {
                    // The group already existed in this zone: update the group
                    updateGroup(group, true);
                } else if (!visited.isEmpty()) {
                    // A group that exists in a different zone with higher precedence
                    return;
                } else if (!allowDeletions || intersection.isEmpty()) {
                    // Deletions are disallowed or the group exists, but not in a zone that's in the authentication
                    // chain. May be due to upgrade or zone changes. Let's re-zone them
                    if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.warn("Updating group '" + groupShortName
                                + "'. This group will in future be assumed to originate from user registry '"
                                + zone + "'.");
                    }
                    updateAuthorityZones(groupName, groupZones, zoneSet);

                    // The group now exists in this zone: update the group
                    updateGroup(group, true);
                } else {
                    // The group existed, but in a zone with lower precedence
                    if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.warn("Recreating occluded group '"
                                + groupShortName
                                + "'. This group was previously created through synchronization with a lower priority user registry.");
                    }
                    ChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(groupName);

                    // create the group
                    updateGroup(group, false);
                }
            }

            synchronized (this) {
                // Maintain the last modified date
                Date groupLastModified = group.getLastModified();
                if (groupLastModified != null) {
                    this.latestTime = Math.max(this.latestTime, groupLastModified.getTime());
                }
            }
        }

        // Recursively walks and caches the authorities relating to and from this group so that we can later detect potential cycles
        private Set<String> getContainedAuthorities(String groupName) {
            // Return the cached children if it is processed
            Set<String> children = this.finalGroupChildAssocs.get(groupName);
            if (children != null) {
                return children;
            }

            // First, recurse to the parent most authorities
            for (String parent : ChainingUserRegistrySynchronizer.this.authorityService
                    .getContainingAuthorities(null, groupName, true)) {
                getContainedAuthorities(parent);
            }

            // Now descend on unprocessed parents.
            return cacheContainedAuthorities(groupName);
        }

        private Set<String> cacheContainedAuthorities(String groupName) {
            // Return the cached children if it is processed
            Set<String> children = this.finalGroupChildAssocs.get(groupName);
            if (children != null) {
                return children;
            }

            // Descend on unprocessed parents.
            children = ChainingUserRegistrySynchronizer.this.authorityService.getContainedAuthorities(null,
                    groupName, true);
            this.finalGroupChildAssocs.put(groupName, children);

            for (String child : children) {
                if (AuthorityType.getAuthorityType(child) != AuthorityType.USER) {
                    cacheContainedAuthorities(child);
                }
            }
            return children;
        }

        private synchronized void updateGroup(NodeDescription group, boolean existed) {
            PropertyMap groupProperties = group.getProperties();
            String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME);
            String groupDisplayName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
            if (groupDisplayName == null) {
                groupDisplayName = ChainingUserRegistrySynchronizer.this.authorityService
                        .getShortName(groupName);
            }

            // Divide the child associations into person and group associations, dealing with case sensitivity
            Set<String> newChildPersons = newPersonSet();
            Set<String> newChildGroups = new TreeSet<String>();

            for (String child : group.getChildAssociations()) {
                if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) {
                    newChildPersons.add(child);
                } else {
                    newChildGroups.add(child);
                }
            }

            // Account for differences if already existing
            if (existed) {
                // Update the display name now
                ChainingUserRegistrySynchronizer.this.authorityService.setAuthorityDisplayName(groupName,
                        groupDisplayName);

                // Work out the association differences
                for (String child : new TreeSet<String>(getContainedAuthorities(groupName))) {
                    if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) {
                        if (!newChildPersons.remove(child)) {
                            recordParentAssociationDeletion(child, groupName);
                        }
                    } else {
                        if (!newChildGroups.remove(child)) {
                            recordParentAssociationDeletion(child, groupName);
                        }
                    }
                }
            }
            // Mark as created if new
            else {
                // Make sure each group to be created features in the association deletion map (as these are handled in the same phase)
                recordParentAssociationDeletion(groupName, null);
                this.groupsToCreate.put(groupName, groupDisplayName);
            }

            // Create new associations
            for (String child : newChildPersons) {
                // Make sure each person with association changes features as a key in the deletion map
                recordParentAssociationDeletion(child, null);
                recordParentAssociationCreation(child, groupName);
            }
            for (String child : newChildGroups) {
                // Make sure each group with association changes features as a key in the deletion map
                recordParentAssociationDeletion(child, null);
                recordParentAssociationCreation(child, groupName);
            }
        }

        private void recordParentAssociationDeletion(String child, String parent) {
            Map<String, Set<String>> parentAssocs;
            if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) {
                parentAssocs = this.personParentAssocsToDelete;
            } else {
                // Reflect the change in the map of final group associations (for cycle detection later)
                parentAssocs = this.groupParentAssocsToDelete;
                if (parent != null) {
                    Set<String> children = this.finalGroupChildAssocs.get(parent);
                    children.remove(child);
                }
            }
            Set<String> parents = parentAssocs.get(child);
            if (parents == null) {
                parents = new TreeSet<String>();
                parentAssocs.put(child, parents);
            }
            if (parent != null) {
                parents.add(parent);
            }
        }

        private void recordParentAssociationCreation(String child, String parent) {
            Map<String, Set<String>> parentAssocs = AuthorityType.getAuthorityType(child) == AuthorityType.USER
                    ? this.personParentAssocsToCreate
                    : this.groupParentAssocsToCreate;
            Set<String> parents = parentAssocs.get(child);
            if (parents == null) {
                parents = new TreeSet<String>();
                parentAssocs.put(child, parents);
            }
            if (parent != null) {
                parents.add(parent);
            }
        }

        private void validateGroupParentAssocsToCreate() {
            Iterator<Map.Entry<String, Set<String>>> i = this.groupParentAssocsToCreate.entrySet().iterator();
            while (i.hasNext()) {
                Map.Entry<String, Set<String>> entry = i.next();
                String group = entry.getKey();
                Set<String> parents = entry.getValue();
                Deque<String> visited = new LinkedList<String>();
                Iterator<String> j = parents.iterator();
                while (j.hasNext()) {
                    String parent = j.next();
                    visited.add(parent);
                    if (validateAuthorityChildren(visited, group)) {
                        // The association validated - commit it
                        Set<String> children = finalGroupChildAssocs.get(parent);
                        if (children == null) {
                            children = new TreeSet<String>();
                            finalGroupChildAssocs.put(parent, children);
                        }
                        children.add(group);
                    } else {
                        // The association did not validate - prune it out
                        if (logger.isWarnEnabled()) {
                            ChainingUserRegistrySynchronizer.logger.warn("Not adding group '"
                                    + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(group)
                                    + "' to group '" + ChainingUserRegistrySynchronizer.this.authorityService
                                            .getShortName(parent)
                                    + "' as this creates a cyclic relationship");
                        }
                        j.remove();
                    }
                    visited.removeLast();
                }
                if (parents.isEmpty()) {
                    i.remove();
                }
            }

            // Sort the group associations in parent-first order (root groups first) to minimize reindexing overhead
            Map<String, Set<String>> sortedGroupAssociations = new LinkedHashMap<String, Set<String>>(
                    this.groupParentAssocsToCreate.size() * 2);
            Deque<String> visited = new LinkedList<String>();
            for (String authority : this.groupParentAssocsToCreate.keySet()) {
                visitGroupParentAssocs(visited, authority, this.groupParentAssocsToCreate,
                        sortedGroupAssociations);
            }

            this.groupParentAssocsToCreate = sortedGroupAssociations;
        }

        private boolean validateAuthorityChildren(Deque<String> visited, String authority) {
            if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) {
                return true;
            }
            if (visited.contains(authority)) {
                return false;
            }
            visited.add(authority);
            try {
                Set<String> children = this.finalGroupChildAssocs.get(authority);
                if (children != null) {
                    for (String child : children) {
                        if (!validateAuthorityChildren(visited, child)) {
                            return false;
                        }
                    }
                }
                return true;
            } finally {
                visited.removeLast();
            }
        }

        /**
         * Visits the given authority by recursively visiting its parents in associationsOld and then adding the
         * authority to associationsNew. Used to sort associationsOld into 'parent-first' order to minimize
         * reindexing overhead.
         * 
         * @param visited
         *            The ancestors that form the path to the authority to visit. Allows detection of cyclic child
         *            associations.
         * @param authority
         *            the authority to visit
         * @param associationsOld
         *            the association map to sort
         * @param associationsNew
         *            the association map to add to in parent-first order
         */
        private boolean visitGroupParentAssocs(Deque<String> visited, String authority,
                Map<String, Set<String>> associationsOld, Map<String, Set<String>> associationsNew) {
            if (visited.contains(authority)) {
                // Prevent cyclic paths (Shouldn't happen as we've already validated)
                return false;
            }
            visited.add(authority);
            try {
                if (!associationsNew.containsKey(authority)) {
                    Set<String> oldParents = associationsOld.get(authority);
                    if (oldParents != null) {
                        Set<String> newParents = new TreeSet<String>();

                        for (String parent : oldParents) {
                            if (visitGroupParentAssocs(visited, parent, associationsOld, associationsNew)) {
                                newParents.add(parent);
                            }
                        }
                        associationsNew.put(authority, newParents);
                    }
                }
                return true;
            } finally {
                visited.removeLast();
            }
        }

        private Set<String> newPersonSet() {
            return ChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive()
                    ? new TreeSet<String>()
                    : new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
        }

        private Map<String, Set<String>> newPersonMap() {
            return ChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive()
                    ? new TreeMap<String, Set<String>>()
                    : new TreeMap<String, Set<String>>(String.CASE_INSENSITIVE_ORDER);
        }

        private void logRetainParentAssociations(Map<String, Set<String>> parentAssocs, Set<String> toRetain) {
            Iterator<Map.Entry<String, Set<String>>> i = parentAssocs.entrySet().iterator();
            StringBuilder groupList = null;
            while (i.hasNext()) {
                Map.Entry<String, Set<String>> entry = i.next();
                String child = entry.getKey();
                if (!toRetain.contains(child)) {
                    if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        if (groupList == null) {
                            groupList = new StringBuilder(1024);
                        } else {
                            groupList.setLength(0);
                        }
                        for (String parent : entry.getValue()) {
                            if (groupList.length() > 0) {
                                groupList.append(", ");
                            }
                            groupList.append('\'').append(
                                    ChainingUserRegistrySynchronizer.this.authorityService.getShortName(parent))
                                    .append('\'');

                        }
                        ChainingUserRegistrySynchronizer.logger.debug("Ignoring non-existent member '"
                                + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(child)
                                + "' in groups {" + groupList.toString() + "}");
                    }
                    i.remove();
                }
            }
        }

        private void processGroups(UserRegistry userRegistry, boolean isFullSync, boolean splitTxns) {
            // MNT-12454 fix. If syncDelete is false, there is no need to pull all users and all groups from LDAP during the full synchronization.
            if ((syncDelete || !groupsToCreate.isEmpty())
                    && (isFullSync || !this.groupParentAssocsToDelete.isEmpty())) {
                final Set<String> allZonePersons = newPersonSet();
                final Set<String> allZoneGroups = new TreeSet<String>();

                // Add in current set of known authorities
                ChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper()
                        .doInTransaction(new RetryingTransactionCallback<Void>() {
                            public Void execute() throws Throwable {
                                allZonePersons.addAll(ChainingUserRegistrySynchronizer.this.authorityService
                                        .getAllAuthoritiesInZone(zoneId, AuthorityType.USER));
                                allZoneGroups.addAll(ChainingUserRegistrySynchronizer.this.authorityService
                                        .getAllAuthoritiesInZone(zoneId, AuthorityType.GROUP));
                                return null;
                            }
                        }, true, splitTxns);

                allZoneGroups.addAll(this.groupsToCreate.keySet());

                // Prune our set of authorities according to deletions
                if (isFullSync) {
                    final Set<String> personDeletionCandidates = newPersonSet();
                    personDeletionCandidates.addAll(allZonePersons);

                    final Set<String> groupDeletionCandidates = new TreeSet<String>();
                    groupDeletionCandidates.addAll(allZoneGroups);

                    this.deletionCandidates = new TreeSet<String>();

                    for (String person : userRegistry.getPersonNames()) {
                        personDeletionCandidates.remove(person);
                    }

                    for (String group : userRegistry.getGroupNames()) {
                        groupDeletionCandidates.remove(group);
                    }

                    this.deletionCandidates = new TreeSet<String>();
                    this.deletionCandidates.addAll(personDeletionCandidates);
                    this.deletionCandidates.addAll(groupDeletionCandidates);

                    if (allowDeletions) {
                        allZonePersons.removeAll(personDeletionCandidates);
                        allZoneGroups.removeAll(groupDeletionCandidates);
                    } else {
                        // Complete association deletion information by scanning deleted groups
                        BatchProcessor<String> groupScanner = new BatchProcessor<String>(
                                zone + " Missing Authority Scanning",
                                ChainingUserRegistrySynchronizer.this.transactionService
                                        .getRetryingTransactionHelper(),
                                this.deletionCandidates, ChainingUserRegistrySynchronizer.this.workerThreads,
                                20, ChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                                ChainingUserRegistrySynchronizer.logger,
                                ChainingUserRegistrySynchronizer.this.loggingInterval);
                        groupScanner.process(new BaseBatchProcessWorker<String>() {

                            @Override
                            public String getIdentifier(String entry) {
                                return entry;
                            }

                            @Override
                            public void process(String authority) throws Throwable {
                                //MNT-12454 fix. Modifies an authority's zone. Move authority from AUTH.EXT.LDAP1 to AUTH.ALF.
                                updateAuthorityZones(authority, Collections.singleton(zoneId),
                                        Collections.singleton(AuthorityService.ZONE_AUTH_ALFRESCO));
                            }
                        }, splitTxns);
                    }

                }

                // Prune the group associations now that we have complete information
                this.groupParentAssocsToCreate.keySet().retainAll(allZoneGroups);
                logRetainParentAssociations(this.groupParentAssocsToCreate, allZoneGroups);
                this.finalGroupChildAssocs.keySet().retainAll(allZoneGroups);

                // Pruning person associations will have to wait until we have passed over all persons and built up
                // this set
                this.allZonePersons = allZonePersons;

                if (!this.groupParentAssocsToDelete.isEmpty()) {
                    // Create/update the groups and delete parent associations to be deleted
                    // Batch 4 Group Creation and Association Deletion
                    BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>(
                            SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone),
                            ChainingUserRegistrySynchronizer.this.transactionService
                                    .getRetryingTransactionHelper(),
                            this.groupParentAssocsToDelete.entrySet(),
                            ChainingUserRegistrySynchronizer.this.workerThreads, 20,
                            ChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                            ChainingUserRegistrySynchronizer.logger,
                            ChainingUserRegistrySynchronizer.this.loggingInterval);
                    groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() {
                        public String getIdentifier(Map.Entry<String, Set<String>> entry) {
                            return entry.getKey() + " " + entry.getValue();
                        }

                        public void process(Map.Entry<String, Set<String>> entry) throws Throwable {
                            String child = entry.getKey();

                            String groupDisplayName = Analyzer.this.groupsToCreate.get(child);
                            if (groupDisplayName != null) {
                                String groupShortName = ChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(child);
                                if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                                    ChainingUserRegistrySynchronizer.logger
                                            .debug("Creating group '" + groupShortName + "'");
                                }
                                // create the group
                                ChainingUserRegistrySynchronizer.this.authorityService.createAuthority(
                                        AuthorityType.getAuthorityType(child), groupShortName, groupDisplayName,
                                        zoneSet);
                            } else {
                                // Maintain association deletions now. The creations will have to be done later once
                                // we have performed all the deletions in order to avoid creating cycles
                                maintainAssociationDeletions(child);
                            }
                        }
                    }, splitTxns);
                }
            }
        }

        private void finalizeAssociations(UserRegistry userRegistry, boolean splitTxns) {
            // First validate the group associations to be created for potential cycles. Remove any offending association
            validateGroupParentAssocsToCreate();

            // Now go ahead and create the group associations
            if (!this.groupParentAssocsToCreate.isEmpty()) {
                // Batch 5 Group Association Creation
                BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>(
                        SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone),
                        ChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper(),
                        this.groupParentAssocsToCreate.entrySet(),
                        ChainingUserRegistrySynchronizer.this.workerThreads, 20,
                        ChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                        ChainingUserRegistrySynchronizer.logger,
                        ChainingUserRegistrySynchronizer.this.loggingInterval);
                groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() {
                    public String getIdentifier(Map.Entry<String, Set<String>> entry) {
                        return entry.getKey() + " " + entry.getValue();
                    }

                    public void process(Map.Entry<String, Set<String>> entry) throws Throwable {
                        maintainAssociationCreations(entry.getKey());
                    }
                }, splitTxns);
            }

            // Remove all the associations we have already dealt with
            this.personParentAssocsToDelete.keySet().removeAll(this.personsProcessed);

            // Filter out associations to authorities that simply can't exist (and log if debugging is enabled)
            logRetainParentAssociations(this.personParentAssocsToCreate, this.allZonePersons);

            // Update associations to persons not updated themselves
            if (!this.personParentAssocsToDelete.isEmpty()) {
                // Batch 6 Person Association
                BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>(
                        SyncProcess.PERSON_ASSOCIATION.getTitle(zone),
                        ChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper(),
                        this.personParentAssocsToDelete.entrySet(),
                        ChainingUserRegistrySynchronizer.this.workerThreads, 20,
                        ChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                        ChainingUserRegistrySynchronizer.logger,
                        ChainingUserRegistrySynchronizer.this.loggingInterval);
                groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() {
                    public String getIdentifier(Map.Entry<String, Set<String>> entry) {
                        return entry.getKey() + " " + entry.getValue();
                    }

                    public void process(Map.Entry<String, Set<String>> entry) throws Throwable {
                        maintainAssociationDeletions(entry.getKey());
                        maintainAssociationCreations(entry.getKey());
                    }
                }, splitTxns);
            }
        }

        private void maintainAssociationDeletions(String authorityName) {
            boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER;
            Set<String> parentsToDelete = isPerson ? this.personParentAssocsToDelete.get(authorityName)
                    : this.groupParentAssocsToDelete.get(authorityName);
            if (parentsToDelete != null && !parentsToDelete.isEmpty()) {
                for (String parent : parentsToDelete) {
                    if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.debug("Removing '"
                                + ChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(authorityName)
                                + "' from group '"
                                + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(parent)
                                + "'");
                    }
                    ChainingUserRegistrySynchronizer.this.authorityService.removeAuthority(parent,
                            authorityName);
                }
            }

        }

        private void maintainAssociationCreations(String authorityName) {
            boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER;
            Set<String> parents = isPerson ? this.personParentAssocsToCreate.get(authorityName)
                    : this.groupParentAssocsToCreate.get(authorityName);
            if (parents != null && !parents.isEmpty()) {
                if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                    for (String groupName : parents) {
                        ChainingUserRegistrySynchronizer.logger.debug("Adding '"
                                + ChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(authorityName)
                                + "' to group '"
                                + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(groupName)
                                + "'");
                    }
                }
                try {
                    ChainingUserRegistrySynchronizer.this.authorityService.addAuthority(parents, authorityName);
                } catch (UnknownAuthorityException e) {
                    // Let's force a transaction retry if a parent doesn't exist. It may be because we are
                    // waiting for another worker thread to create it
                    throw new ConcurrencyFailureException("Forcing batch retry for unknown authority", e);
                } catch (InvalidNodeRefException e) {
                    // Another thread may have written the node, but it is not visible to this transaction
                    // See: ALF-5471: 'authorityMigration' patch can report 'Node does not exist'
                    throw new ConcurrencyFailureException("Forcing batch retry for invalid node", e);
                }
            }
            // Remember that this person's associations have been maintained
            if (isPerson) {
                synchronized (this) {
                    this.personsProcessed.add(authorityName);
                }
            }
        }
    } // end of Analyzer class

    // Run the first process the Group Analyzer
    final Analyzer groupAnalyzer = new Analyzer(lastModifiedMillis);
    int groupProcessedCount = groupProcessor.process(groupAnalyzer, splitTxns);

    groupAnalyzer.processGroups(userRegistry, isFullSync, splitTxns);

    // Process persons and their parent associations

    lastModifiedMillis = forceUpdate ? -1
            : getMostRecentUpdateTime(ChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId,
                    splitTxns);
    lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis);
    if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) {
        if (lastModified == null) {
            ChainingUserRegistrySynchronizer.logger
                    .info("Retrieving all users from user registry '" + zone + "'");
        } else {
            ChainingUserRegistrySynchronizer.logger.info(
                    "Retrieving users changed since " + DateFormat.getDateTimeInstance().format(lastModified)
                            + " from user registry '" + zone + "'");
        }
    }

    // User Creation and Association
    final BatchProcessor<NodeDescription> personProcessor = new BatchProcessor<NodeDescription>(
            SyncProcess.USER_CREATION.getTitle(zone), this.transactionService.getRetryingTransactionHelper(),
            userRegistry.getPersons(lastModified), this.workerThreads, 10, this.applicationEventPublisher,
            ChainingUserRegistrySynchronizer.logger, this.loggingInterval);

    final UserRegistry userRegistryFinalRef = userRegistry;

    class PersonWorker extends BaseBatchProcessWorker<NodeDescription> {
        private long latestTime;

        public PersonWorker(final long latestTime) {
            this.latestTime = latestTime;
        }

        public long getLatestTime() {
            return this.latestTime;
        }

        public String getIdentifier(NodeDescription entry) {
            return entry.getSourceId();
        }

        public void process(NodeDescription person) throws Throwable {
            // Make a mutable copy of the person properties, since they get written back to by person service
            HashMap<QName, Serializable> personProperties = new HashMap<QName, Serializable>(
                    person.getProperties());
            String personName = personProperties.get(ContentModel.PROP_USERNAME).toString().trim();
            personProperties.put(ContentModel.PROP_USERNAME, personName);

            if (Boolean.parseBoolean(ChainingUserRegistrySynchronizer.this.externalUserControl)
                    && ChainingUserRegistrySynchronizer.this.externalUserControlSubsystemName.equals(zone)
                    && userRegistryFinalRef instanceof LDAPUserRegistry) {
                try {
                    LDAPUserRegistry ldapUserRegistry = (LDAPUserRegistry) userRegistryFinalRef;

                    if (ldapUserRegistry.getUserAccountStatusInterpreter() != null) {
                        QName propertyNameToCheck = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
                                "userAccountStatusProperty");

                        if (personProperties.get(propertyNameToCheck) != null
                                || ldapUserRegistry.getUserAccountStatusInterpreter().acceptsNullArgument()) {
                            boolean isUserAccountDisabled = ldapUserRegistry.getUserAccountStatusInterpreter()
                                    .isUserAccountDisabled(personProperties.get(propertyNameToCheck));

                            personProperties.put(ContentModel.PROP_ENABLED, !isUserAccountDisabled);
                        }
                    }
                } catch (IllegalArgumentException iae) {
                    // Can be thrown by certain implementations of AbstractDirectoryServiceUserAccountStatusInterpreter;
                    // We'll just log it.
                    ChainingUserRegistrySynchronizer.logger.debug(iae.getMessage(), iae);
                }
            }

            // for invalid names will throw ConstraintException that will be catched by BatchProcessor$TxnCallback
            nameChecker.evaluate(personName);
            Set<String> zones = ChainingUserRegistrySynchronizer.this.authorityService
                    .getAuthorityZones(personName);
            if (zones == null) {
                // The person did not exist at all
                if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                    ChainingUserRegistrySynchronizer.logger.debug("Creating user '" + personName + "'");
                }
                ChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet);
            } else if (zones.contains(zoneId)) {
                // The person already existed in this zone: update the person
                if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                    ChainingUserRegistrySynchronizer.logger.debug("Updating user '" + personName + "'");
                }
                ChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName,
                        personProperties, false);
            } else {
                // Check whether the user is in any of the authentication chain zones
                Set<String> intersection = new TreeSet<String>(zones);
                intersection.retainAll(allZoneIds);
                // Check whether the user is in any of the higher priority authentication chain zones
                Set<String> visited = new TreeSet<String>(intersection);
                visited.retainAll(visitedZoneIds);
                if (visited.size() > 0) {
                    // A person that exists in a different zone with higher precedence - ignore
                    return;
                }

                else if (!allowDeletions || intersection.isEmpty()) {
                    // The person exists, but in a different zone. Either deletions are disallowed or the zone is
                    // not in the authentication chain. May be due to upgrade or zone changes. Let's re-zone them
                    if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.warn("Updating user '" + personName
                                + "'. This user will in future be assumed to originate from user registry '"
                                + zone + "'.");
                    }
                    updateAuthorityZones(personName, zones, zoneSet);
                    ChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName,
                            personProperties, false);
                } else {
                    // The person existed, but in a zone with lower precedence
                    if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.warn("Recreating occluded user '" + personName
                                + "'. This user was previously created through synchronization with a lower priority user registry.");
                    }
                    ChainingUserRegistrySynchronizer.this.personService.deletePerson(personName);
                    ChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet);
                }
            }

            // Maintain association deletions and creations in one shot (safe to do this with persons as we can't
            // create cycles)
            groupAnalyzer.maintainAssociationDeletions(personName);
            groupAnalyzer.maintainAssociationCreations(personName);

            synchronized (this) {
                // Maintain the last modified date
                Date personLastModified = person.getLastModified();
                if (personLastModified != null) {
                    this.latestTime = Math.max(this.latestTime, personLastModified.getTime());
                }
            }
        }
    }

    PersonWorker persons = new PersonWorker(lastModifiedMillis);
    int personProcessedCount = personProcessor.process(persons, splitTxns);

    // Process those associations to persons who themselves have not been updated
    groupAnalyzer.finalizeAssociations(userRegistry, splitTxns);

    // Only now that the whole tree has been processed is it safe to persist the last modified dates
    long latestTime = groupAnalyzer.getLatestTime();
    if (latestTime != -1) {
        setMostRecentUpdateTime(ChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId,
                latestTime, splitTxns);
    }
    latestTime = persons.getLatestTime();
    if (latestTime != -1) {
        setMostRecentUpdateTime(ChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId,
                latestTime, splitTxns);
    }

    // Delete authorities if we have complete information for the zone
    Set<String> deletionCandidates = groupAnalyzer.getDeletionCandidates();
    if (isFullSync && allowDeletions && !deletionCandidates.isEmpty()) {
        // Batch 7 Authority Deletion
        BatchProcessor<String> authorityDeletionProcessor = new BatchProcessor<String>(
                SyncProcess.AUTHORITY_DELETION.getTitle(zone),
                this.transactionService.getRetryingTransactionHelper(), deletionCandidates, this.workerThreads,
                10, this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger,
                this.loggingInterval);
        class AuthorityDeleter extends BaseBatchProcessWorker<String> {
            private int personProcessedCount;
            private int groupProcessedCount;

            public int getPersonProcessedCount() {
                return this.personProcessedCount;
            }

            public int getGroupProcessedCount() {
                return this.groupProcessedCount;
            }

            public String getIdentifier(String entry) {
                return entry;
            }

            public void process(String authority) throws Throwable {
                if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) {
                    if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.debug("Deleting user '" + authority + "'");
                    }
                    ChainingUserRegistrySynchronizer.this.personService.deletePerson(authority);
                    synchronized (this) {
                        this.personProcessedCount++;
                    }
                } else {
                    if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        ChainingUserRegistrySynchronizer.logger.debug("Deleting group '"
                                + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(authority)
                                + "'");
                    }
                    ChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(authority);
                    synchronized (this) {
                        this.groupProcessedCount++;
                    }
                }
            }
        }
        AuthorityDeleter authorityDeleter = new AuthorityDeleter();
        authorityDeletionProcessor.process(authorityDeleter, splitTxns);
        groupProcessedCount += authorityDeleter.getGroupProcessedCount();
        personProcessedCount += authorityDeleter.getPersonProcessedCount();
    }

    // Remember we have visited this zone
    visitedZoneIds.add(zoneId);

    Object statusParams[] = { personProcessedCount, groupProcessedCount };
    final String statusMessage = I18NUtil.getMessage("synchronization.summary.status", statusParams);

    if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) {
        ChainingUserRegistrySynchronizer.logger
                .info("Finished synchronizing users and groups with user registry '" + zone + "'");
        ChainingUserRegistrySynchronizer.logger.info(statusMessage);
    }

    notifySyncDirectoryEnd(zone, statusMessage);

}

From source file:org.cggh.repo.security.sync.CustomChainingUserRegistrySynchronizer.java

/**
 * Synchronizes local groups and users with a {@link UserRegistry} for a particular zone, optionally handling
 * deletions.//from  www  . ja v  a 2  s .co  m
 * 
 * @param zone
 *            the zone id. This identifier is used to tag all created groups and users, so that in the future we can
 *            tell those that have been deleted from the registry.
 * @param userRegistry
 *            the user registry for the zone.
 * @param forceUpdate
 *            Should the complete set of users and groups be updated / created locally or just those known to have
 *            changed since the last sync? When <code>true</code> then <i>all</i> users and groups are queried from
 *            the user registry and updated locally. When <code>false</code> then each source is only queried for
 *            those users and groups modified since the most recent modification date of all the objects last
 *            queried from that same source.
 * @param isFullSync
 *            Should a complete set of user and group IDs be queried from the user registries in order to determine
 *            deletions? This parameter is independent of <code>force</code> as a separate query is run to process
 *            updates.
 * @param splitTxns
 *            Can the modifications to Alfresco be split across multiple transactions for maximum performance? If
 *            <code>true</code>, users and groups are created/updated in batches for increased performance. If
 *            <code>false</code>, all users and groups are processed in the current transaction. This is required if
 *            calling synchronously (e.g. in response to an authentication event in the same transaction).
 * @param visitedZoneIds
 *            the set of zone ids already processed. These zones have precedence over the current zone when it comes
 *            to group name 'collisions'. If a user or group is queried that already exists locally but is tagged
 *            with one of the zones in this set, then it will be ignored as this zone has lower priority.
 * @param allZoneIds
 *            the set of all zone ids in the authentication chain. Helps us work out whether the zone information
 *            recorded against a user or group is invalid for the current authentication chain and whether the user
 *            or group needs to be 're-zoned'.
 */
private void syncWithPlugin(final String zone, UserRegistry userRegistry, boolean forceUpdate,
        boolean isFullSync, boolean splitTxns, final Set<String> visitedZoneIds, final Set<String> allZoneIds) {
    // Create a prefixed zone ID for use with the authority service
    final String zoneId = AuthorityService.ZONE_AUTH_EXT_PREFIX + zone;

    // Batch Process Names
    final String reservedBatchProcessNames[] = { SyncProcess.GROUP_ANALYSIS.getTitle(zone),
            SyncProcess.USER_CREATION.getTitle(zone), SyncProcess.MISSING_AUTHORITY.getTitle(zone),
            SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone),
            SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone),
            SyncProcess.PERSON_ASSOCIATION.getTitle(zone), SyncProcess.AUTHORITY_DELETION.getTitle(zone) };

    notifySyncDirectoryStart(zone, reservedBatchProcessNames);

    // Ensure that the zoneId exists before multiple threads start using it
    this.transactionService.getRetryingTransactionHelper()
            .doInTransaction(new RetryingTransactionCallback<Void>() {
                @Override
                public Void execute() throws Throwable {
                    authorityService.getOrCreateZone(zoneId);
                    return null;
                }
            }, false, splitTxns);

    // The set of zones we associate with new objects (default plus registry specific)
    final Set<String> zoneSet = getZones(zoneId);

    long lastModifiedMillis = forceUpdate ? -1
            : getMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE,
                    zoneId, splitTxns);
    Date lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis);

    if (CustomChainingUserRegistrySynchronizer.logger.isInfoEnabled()) {
        if (lastModified == null) {
            CustomChainingUserRegistrySynchronizer.logger
                    .info("Retrieving all groups from user registry '" + zone + "'");
        } else {
            CustomChainingUserRegistrySynchronizer.logger.info(
                    "Retrieving groups changed since " + DateFormat.getDateTimeInstance().format(lastModified)
                            + " from user registry '" + zone + "'");
        }
    }

    // First, analyze the group structure. Create maps of authorities to their parents for associations to create
    // and delete. Also deal with 'overlaps' with other zones in the authentication chain.
    final BatchProcessor<NodeDescription> groupProcessor = new BatchProcessor<NodeDescription>(
            SyncProcess.GROUP_ANALYSIS.getTitle(zone), this.transactionService.getRetryingTransactionHelper(),
            userRegistry.getGroups(lastModified), this.workerThreads, 20, this.applicationEventPublisher,
            CustomChainingUserRegistrySynchronizer.logger, this.loggingInterval);
    class Analyzer extends BaseBatchProcessWorker<NodeDescription> {
        private final Map<String, String> groupsToCreate = new TreeMap<String, String>();
        private final Map<String, Set<String>> personParentAssocsToCreate = newPersonMap();
        private final Map<String, Set<String>> personParentAssocsToDelete = newPersonMap();
        private Map<String, Set<String>> groupParentAssocsToCreate = new TreeMap<String, Set<String>>();
        private final Map<String, Set<String>> groupParentAssocsToDelete = new TreeMap<String, Set<String>>();
        private final Map<String, Set<String>> finalGroupChildAssocs = new TreeMap<String, Set<String>>();
        private List<String> personsProcessed = new LinkedList<String>();
        private Set<String> allZonePersons = Collections.emptySet();
        private Set<String> deletionCandidates;

        private long latestTime;

        public Analyzer(final long latestTime) {
            this.latestTime = latestTime;
        }

        public long getLatestTime() {
            return this.latestTime;
        }

        public Set<String> getDeletionCandidates() {
            return this.deletionCandidates;
        }

        public String getIdentifier(NodeDescription entry) {
            return entry.getSourceId();
        }

        public void process(NodeDescription group) throws Throwable {
            PropertyMap groupProperties = group.getProperties();
            String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME);
            String groupShortName = CustomChainingUserRegistrySynchronizer.this.authorityService
                    .getShortName(groupName);
            Set<String> groupZones = CustomChainingUserRegistrySynchronizer.this.authorityService
                    .getAuthorityZones(groupName);

            if (groupZones == null) {
                // The group did not exist at all
                updateGroup(group, false);
            } else {
                // Check whether the group is in any of the authentication chain zones
                Set<String> intersection = new TreeSet<String>(groupZones);
                intersection.retainAll(allZoneIds);
                // Check whether the group is in any of the higher priority authentication chain zones
                Set<String> visited = new TreeSet<String>(intersection);
                visited.retainAll(visitedZoneIds);

                if (groupZones.contains(zoneId)) {
                    // The group already existed in this zone: update the group
                    updateGroup(group, true);
                } else if (!visited.isEmpty()) {
                    // A group that exists in a different zone with higher precedence
                    return;
                } else if (!allowDeletions || intersection.isEmpty()) {
                    // Deletions are disallowed or the group exists, but not in a zone that's in the authentication
                    // chain. May be due to upgrade or zone changes. Let's re-zone them
                    if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger.warn("Updating group '" + groupShortName
                                + "'. This group will in future be assumed to originate from user registry '"
                                + zone + "'.");
                    }
                    updateAuthorityZones(groupName, groupZones, zoneSet);

                    // The group now exists in this zone: update the group
                    updateGroup(group, true);
                } else {
                    // The group existed, but in a zone with lower precedence
                    if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger.warn("Recreating occluded group '"
                                + groupShortName
                                + "'. This group was previously created through synchronization with a lower priority user registry.");
                    }
                    CustomChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(groupName);

                    // create the group
                    updateGroup(group, false);
                }
            }

            synchronized (this) {
                // Maintain the last modified date
                Date groupLastModified = group.getLastModified();
                if (groupLastModified != null) {
                    this.latestTime = Math.max(this.latestTime, groupLastModified.getTime());
                }
            }
        }

        // Recursively walks and caches the authorities relating to and from this group so that we can later detect potential cycles
        private Set<String> getContainedAuthorities(String groupName) {
            // Return the cached children if it is processed
            Set<String> children = this.finalGroupChildAssocs.get(groupName);
            if (children != null) {
                return children;
            }

            // First, recurse to the parent most authorities
            for (String parent : CustomChainingUserRegistrySynchronizer.this.authorityService
                    .getContainingAuthorities(null, groupName, true)) {
                getContainedAuthorities(parent);
            }

            // Now descend on unprocessed parents.
            return cacheContainedAuthorities(groupName);
        }

        private Set<String> cacheContainedAuthorities(String groupName) {
            // Return the cached children if it is processed
            Set<String> children = this.finalGroupChildAssocs.get(groupName);
            if (children != null) {
                return children;
            }

            // Descend on unprocessed parents.
            children = CustomChainingUserRegistrySynchronizer.this.authorityService
                    .getContainedAuthorities(null, groupName, true);
            this.finalGroupChildAssocs.put(groupName, children);

            for (String child : children) {
                if (AuthorityType.getAuthorityType(child) != AuthorityType.USER) {
                    cacheContainedAuthorities(child);
                }
            }
            return children;
        }

        private synchronized void updateGroup(NodeDescription group, boolean existed) {
            PropertyMap groupProperties = group.getProperties();
            String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME);
            String groupDisplayName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
            if (groupDisplayName == null) {
                groupDisplayName = CustomChainingUserRegistrySynchronizer.this.authorityService
                        .getShortName(groupName);
            }

            // Divide the child associations into person and group associations, dealing with case sensitivity
            Set<String> newChildPersons = newPersonSet();
            Set<String> newChildGroups = new TreeSet<String>();

            for (String child : group.getChildAssociations()) {
                if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) {
                    newChildPersons.add(child);
                } else {
                    newChildGroups.add(child);
                }
            }

            // Account for differences if already existing
            if (existed) {
                // Update the display name now
                CustomChainingUserRegistrySynchronizer.this.authorityService.setAuthorityDisplayName(groupName,
                        groupDisplayName);

                // Work out the association differences
                for (String child : new TreeSet<String>(getContainedAuthorities(groupName))) {
                    if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) {
                        if (!newChildPersons.remove(child)) {
                            recordParentAssociationDeletion(child, groupName);
                        }
                    } else {
                        if (!newChildGroups.remove(child)) {
                            recordParentAssociationDeletion(child, groupName);
                        }
                    }
                }
            }
            // Mark as created if new
            else {
                // Make sure each group to be created features in the association deletion map (as these are handled in the same phase)
                recordParentAssociationDeletion(groupName, null);
                this.groupsToCreate.put(groupName, groupDisplayName);
            }

            // Create new associations
            for (String child : newChildPersons) {
                // Make sure each person with association changes features as a key in the deletion map
                recordParentAssociationDeletion(child, null);
                recordParentAssociationCreation(child, groupName);
            }
            for (String child : newChildGroups) {
                // Make sure each group with association changes features as a key in the deletion map
                recordParentAssociationDeletion(child, null);
                recordParentAssociationCreation(child, groupName);
            }
        }

        private void recordParentAssociationDeletion(String child, String parent) {
            Map<String, Set<String>> parentAssocs;
            if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) {
                parentAssocs = this.personParentAssocsToDelete;
            } else {
                // Reflect the change in the map of final group associations (for cycle detection later)
                parentAssocs = this.groupParentAssocsToDelete;
                if (parent != null) {
                    Set<String> children = this.finalGroupChildAssocs.get(parent);
                    children.remove(child);
                }
            }
            Set<String> parents = parentAssocs.get(child);
            if (parents == null) {
                parents = new TreeSet<String>();
                parentAssocs.put(child, parents);
            }
            if (parent != null) {
                parents.add(parent);
            }
        }

        private void recordParentAssociationCreation(String child, String parent) {
            Map<String, Set<String>> parentAssocs = AuthorityType.getAuthorityType(child) == AuthorityType.USER
                    ? this.personParentAssocsToCreate
                    : this.groupParentAssocsToCreate;
            Set<String> parents = parentAssocs.get(child);
            if (parents == null) {
                parents = new TreeSet<String>();
                parentAssocs.put(child, parents);
            }
            if (parent != null) {
                parents.add(parent);
            }
        }

        private void validateGroupParentAssocsToCreate() {
            Iterator<Map.Entry<String, Set<String>>> i = this.groupParentAssocsToCreate.entrySet().iterator();
            while (i.hasNext()) {
                Map.Entry<String, Set<String>> entry = i.next();
                String group = entry.getKey();
                Set<String> parents = entry.getValue();
                Deque<String> visited = new LinkedList<String>();
                Iterator<String> j = parents.iterator();
                while (j.hasNext()) {
                    String parent = j.next();
                    visited.add(parent);
                    if (validateAuthorityChildren(visited, group)) {
                        // The association validated - commit it
                        Set<String> children = finalGroupChildAssocs.get(parent);
                        if (children == null) {
                            children = new TreeSet<String>();
                            finalGroupChildAssocs.put(parent, children);
                        }
                        children.add(group);
                    } else {
                        // The association did not validate - prune it out
                        if (logger.isWarnEnabled()) {
                            CustomChainingUserRegistrySynchronizer.logger.warn("Not adding group '"
                                    + CustomChainingUserRegistrySynchronizer.this.authorityService
                                            .getShortName(group)
                                    + "' to group '"
                                    + CustomChainingUserRegistrySynchronizer.this.authorityService
                                            .getShortName(parent)
                                    + "' as this creates a cyclic relationship");
                        }
                        j.remove();
                    }
                    visited.removeLast();
                }
                if (parents.isEmpty()) {
                    i.remove();
                }
            }

            // Sort the group associations in parent-first order (root groups first) to minimize reindexing overhead
            Map<String, Set<String>> sortedGroupAssociations = new LinkedHashMap<String, Set<String>>(
                    this.groupParentAssocsToCreate.size() * 2);
            Deque<String> visited = new LinkedList<String>();
            for (String authority : this.groupParentAssocsToCreate.keySet()) {
                visitGroupParentAssocs(visited, authority, this.groupParentAssocsToCreate,
                        sortedGroupAssociations);
            }

            this.groupParentAssocsToCreate = sortedGroupAssociations;
        }

        private boolean validateAuthorityChildren(Deque<String> visited, String authority) {
            if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) {
                return true;
            }
            if (visited.contains(authority)) {
                return false;
            }
            visited.add(authority);
            try {
                Set<String> children = this.finalGroupChildAssocs.get(authority);
                if (children != null) {
                    for (String child : children) {
                        if (!validateAuthorityChildren(visited, child)) {
                            return false;
                        }
                    }
                }
                return true;
            } finally {
                visited.removeLast();
            }
        }

        /**
         * Visits the given authority by recursively visiting its parents in associationsOld and then adding the
         * authority to associationsNew. Used to sort associationsOld into 'parent-first' order to minimize
         * reindexing overhead.
         * 
         * @param visited
         *            The ancestors that form the path to the authority to visit. Allows detection of cyclic child
         *            associations.
         * @param authority
         *            the authority to visit
         * @param associationsOld
         *            the association map to sort
         * @param associationsNew
         *            the association map to add to in parent-first order
         */
        private boolean visitGroupParentAssocs(Deque<String> visited, String authority,
                Map<String, Set<String>> associationsOld, Map<String, Set<String>> associationsNew) {
            if (visited.contains(authority)) {
                // Prevent cyclic paths (Shouldn't happen as we've already validated)
                return false;
            }
            visited.add(authority);
            try {
                if (!associationsNew.containsKey(authority)) {
                    Set<String> oldParents = associationsOld.get(authority);
                    if (oldParents != null) {
                        Set<String> newParents = new TreeSet<String>();

                        for (String parent : oldParents) {
                            if (visitGroupParentAssocs(visited, parent, associationsOld, associationsNew)) {
                                newParents.add(parent);
                            }
                        }
                        associationsNew.put(authority, newParents);
                    }
                }
                return true;
            } finally {
                visited.removeLast();
            }
        }

        private Set<String> newPersonSet() {
            return CustomChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive()
                    ? new TreeSet<String>()
                    : new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
        }

        private Map<String, Set<String>> newPersonMap() {
            return CustomChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive()
                    ? new TreeMap<String, Set<String>>()
                    : new TreeMap<String, Set<String>>(String.CASE_INSENSITIVE_ORDER);
        }

        private void logRetainParentAssociations(Map<String, Set<String>> parentAssocs, Set<String> toRetain) {
            Iterator<Map.Entry<String, Set<String>>> i = parentAssocs.entrySet().iterator();
            StringBuilder groupList = null;
            while (i.hasNext()) {
                Map.Entry<String, Set<String>> entry = i.next();
                String child = entry.getKey();
                if (!toRetain.contains(child)) {
                    if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        if (groupList == null) {
                            groupList = new StringBuilder(1024);
                        } else {
                            groupList.setLength(0);
                        }
                        for (String parent : entry.getValue()) {
                            if (groupList.length() > 0) {
                                groupList.append(", ");
                            }
                            groupList.append('\'')
                                    .append(CustomChainingUserRegistrySynchronizer.this.authorityService
                                            .getShortName(parent))
                                    .append('\'');

                        }
                        CustomChainingUserRegistrySynchronizer.logger
                                .debug("Ignoring non-existent member '"
                                        + CustomChainingUserRegistrySynchronizer.this.authorityService
                                                .getShortName(child)
                                        + "' in groups {" + groupList.toString() + "}");
                    }
                    i.remove();
                }
            }
        }

        private void processGroups(UserRegistry userRegistry, boolean isFullSync, boolean splitTxns) {
            // MNT-12454 fix. If syncDelete is false, there is no need to pull all users and all groups from LDAP during the full synchronization.
            if ((syncDelete || !groupsToCreate.isEmpty())
                    && (isFullSync || !this.groupParentAssocsToDelete.isEmpty())) {
                final Set<String> allZonePersons = newPersonSet();
                final Set<String> allZoneGroups = new TreeSet<String>();

                // Add in current set of known authorities
                CustomChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper()
                        .doInTransaction(new RetryingTransactionCallback<Void>() {
                            public Void execute() throws Throwable {
                                allZonePersons
                                        .addAll(CustomChainingUserRegistrySynchronizer.this.authorityService
                                                .getAllAuthoritiesInZone(zoneId, AuthorityType.USER));
                                allZoneGroups
                                        .addAll(CustomChainingUserRegistrySynchronizer.this.authorityService
                                                .getAllAuthoritiesInZone(zoneId, AuthorityType.GROUP));
                                return null;
                            }
                        }, true, splitTxns);

                allZoneGroups.addAll(this.groupsToCreate.keySet());

                // Prune our set of authorities according to deletions
                if (isFullSync) {
                    final Set<String> personDeletionCandidates = newPersonSet();
                    personDeletionCandidates.addAll(allZonePersons);

                    final Set<String> groupDeletionCandidates = new TreeSet<String>();
                    groupDeletionCandidates.addAll(allZoneGroups);

                    this.deletionCandidates = new TreeSet<String>();

                    for (String person : userRegistry.getPersonNames()) {
                        personDeletionCandidates.remove(person);
                    }

                    for (String group : userRegistry.getGroupNames()) {
                        groupDeletionCandidates.remove(group);
                    }

                    this.deletionCandidates = new TreeSet<String>();
                    this.deletionCandidates.addAll(personDeletionCandidates);
                    this.deletionCandidates.addAll(groupDeletionCandidates);

                    if (allowDeletions) {
                        allZonePersons.removeAll(personDeletionCandidates);
                        allZoneGroups.removeAll(groupDeletionCandidates);
                    } else {
                        // Complete association deletion information by scanning deleted groups
                        BatchProcessor<String> groupScanner = new BatchProcessor<String>(
                                zone + " Missing Authority Scanning",
                                CustomChainingUserRegistrySynchronizer.this.transactionService
                                        .getRetryingTransactionHelper(),
                                this.deletionCandidates,
                                CustomChainingUserRegistrySynchronizer.this.workerThreads, 20,
                                CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                                CustomChainingUserRegistrySynchronizer.logger,
                                CustomChainingUserRegistrySynchronizer.this.loggingInterval);
                        groupScanner.process(new BaseBatchProcessWorker<String>() {

                            @Override
                            public String getIdentifier(String entry) {
                                return entry;
                            }

                            @Override
                            public void process(String authority) throws Throwable {
                                //MNT-12454 fix. Modifies an authority's zone. Move authority from AUTH.EXT.LDAP1 to AUTH.ALF.
                                updateAuthorityZones(authority, Collections.singleton(zoneId),
                                        Collections.singleton(AuthorityService.ZONE_AUTH_ALFRESCO));
                            }
                        }, splitTxns);
                    }

                }

                // Prune the group associations now that we have complete information
                this.groupParentAssocsToCreate.keySet().retainAll(allZoneGroups);
                logRetainParentAssociations(this.groupParentAssocsToCreate, allZoneGroups);
                this.finalGroupChildAssocs.keySet().retainAll(allZoneGroups);

                // Pruning person associations will have to wait until we have passed over all persons and built up
                // this set
                this.allZonePersons = allZonePersons;

                if (!this.groupParentAssocsToDelete.isEmpty()) {
                    // Create/update the groups and delete parent associations to be deleted
                    // Batch 4 Group Creation and Association Deletion
                    BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>(
                            SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone),
                            CustomChainingUserRegistrySynchronizer.this.transactionService
                                    .getRetryingTransactionHelper(),
                            this.groupParentAssocsToDelete.entrySet(),
                            CustomChainingUserRegistrySynchronizer.this.workerThreads, 20,
                            CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                            CustomChainingUserRegistrySynchronizer.logger,
                            CustomChainingUserRegistrySynchronizer.this.loggingInterval);
                    groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() {
                        public String getIdentifier(Map.Entry<String, Set<String>> entry) {
                            return entry.getKey() + " " + entry.getValue();
                        }

                        public void process(Map.Entry<String, Set<String>> entry) throws Throwable {
                            String child = entry.getKey();

                            String groupDisplayName = Analyzer.this.groupsToCreate.get(child);
                            if (groupDisplayName != null) {
                                String groupShortName = CustomChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(child);
                                if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                                    CustomChainingUserRegistrySynchronizer.logger
                                            .debug("Creating group '" + groupShortName + "'");
                                }
                                // create the group
                                CustomChainingUserRegistrySynchronizer.this.authorityService.createAuthority(
                                        AuthorityType.getAuthorityType(child), groupShortName, groupDisplayName,
                                        zoneSet);
                            } else {
                                // Maintain association deletions now. The creations will have to be done later once
                                // we have performed all the deletions in order to avoid creating cycles
                                maintainAssociationDeletions(child);
                            }
                        }
                    }, splitTxns);
                }
            }
        }

        private void finalizeAssociations(UserRegistry userRegistry, boolean splitTxns) {
            // First validate the group associations to be created for potential cycles. Remove any offending association
            validateGroupParentAssocsToCreate();

            // Now go ahead and create the group associations
            if (!this.groupParentAssocsToCreate.isEmpty()) {
                // Batch 5 Group Association Creation
                BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>(
                        SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone),
                        CustomChainingUserRegistrySynchronizer.this.transactionService
                                .getRetryingTransactionHelper(),
                        this.groupParentAssocsToCreate.entrySet(),
                        CustomChainingUserRegistrySynchronizer.this.workerThreads, 20,
                        CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                        CustomChainingUserRegistrySynchronizer.logger,
                        CustomChainingUserRegistrySynchronizer.this.loggingInterval);
                groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() {
                    public String getIdentifier(Map.Entry<String, Set<String>> entry) {
                        return entry.getKey() + " " + entry.getValue();
                    }

                    public void process(Map.Entry<String, Set<String>> entry) throws Throwable {
                        maintainAssociationCreations(entry.getKey());
                    }
                }, splitTxns);
            }

            // Remove all the associations we have already dealt with
            this.personParentAssocsToDelete.keySet().removeAll(this.personsProcessed);

            // Filter out associations to authorities that simply can't exist (and log if debugging is enabled)
            logRetainParentAssociations(this.personParentAssocsToCreate, this.allZonePersons);

            // Update associations to persons not updated themselves
            if (!this.personParentAssocsToDelete.isEmpty()) {
                // Batch 6 Person Association
                BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>(
                        SyncProcess.PERSON_ASSOCIATION.getTitle(zone),
                        CustomChainingUserRegistrySynchronizer.this.transactionService
                                .getRetryingTransactionHelper(),
                        this.personParentAssocsToDelete.entrySet(),
                        CustomChainingUserRegistrySynchronizer.this.workerThreads, 20,
                        CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher,
                        CustomChainingUserRegistrySynchronizer.logger,
                        CustomChainingUserRegistrySynchronizer.this.loggingInterval);
                groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() {
                    public String getIdentifier(Map.Entry<String, Set<String>> entry) {
                        return entry.getKey() + " " + entry.getValue();
                    }

                    public void process(Map.Entry<String, Set<String>> entry) throws Throwable {
                        maintainAssociationDeletions(entry.getKey());
                        maintainAssociationCreations(entry.getKey());
                    }
                }, splitTxns);
            }
        }

        private void maintainAssociationDeletions(String authorityName) {
            boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER;
            Set<String> parentsToDelete = isPerson ? this.personParentAssocsToDelete.get(authorityName)
                    : this.groupParentAssocsToDelete.get(authorityName);
            if (parentsToDelete != null && !parentsToDelete.isEmpty()) {
                for (String parent : parentsToDelete) {
                    if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger.debug("Removing '"
                                + CustomChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(authorityName)
                                + "' from group '"
                                + CustomChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(parent)
                                + "'");
                    }
                    CustomChainingUserRegistrySynchronizer.this.authorityService.removeAuthority(parent,
                            authorityName);
                }
            }

        }

        private void maintainAssociationCreations(String authorityName) {
            boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER;
            Set<String> parents = isPerson ? this.personParentAssocsToCreate.get(authorityName)
                    : this.groupParentAssocsToCreate.get(authorityName);
            if (parents != null && !parents.isEmpty()) {
                if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                    for (String groupName : parents) {
                        CustomChainingUserRegistrySynchronizer.logger.debug("Adding '"
                                + CustomChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(authorityName)
                                + "' to group '" + CustomChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(groupName)
                                + "'");
                    }
                }
                try {
                    CustomChainingUserRegistrySynchronizer.this.authorityService.addAuthority(parents,
                            authorityName);
                } catch (UnknownAuthorityException e) {
                    // Let's force a transaction retry if a parent doesn't exist. It may be because we are
                    // waiting for another worker thread to create it
                    throw new ConcurrencyFailureException("Forcing batch retry for unknown authority", e);
                } catch (InvalidNodeRefException e) {
                    // Another thread may have written the node, but it is not visible to this transaction
                    // See: ALF-5471: 'authorityMigration' patch can report 'Node does not exist'
                    throw new ConcurrencyFailureException("Forcing batch retry for invalid node", e);
                }
            }
            // Remember that this person's associations have been maintained
            if (isPerson) {
                synchronized (this) {
                    this.personsProcessed.add(authorityName);
                }
            }
        }
    } // end of Analyzer class

    // Run the first process the Group Analyzer
    final Analyzer groupAnalyzer = new Analyzer(lastModifiedMillis);
    int groupProcessedCount = groupProcessor.process(groupAnalyzer, splitTxns);

    groupAnalyzer.processGroups(userRegistry, isFullSync, splitTxns);

    // Process persons and their parent associations

    lastModifiedMillis = forceUpdate ? -1
            : getMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE,
                    zoneId, splitTxns);
    lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis);
    if (CustomChainingUserRegistrySynchronizer.logger.isInfoEnabled()) {
        if (lastModified == null) {
            CustomChainingUserRegistrySynchronizer.logger
                    .info("Retrieving all users from user registry '" + zone + "'");
        } else {
            CustomChainingUserRegistrySynchronizer.logger.info(
                    "Retrieving users changed since " + DateFormat.getDateTimeInstance().format(lastModified)
                            + " from user registry '" + zone + "'");
        }
    }

    // User Creation and Association
    final BatchProcessor<NodeDescription> personProcessor = new BatchProcessor<NodeDescription>(
            SyncProcess.USER_CREATION.getTitle(zone), this.transactionService.getRetryingTransactionHelper(),
            userRegistry.getPersons(lastModified), this.workerThreads, 10, this.applicationEventPublisher,
            CustomChainingUserRegistrySynchronizer.logger, this.loggingInterval);
    class PersonWorker extends BaseBatchProcessWorker<NodeDescription> {
        private long latestTime;

        public PersonWorker(final long latestTime) {
            this.latestTime = latestTime;
        }

        public long getLatestTime() {
            return this.latestTime;
        }

        public String getIdentifier(NodeDescription entry) {
            return entry.getSourceId();
        }

        public void process(NodeDescription person) throws Throwable {
            // Make a mutable copy of the person properties, since they get written back to by person service
            HashMap<QName, Serializable> personProperties = new HashMap<QName, Serializable>(
                    person.getProperties());
            String personName = personProperties.get(ContentModel.PROP_USERNAME).toString().trim();
            personProperties.put(ContentModel.PROP_USERNAME, personName);
            // for invalid names will throw ConstraintException that will be catched by BatchProcessor$TxnCallback
            nameChecker.evaluate(personName);
            Set<String> zones = CustomChainingUserRegistrySynchronizer.this.authorityService
                    .getAuthorityZones(personName);
            if (zones == null) {
                // The person did not exist at all
                if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                    CustomChainingUserRegistrySynchronizer.logger.debug("Creating user '" + personName + "'");
                }
                CustomChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties,
                        zoneSet);
                CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName,
                        person.getProperties(), getLatestTime());
            } else if (zones.contains(zoneId)) {
                // The person already existed in this zone: update the person
                if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                    CustomChainingUserRegistrySynchronizer.logger.debug("Updating user '" + personName + "'");
                }
                CustomChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName,
                        personProperties, false);
                CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName,
                        person.getProperties(), getLatestTime());
            } else {
                // Check whether the user is in any of the authentication chain zones
                Set<String> intersection = new TreeSet<String>(zones);
                intersection.retainAll(allZoneIds);
                // Check whether the user is in any of the higher priority authentication chain zones
                Set<String> visited = new TreeSet<String>(intersection);
                visited.retainAll(visitedZoneIds);
                if (visited.size() > 0) {
                    // A person that exists in a different zone with higher precedence - ignore
                    return;
                }

                else if (!allowDeletions || intersection.isEmpty()) {
                    // The person exists, but in a different zone. Either deletions are disallowed or the zone is
                    // not in the authentication chain. May be due to upgrade or zone changes. Let's re-zone them
                    if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger.warn("Updating user '" + personName
                                + "'. This user will in future be assumed to originate from user registry '"
                                + zone + "'.");
                    }
                    updateAuthorityZones(personName, zones, zoneSet);
                    CustomChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName,
                            personProperties, false);
                    CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName,
                            person.getProperties(), getLatestTime());
                } else {
                    // The person existed, but in a zone with lower precedence
                    if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger.warn("Recreating occluded user '"
                                + personName
                                + "'. This user was previously created through synchronization with a lower priority user registry.");
                    }
                    CustomChainingUserRegistrySynchronizer.this.personService.deletePerson(personName);
                    CustomChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties,
                            zoneSet);
                    CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName,
                            person.getProperties(), getLatestTime());
                }
            }

            // Maintain association deletions and creations in one shot (safe to do this with persons as we can't
            // create cycles)
            groupAnalyzer.maintainAssociationDeletions(personName);
            groupAnalyzer.maintainAssociationCreations(personName);

            synchronized (this) {
                // Maintain the last modified date
                Date personLastModified = person.getLastModified();
                if (personLastModified != null) {
                    this.latestTime = Math.max(this.latestTime, personLastModified.getTime());
                }
            }
        }
    }

    PersonWorker persons = new PersonWorker(lastModifiedMillis);
    int personProcessedCount = personProcessor.process(persons, splitTxns);

    // Process those associations to persons who themselves have not been updated
    groupAnalyzer.finalizeAssociations(userRegistry, splitTxns);

    // Only now that the whole tree has been processed is it safe to persist the last modified dates
    long latestTime = groupAnalyzer.getLatestTime();
    if (latestTime != -1) {
        setMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId,
                latestTime, splitTxns);
    }
    latestTime = persons.getLatestTime();
    if (latestTime != -1) {
        setMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId,
                latestTime, splitTxns);
    }

    // Delete authorities if we have complete information for the zone
    Set<String> deletionCandidates = groupAnalyzer.getDeletionCandidates();
    if (isFullSync && allowDeletions && !deletionCandidates.isEmpty()) {
        // Batch 7 Authority Deletion
        BatchProcessor<String> authorityDeletionProcessor = new BatchProcessor<String>(
                SyncProcess.AUTHORITY_DELETION.getTitle(zone),
                this.transactionService.getRetryingTransactionHelper(), deletionCandidates, this.workerThreads,
                10, this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger,
                this.loggingInterval);
        class AuthorityDeleter extends BaseBatchProcessWorker<String> {
            private int personProcessedCount;
            private int groupProcessedCount;

            public int getPersonProcessedCount() {
                return this.personProcessedCount;
            }

            public int getGroupProcessedCount() {
                return this.groupProcessedCount;
            }

            public String getIdentifier(String entry) {
                return entry;
            }

            public void process(String authority) throws Throwable {
                if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) {
                    if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger
                                .debug("Deleting user '" + authority + "'");
                    }
                    CustomChainingUserRegistrySynchronizer.this.personService.deletePerson(authority);
                    synchronized (this) {
                        this.personProcessedCount++;
                    }
                } else {
                    if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) {
                        CustomChainingUserRegistrySynchronizer.logger.debug("Deleting group '"
                                + CustomChainingUserRegistrySynchronizer.this.authorityService
                                        .getShortName(authority)
                                + "'");
                    }
                    CustomChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(authority);
                    synchronized (this) {
                        this.groupProcessedCount++;
                    }
                }
            }
        }
        AuthorityDeleter authorityDeleter = new AuthorityDeleter();
        authorityDeletionProcessor.process(authorityDeleter, splitTxns);
        groupProcessedCount += authorityDeleter.getGroupProcessedCount();
        personProcessedCount += authorityDeleter.getPersonProcessedCount();
    }

    // Remember we have visited this zone
    visitedZoneIds.add(zoneId);

    Object statusParams[] = { personProcessedCount, groupProcessedCount };
    final String statusMessage = I18NUtil.getMessage("synchronization.summary.status", statusParams);

    if (CustomChainingUserRegistrySynchronizer.logger.isInfoEnabled()) {
        CustomChainingUserRegistrySynchronizer.logger
                .info("Finished synchronizing users and groups with user registry '" + zone + "'");
        CustomChainingUserRegistrySynchronizer.logger.info(statusMessage);
    }

    notifySyncDirectoryEnd(zone, statusMessage);

}

From source file:com.rapidminer.gui.new_plotter.gui.ColorSchemeDialog.java

private void createPreviewPlotBackend(Color background, int groupinBins) {
    DataTable dataTable;//from w ww.  ja v  a  2  s .c om
    // retrieve data for showing example data
    try {
        ExampleSet exampleSet = (ExampleSet) ((IOObjectEntry) new RepositoryLocation("//Samples/data/Iris")
                .locateEntry()).retrieveData(null);
        dataTable = new DataTableExampleSetAdapter(exampleSet, null);
    } catch (MalformedRepositoryLocationException e) {
        return;
    } catch (RepositoryException e) {
        return;
    }

    if (dataTable == null || dataTable.getColumnNumber() < 2) {
        return;
    }

    // domain and y column
    DataTableColumn domainColumn = new DataTableColumn(dataTable, 0);
    DataTableColumn mainColumn = new DataTableColumn(dataTable, 1);

    Font titleFont = new Font("Lucida Sans", Font.PLAIN, 12);

    // configure gradient preview plot
    gradientPlotConfig = new PlotConfiguration(domainColumn);
    gradientPlotConfig.setTitleText(I18N
            .getGUILabel("plotter.configuration_dialog.color_scheme_dialog.numerical_gradient_preview.label"));
    gradientPlotConfig.setFrameBackgroundColor(background);
    gradientPlotConfig.getDomainConfigManager().setLabel("");
    gradientPlotConfig.setTitleFont(titleFont);
    gradientPlotConfig.getLegendConfiguration().setLegendPosition(LegendPosition.NONE);

    RangeAxisConfig rangeAxis = new RangeAxisConfig("", gradientPlotConfig);
    ValueSource valueSource = new ValueSource(gradientPlotConfig, mainColumn, null, false);
    rangeAxis.addValueSource(valueSource,
            gradientPlotConfig.getAutomaticSeriesFormatForNextValueSource(rangeAxis));
    gradientPlotConfig.addRangeAxisConfig(rangeAxis);

    DefaultDimensionConfig colorDimension = new DefaultDimensionConfig(gradientPlotConfig, mainColumn,
            PlotDimension.COLOR);
    gradientPlotConfig.setDimensionConfig(PlotDimension.COLOR, colorDimension);

    PlotInstance plotInstance = new PlotInstance(gradientPlotConfig, dataTable);

    gradientPlotter = new JFreeChartPlotEngine(plotInstance, true);

    // configure nominal preview plot
    nominalPlotConfig = new PlotConfiguration(domainColumn);
    nominalPlotConfig.setTitleText(
            I18N.getGUILabel("plotter.configuration_dialog.color_scheme_dialog.nominal_color_preview.label"));
    nominalPlotConfig.setFrameBackgroundColor(background);
    nominalPlotConfig.getDomainConfigManager().setLabel("");
    nominalPlotConfig.setTitleFont(titleFont);
    nominalPlotConfig.getLegendConfiguration().setLegendPosition(LegendPosition.NONE);

    EqualDataFractionGrouping edfg;
    try {
        edfg = new EqualDataFractionGrouping(domainColumn, 4, true, DateFormat.getDateTimeInstance());
    } catch (ChartConfigurationException e1) {
        return;
    }
    nominalPlotConfig.getDomainConfigManager().setGrouping(edfg);

    RangeAxisConfig nominalRangeAxis = new RangeAxisConfig("", nominalPlotConfig);
    ValueSource nominalValueSource = new ValueSource(nominalPlotConfig, mainColumn,
            AggregationFunctionType.count, true);
    nominalValueSource.getSeriesFormat().setSeriesType(VisualizationType.BARS);
    nominalValueSource.getSeriesFormat().setStackingMode(StackingMode.RELATIVE);
    nominalRangeAxis.addValueSource(nominalValueSource,
            nominalPlotConfig.getAutomaticSeriesFormatForNextValueSource(nominalRangeAxis));
    nominalPlotConfig.addRangeAxisConfig(nominalRangeAxis);

    DefaultDimensionConfig nominalColorDimension = new DefaultDimensionConfig(nominalPlotConfig, mainColumn,
            PlotDimension.COLOR);

    EqualDataFractionGrouping edfgColor;
    try {
        edfgColor = new EqualDataFractionGrouping(mainColumn, groupinBins, true,
                DateFormat.getDateTimeInstance());
    } catch (ChartConfigurationException e1) {
        return;
    }
    nominalColorDimension.setGrouping(edfgColor);
    nominalPlotConfig.setDimensionConfig(PlotDimension.COLOR, nominalColorDimension);

    PlotInstance nominalPlotInstance = new PlotInstance(nominalPlotConfig, dataTable);

    nominalPlotter = new JFreeChartPlotEngine(nominalPlotInstance, true);

    gradientPlotter.endInitializing();
    nominalPlotter.endInitializing();

    return;
}

From source file:com.f8full.casserolesencours.CasserolesEnCoursActivity.java

private void createAndShareRequestTable() throws JSONException, HttpResponseException, IOException {
    String SqlQuery = "CREATE TABLE " + getString(R.string.registerRequestTableName)
            + " (Date:DATETIME, RequestedViewOnMasterTable_ID:STRING)";

    String encodedQuery = URLEncoder.encode(SqlQuery, "UTF-8");

    GoogleUrl GUrl = new GoogleUrl(SERVICE_URL + "?sql=" + encodedQuery + "&encid=true");

    try {/*from w  w  w  . jav  a 2 s. co  m*/

        HttpRequest request = mGOOGClient.getRequestFactory().buildPostRequest(GUrl, null);
        HttpHeaders headers = new HttpHeaders();

        headers.setContentLength("0");//Required so that Fusion Table API considers request
        request.setHeaders(headers);

        HttpResponse response = request.execute();

        if (response.getStatusCode() == 200) {
            //Table created, insert relevant data
            //Extract encrypted ID
            String tableName = "NONAME";

            InputStreamReader inputStreamReader = new InputStreamReader(response.getContent());
            BufferedReader bufferedStreamReader = new BufferedReader(inputStreamReader);
            CSVReader reader = new CSVReader(bufferedStreamReader);
            // The first line is the column names, and the remaining lines are the rows.
            List<String[]> csvLines = reader.readAll();
            List<String> columns = Arrays.asList(csvLines.get(0));
            List<String[]> rows = csvLines.subList(1, csvLines.size());

            //TextView textView = (TextView) findViewById(R.id.nameField);
            String regRequestTableIDToShare = rows.get(0)[0];

            setRegRequestTableID(regRequestTableIDToShare);
            mRegisterRequestTableID = regRequestTableIDToShare;

            //Now insert data
            SqlQuery = "INSERT INTO " + regRequestTableIDToShare
                    + " (Date, RequestedViewOnMasterTable_ID) VALUES ('"
                    + DateFormat.getDateTimeInstance().format(new Date()) + "', '"
                    + getString(R.string.regTableReqRegisteredTextStart) + " "
                    + getString(R.string.updateRegStatusButtonText) + " "
                    + getString(R.string.regTableReqRegisteredTextEnd) + "')";

            encodedQuery = URLEncoder.encode(SqlQuery, "UTF-8");

            GUrl = new GoogleUrl(SERVICE_URL + "?sql=" + encodedQuery);

            try {

                HttpRequest requestFillRegTable = mGOOGClient.getRequestFactory().buildPostRequest(GUrl, null);
                headers = new HttpHeaders();

                headers.setContentLength("0");//Required so that Fusion Table API considers request
                requestFillRegTable.setHeaders(headers);

                HttpResponse responseFillRegTable = requestFillRegTable.execute();

                if (responseFillRegTable.getStatusCode() == 200) {
                    toastMessage("Request table timestamped :)");

                }

            } catch (HttpResponseException e) {
                throw e;

            } catch (IOException e) {

                throw e;
            }

            //now share it with user casserolesencours@gmail.com
            try {
                //               <entry xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'>
                //                 <category scheme='http://schemas.google.com/g/2005#kind'
                //                   term='http://schemas.google.com/acl/2007#accessRule'/>
                //                 <gAcl:role value='writer'/>
                //                 <gAcl:scope type='user' value='new_writer@example.com'/>
                //               </entry>

                XmlNamespaceDictionary docDic = new XmlNamespaceDictionary();
                docDic.set("", "http://www.w3.org/2005/Atom");
                docDic.set("gAcl", "http://schemas.google.com/acl/2007");

                GenericData data = new GenericData();
                AtomCategory category = AtomCategory.newKind("accessRule");
                AtomRole role = AtomRole.newRole("writer");
                AtomScope scope = AtomScope.newScope("user", "casserolesencours@gmail.com");

                data.put("category", category);
                data.put("gAcl:role", role);
                data.put("gAcl:scope", scope);

                AtomContent content = AtomContent.forEntry(docDic, data);

                GUrl = new GoogleUrl("https://docs.google.com/feeds/default/private/full/"
                        + regRequestTableIDToShare + "/acl?v=3&send-notification-emails=false");
                HttpRequest requestShare = mGOOGClient.getRequestFactory().buildPostRequest(GUrl, content);

                HttpResponse responseShare = requestShare.execute();

                if (responseShare.getStatusCode() == 201) {
                    toastMessage(getString(R.string.registerShareTableOKToast));

                    mMainHandler.post(new Runnable() {

                        public void run() {

                            ((TextView) findViewById(R.id.geolocationStatus))
                                    .setTextColor(getResources().getColor(R.color.text_orange));
                            ((TextView) findViewById(R.id.geolocationStatus))
                                    .setText(getString(R.string.geolocationAnonymizePending));

                            setTableStatus(getString(R.string.geolocationAnonymizePending));

                            ((Button) findViewById(R.id.registerAnonymize)).setVisibility(View.GONE);
                            ((Button) findViewById(R.id.checkAnonymize)).setVisibility(View.VISIBLE);
                        }
                    });

                }
            } catch (HttpResponseException e) {
                if (e.getStatusCode() == 409) //Conflict
                {
                    toastMessage("SHOULD NOT HAPPEN");
                }

                throw (e);
            } catch (IOException e) {
                throw (e);
            }
        }

    } catch (HttpResponseException e) {
        throw e;

    } catch (IOException e) {

        throw e;
    }

}

From source file:org.apache.hadoop.dfs.Balancer.java

/** main method of Balancer
 * @param args arguments to a Balancer//from  w  w w . j  a  v a2 s . c  om
 * @exception any exception occurs during datanode balancing
 */
public int run(String[] args) throws Exception {
    long startTime = FSNamesystem.now();
    OutputStream out = null;
    try {
        // initialize a balancer
        init(parseArgs(args));

        /* Check if there is another balancer running.
         * Exit if there is another one running.
         */
        out = checkAndMarkRunningBalancer();
        if (out == null) {
            System.out.println("Another balancer is running. Exiting...");
            return ALREADY_RUNNING;
        }

        Formatter formatter = new Formatter(System.out);
        System.out.println(
                "Time Stamp               Iteration#  Bytes Already Moved  Bytes Left To Move  Bytes Being Moved");
        int iterations = 0;
        while (true) {
            /* get all live datanodes of a cluster and their disk usage
             * decide the number of bytes need to be moved
             */
            long bytesLeftToMove = initNodes();
            if (bytesLeftToMove == 0) {
                System.out.println("The cluster is balanced. Exiting...");
                return SUCCESS;
            } else {
                LOG.info("Need to move " + FsShell.byteDesc(bytesLeftToMove)
                        + " bytes to make the cluster balanced.");
            }

            /* Decide all the nodes that will participate in the block move and
             * the number of bytes that need to be moved from one node to another
             * in this iteration. Maximum bytes to be moved per node is
             * Min(1 Band worth of bytes,  MAX_SIZE_TO_MOVE).
             */
            long bytesToMove = chooseNodes();
            if (bytesToMove == 0) {
                System.out.println("No block can be moved. Exiting...");
                return NO_MOVE_BLOCK;
            } else {
                LOG.info("Will move " + FsShell.byteDesc(bytesToMove) + "bytes in this iteration");
            }

            formatter.format("%-24s %10d  %19s  %18s  %17s\n",
                    DateFormat.getDateTimeInstance().format(new Date()), iterations,
                    FsShell.byteDesc(bytesMoved.get()), FsShell.byteDesc(bytesLeftToMove),
                    FsShell.byteDesc(bytesToMove));

            /* For each pair of <source, target>, start a thread that repeatedly 
             * decide a block to be moved and its proxy source, 
             * then initiates the move until all bytes are moved or no more block
             * available to move.
             * Exit no byte has been moved for 5 consecutive iterations.
             */
            if (dispatchBlockMoves() > 0) {
                notChangedIterations = 0;
            } else {
                notChangedIterations++;
                if (notChangedIterations >= 5) {
                    System.out.println("No block has been moved for 5 iterations. Exiting...");
                    return NO_MOVE_PROGRESS;
                }
            }

            // clean all lists
            resetData();

            try {
                Thread.sleep(2 * conf.getLong("dfs.heartbeat.interval", 3));
            } catch (InterruptedException ignored) {
            }

            iterations++;
        }
    } catch (IllegalArgumentException ae) {
        return ILLEGAL_ARGS;
    } catch (IOException e) {
        System.out.println("Received an IO exception: " + e.getMessage() + " . Exiting...");
        return IO_EXCEPTION;
    } finally {
        // shutdown thread pools
        dispatcherExecutor.shutdownNow();
        moverExecutor.shutdownNow();

        // close the output file
        IOUtils.closeStream(out);
        try {
            fs.delete(BALANCER_ID_PATH, true);
        } catch (IOException ignored) {
        }
        System.out.println("Balancing took " + time2Str(FSNamesystem.now() - startTime));
    }
}

From source file:edu.ku.brc.specify.datamodel.busrules.BaseTreeBusRules.java

/**
 * @return true if locks were aquired.//  w w  w  .  ja v  a 2 s .c  om
 * 
 * Locks necessary tables prior to a save.
 * Only used when ALLOW_CONCURRENT_FORM_ACCESS is true.
 */
protected boolean getRequiredLocks(Object dataObj) {
    TreeDefIface<?, ?, ?> treeDef = ((Treeable<?, ?, ?>) dataObj).getDefinition();
    boolean result = !TreeDefStatusMgr.isRenumberingNodes(treeDef)
            && TreeDefStatusMgr.isNodeNumbersAreUpToDate(treeDef);
    if (!result) {
        try {
            Thread.sleep(1500);
            result = !TreeDefStatusMgr.isRenumberingNodes(treeDef)
                    && TreeDefStatusMgr.isNodeNumbersAreUpToDate(treeDef);
        } catch (Exception e) {
            result = false;
        }
    }
    if (result) {
        TaskSemaphoreMgr.USER_ACTION r = TaskSemaphoreMgr.lock(getFormSaveLockTitle(), getFormSaveLockName(),
                "save", TaskSemaphoreMgr.SCOPE.Discipline, false, new TaskSemaphoreMgrCallerIFace() {

                    /* (non-Javadoc)
                     * @see edu.ku.brc.specify.dbsupport.TaskSemaphoreMgrCallerIFace#resolveConflict(edu.ku.brc.specify.datamodel.SpTaskSemaphore, boolean, java.lang.String)
                     */
                    @Override
                    public USER_ACTION resolveConflict(SpTaskSemaphore semaphore, boolean previouslyLocked,
                            String prevLockBy) {
                        if (System.currentTimeMillis()
                                - semaphore.getLockedTime().getTime() > FORM_SAVE_LOCK_MAX_DURATION_IN_MILLIS) {
                            //something is clearly wrong with the lock. Ignore it and re-use it. It will be cleared when save succeeds.
                            log.warn("automatically overriding expired " + getFormSaveLockTitle()
                                    + " lock set by " + prevLockBy + " at "
                                    + DateFormat.getDateTimeInstance().format(semaphore.getLockedTime()));
                            return USER_ACTION.OK;
                        } else {
                            return USER_ACTION.Error;
                        }
                    }

                }, false);
        result = r == TaskSemaphoreMgr.USER_ACTION.OK;
    }
    return result;
}

From source file:org.apache.hadoop.hdfs.server.balancer.Balancer.java

/** main method of Balancer
 * @param args arguments to a Balancer/*from  w  ww  .  j  a  v a2 s  .c o  m*/
 * @exception any exception occurs during datanode balancing
 */
public int run(String[] args) throws Exception {
    long startTime = Util.now();
    OutputStream out = null;
    try {
        // initialize a balancer
        init(parseArgs(args));

        /* Check if there is another balancer running.
         * Exit if there is another one running.
         */
        out = checkAndMarkRunningBalancer();
        if (out == null) {
            System.out.println("Another balancer is running. Exiting...");
            return ALREADY_RUNNING;
        }

        Formatter formatter = new Formatter(System.out);
        System.out.println(
                "Time Stamp               Iteration#  Bytes Already Moved  Bytes Left To Move  Bytes Being Moved");
        int iterations = 0;
        while (true) {
            /* get all live datanodes of a cluster and their disk usage
             * decide the number of bytes need to be moved
             */
            long bytesLeftToMove = initNodes();
            if (bytesLeftToMove == 0) {
                System.out.println("The cluster is balanced. Exiting...");
                return SUCCESS;
            } else {
                LOG.info("Need to move " + StringUtils.byteDesc(bytesLeftToMove)
                        + " bytes to make the cluster balanced.");
            }

            /* Decide all the nodes that will participate in the block move and
             * the number of bytes that need to be moved from one node to another
             * in this iteration. Maximum bytes to be moved per node is
             * Min(1 Band worth of bytes,  MAX_SIZE_TO_MOVE).
             */
            long bytesToMove = chooseNodes();
            if (bytesToMove == 0) {
                System.out.println("No block can be moved. Exiting...");
                return NO_MOVE_BLOCK;
            } else {
                LOG.info("Will move " + StringUtils.byteDesc(bytesToMove) + "bytes in this iteration");
            }

            formatter.format("%-24s %10d  %19s  %18s  %17s\n",
                    DateFormat.getDateTimeInstance().format(new Date()), iterations,
                    StringUtils.byteDesc(bytesMoved.get()), StringUtils.byteDesc(bytesLeftToMove),
                    StringUtils.byteDesc(bytesToMove));

            /* For each pair of <source, target>, start a thread that repeatedly 
             * decide a block to be moved and its proxy source, 
             * then initiates the move until all bytes are moved or no more block
             * available to move.
             * Exit no byte has been moved for 5 consecutive iterations.
             */
            if (dispatchBlockMoves() > 0) {
                notChangedIterations = 0;
            } else {
                notChangedIterations++;
                if (notChangedIterations >= 5) {
                    System.out.println("No block has been moved for 5 iterations. Exiting...");
                    return NO_MOVE_PROGRESS;
                }
            }

            // clean all lists
            resetData();

            try {
                Thread.sleep(2 * conf.getLong("dfs.heartbeat.interval", 3));
            } catch (InterruptedException ignored) {
            }

            iterations++;
        }
    } catch (IllegalArgumentException ae) {
        return ILLEGAL_ARGS;
    } catch (IOException e) {
        System.out.println("Received an IO exception: " + e.getMessage() + " . Exiting...");
        return IO_EXCEPTION;
    } finally {
        // shutdown thread pools
        dispatcherExecutor.shutdownNow();
        moverExecutor.shutdownNow();

        shouldRun = false;
        try {
            if (keyupdaterthread != null)
                keyupdaterthread.interrupt();
        } catch (Exception e) {
            LOG.warn("Exception shutting down access key updater thread", e);
        }
        // close the output file
        IOUtils.closeStream(out);
        if (fs != null) {
            try {
                fs.delete(BALANCER_ID_PATH, true);
            } catch (IOException ignored) {
            }
        }
        System.out.println("Balancing took " + time2Str(Util.now() - startTime));
    }
}

From source file:com.f8full.casserolesencours.CasserolesEnCoursActivity.java

protected void writeToFusionTable(boolean manual, String desc) {
    if (mAlohar.getPlaceManager().getCurrentLocation().getLatitude() == 0.0
            || mAlohar.getPlaceManager().getCurrentLocation().getLongitude() == 0.0) {
        toastMessage(getString(R.string.nullocationErrorMessage));
        return;/* ww  w .ja v  a2 s . c om*/
    }

    JSONObject newData = new JSONObject();

    try {
        newData.put("DESC", desc);
        newData.put("LOCATION", getLatLongPosition());
        newData.put("DATE", DateFormat.getDateTimeInstance().format(new Date()));

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    writeToFusionTable(manual, newData);

}

From source file:mzb.Balancer.java

/** Run an iteration for all datanodes. */
private ReturnStatus run(int iteration, Formatter formatter, Configuration conf) {
    try {//from ww w.  j a v  a2s. com
        this.fs = FileSystem.get(conf);
        /* get all live datanodes of a cluster and their disk usage
         * decide the number of bytes need to be moved
         */
        //final long bytesLeftToMove = 
        initNodes(nnc.client.getDatanodeReport(DatanodeReportType.LIVE));
        /*if (bytesLeftToMove == 0) {
          System.out.println("The cluster is balanced. Exiting...");
          return ReturnStatus.SUCCESS;
        } else {
          LOG.info( "Need to move "+ StringUtils.byteDesc(bytesLeftToMove)
              + " to make the cluster balanced." );
        }*/

        /* Decide all the nodes that will participate in the block move and
         * the number of bytes that need to be moved from one node to another
         * in this iteration. Maximum bytes to be moved per node is
         * Min(1 Band worth of bytes,  MAX_SIZE_TO_MOVE).
         */
        final long bytesToMove = chooseNodes(metaFile, targetDir);
        if (bytesToMove == 0) {
            System.out.println("No block can be moved. Exiting...");
            return ReturnStatus.NO_MOVE_BLOCK;
        } else {
            LOG.info("Will move " + StringUtils.byteDesc(bytesToMove) + " in this iteration");
        }

        formatter.format("%-24s %10d  %19s  %18s  %n", DateFormat.getDateTimeInstance().format(new Date()),
                iteration, StringUtils.byteDesc(bytesMoved.get()),
                //StringUtils.byteDesc(bytesLeftToMove),
                StringUtils.byteDesc(bytesToMove));

        /* For each pair of <source, target>, start a thread that repeatedly 
         * decide a block to be moved and its proxy source, 
         * then initiates the move until all bytes are moved or no more block
         * available to move.
         * Exit no byte has been moved for 5 consecutive iterations.
         */
        if (!this.nnc.shouldContinue(dispatchBlockMoves())) {
            return ReturnStatus.NO_MOVE_PROGRESS;
        }

        return ReturnStatus.IN_PROGRESS;
    } catch (IllegalArgumentException e) {
        System.out.println(e + ".  Exiting ...");
        return ReturnStatus.ILLEGAL_ARGS;
    } catch (IOException e) {
        System.out.println(e + ".  Exiting ...");
        return ReturnStatus.IO_EXCEPTION;
    } catch (InterruptedException e) {
        System.out.println(e + ".  Exiting ...");
        return ReturnStatus.INTERRUPTED;
    } finally {
        // shutdown thread pools
        dispatcherExecutor.shutdownNow();
        moverExecutor.shutdownNow();
    }
}