org.apereo.portal.layout.dlm.EditManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apereo.portal.layout.dlm.EditManager.java

Source

/**
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apereo.portal.layout.dlm;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apereo.portal.PortalException;
import org.apereo.portal.layout.IUserLayoutStore;
import org.apereo.portal.security.IPerson;
import org.apereo.portal.spring.locator.UserLayoutStoreLocator;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/** 
 * Handles ILF node edit directives recorded in the PLF.
 * 
 * @version $Revision$ $Date$
 * @since uPortal 2.5
 */
public class EditManager {
    private static IUserLayoutStore dls = null;
    private static final Log LOG = LogFactory.getLog(EditManager.class);

    /**
     * Hands back the single instance of RDBMDistributedLayoutStore. There is
     * already a method
     * for aquiring a single instance of the configured layout store so we
     * delegate over there so that all references refer to the same instance.
     * This method is solely for convenience so that we don't have to keep
     * calling UserLayoutStoreFactory and casting the resulting class.
     */
    private static IUserLayoutStore getDLS() {
        if (dls == null) {
            dls = UserLayoutStoreLocator.getUserLayoutStore();
        }
        return dls;
    }

    /**
       Get the edit set if any stored in the passed in node. If not found and
       if the create flag is true then create a new edit set and add it as a
       child to the passed in node. Then return it.
    */
    private static Element getEditSet(Element node, Document plf, IPerson person, boolean create)
            throws PortalException {
        Node child = node.getFirstChild();

        while (child != null) {
            if (child.getNodeName().equals(Constants.ELM_EDIT_SET))
                return (Element) child;
            child = child.getNextSibling();
        }

        if (create == false)
            return null;

        String ID = null;

        try {
            ID = getDLS().getNextStructDirectiveId(person);
        } catch (Exception e) {
            throw new PortalException("Exception encountered while " + "generating new edit set node "
                    + "Id for userId=" + person.getID(), e);
        }
        Element editSet = plf.createElement(Constants.ELM_EDIT_SET);
        editSet.setAttribute(Constants.ATT_TYPE, Constants.ELM_EDIT_SET);
        editSet.setAttribute(Constants.ATT_ID, ID);
        node.appendChild(editSet);
        return editSet;
    }

    /**
       Create and append an edit directive to the edit set if not there.
       This only records that the attribute was changed
       and the value in the plf copy node should be used, if
       allowed, during the merge at login time.
    */
    static void addEditDirective(Element plfNode, String attributeName, IPerson person) throws PortalException {
        addDirective(plfNode, attributeName, Constants.ELM_EDIT, person);
    }

    /**
       Create and append a user preferences edit directive to the edit set if
       not there. This only records that the attribute was changed. The value
       will be in the user preferences object for the user.
    */
    public static void addPrefsDirective(Element plfNode, String attributeName, IPerson person)
            throws PortalException {
        addDirective(plfNode, attributeName, Constants.ELM_PREF, person);
    }

    /**
       Create and append an edit directive to the edit set if not there.
    */
    private static void addDirective(Element plfNode, String attributeName, String type, IPerson person)
            throws PortalException {
        Document plf = (Document) person.getAttribute(Constants.PLF);
        Element editSet = getEditSet(plfNode, plf, person, true);

        // see if attributes has already been marked as being edited
        Element child = (Element) editSet.getFirstChild();
        Element edit = null;

        while (child != null && edit == null) {
            if (child.getNodeName().equals(type) && child.getAttribute(Constants.ATT_NAME).equals(attributeName))
                edit = child;
            child = (Element) child.getNextSibling();
        }
        if (edit == null) // if not found then newly mark as edited
        {
            String ID = null;

            try {
                ID = getDLS().getNextStructDirectiveId(person);
            } catch (Exception e) {
                throw new PortalException("Exception encountered while " + "generating new edit node "
                        + "Id for userId=" + person.getID(), e);
            }
            edit = plf.createElement(type);
            edit.setAttribute(Constants.ATT_TYPE, type);
            edit.setAttribute(Constants.ATT_ID, ID);
            edit.setAttribute(Constants.ATT_NAME, attributeName);
            editSet.appendChild(edit);
        }
    }

    /**
       Evaluate whether attribute changes exist in the ilfChild and if so
       apply them. Returns true if some changes existed. If changes existed
       but matched those in the original node then they are not applicable,
       are removed from the editSet, and false is returned.
    */
    public static boolean applyEditSet(Element plfChild, Element original) {
        // first get edit set if it exists
        Element editSet = null;
        try {
            editSet = getEditSet(plfChild, null, null, false);
        } catch (Exception e) {
            // should never occur unless problem during create in getEditSet
            // and we are telling it not to create.
            return false;
        }

        if (editSet == null || editSet.getChildNodes().getLength() == 0)
            return false;

        if (original.getAttribute(Constants.ATT_EDIT_ALLOWED).equals("false")) {
            // can't change anymore so discard changes
            plfChild.removeChild(editSet);
            return false;
        }

        Document ilf = original.getOwnerDocument();
        boolean attributeChanged = false;
        Element edit = (Element) editSet.getFirstChild();

        while (edit != null) {
            String attribName = edit.getAttribute(Constants.ATT_NAME);
            Attr attr = plfChild.getAttributeNode(attribName);

            // preferences are only updated at preference storage time so
            // if a preference change exists in the edit set assume it is
            // still valid so that the node being edited will persist in
            // the PLF.
            if (edit.getNodeName().equals(Constants.ELM_PREF))
                attributeChanged = true;
            else if (attr == null) {
                // attribute removed. See if needs removing in original.
                attr = original.getAttributeNode(attribName);
                if (attr == null) // edit irrelevant,
                    editSet.removeChild(edit);
                else {
                    // edit differs, apply to original
                    original.removeAttribute(attribName);
                    attributeChanged = true;
                }
            } else {
                // attribute there, see if original is also there
                Attr origAttr = original.getAttributeNode(attribName);
                if (origAttr == null) {
                    // original attribute isn't defined so need to add
                    origAttr = (Attr) ilf.importNode(attr, true);
                    original.setAttributeNode(origAttr);
                    attributeChanged = true;
                } else {
                    // original attrib found, see if different
                    if (attr.getValue().equals(origAttr.getValue())) {
                        // they are the same, edit irrelevant
                        editSet.removeChild(edit);
                    } else {
                        // edit differs, apply to original
                        origAttr.setValue(attr.getValue());
                        attributeChanged = true;
                    }
                }
            }
            edit = (Element) edit.getNextSibling();
        }
        return attributeChanged;
    }

    /**
     * Searches for a dlm:pref command which indicates that a user preference
     * was change and if found removes it from the user's PLF.
     */
    public static void removePreferenceDirective(IPerson person, String elementId, String attributeName) {
        removeDirective(elementId, attributeName, Constants.ELM_PREF, person);
    }

    /**
     * Searches for a dlm:edit command which indicates that a node attribute was
     * reset to the value in the fragment and if found removes it from the
     * user's PLF.
     */
    public static void removeEditDirective(String elementId, String attributeName, IPerson person) {
        removeDirective(elementId, attributeName, Constants.ELM_EDIT, person);
    }

    /**
     * Searches for a command of the passed-in type and if found removes it from
     * the user's PLF.
     */
    private static void removeDirective(String elementId, String attributeName, String type, IPerson person) {
        Document plf = (Document) person.getAttribute(Constants.PLF);
        Element node = plf.getElementById(elementId);
        if (node == null)
            return;

        Element editSet = null;

        try {
            editSet = getEditSet(node, plf, person, false);
        } catch (Exception e) {
            /*
             * we should never get here since we are calling getEditSet passing
             * create=false meaning that the only portion of that method that
             * tosses an exception will not be reached with this call. But if a
             * runtime exception somehow occurs we will log it so that we don't
             * lose the information.
             */
            LOG.error(e, e);
            return;
        }

        // if no edit set then the edit can't be there either
        if (editSet == null)
            return;

        Node child = editSet.getFirstChild();

        while (child != null) {
            if (child.getNodeName().equals(type)) {
                Attr attr = ((Element) child).getAttributeNode(Constants.ATT_NAME);
                if (attr != null && attr.getValue().equals(attributeName)) {
                    // we found it, remove it
                    editSet.removeChild(child);
                    break;
                }
            }
            child = child.getNextSibling();
        }
        // if that was the last on in the edit set then delete it
        if (editSet.getFirstChild() == null)
            node.removeChild(editSet);
    }
}