001: /* Copyright 2005 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.layout.dlm;
007:
008: import org.apache.commons.logging.Log;
009: import org.apache.commons.logging.LogFactory;
010: import org.jasig.portal.layout.IUserLayoutStore;
011: import org.jasig.portal.layout.UserLayoutStoreFactory;
012: import org.jasig.portal.PortalException;
013: import org.jasig.portal.security.IPerson;
014: import org.w3c.dom.Document;
015: import org.w3c.dom.Element;
016: import org.w3c.dom.Node;
017: import org.w3c.dom.NodeList;
018:
019: /**
020: * Looks for, applies against the ilf, and updates accordingly the delete
021: * set within a plf.
022: *
023: * @version $Revision: 36294 $ $Date: 2005-11-10 12:36:31 -0700 (Thu, 10 Nov 2005) $
024: * @since uPortal 2.5
025: */
026: public class DeleteManager {
027: public static final String RCS_ID = "@(#) $Header$";
028: private static final Log LOG = LogFactory
029: .getLog(DeleteManager.class);
030:
031: private static RDBMDistributedLayoutStore dls = null;
032:
033: /**
034: * Hands back the single instance of RDBMDistributedLayoutStore. There is
035: * already a method
036: * for aquiring a single instance of the configured layout store so we
037: * delegate over there so that all references refer to the same instance.
038: * This method is solely for convenience so that we don't have to keep
039: * calling UserLayoutStoreFactory and casting the resulting class.
040: */
041: private static RDBMDistributedLayoutStore getDLS() {
042: if (dls == null) {
043: IUserLayoutStore uls = null;
044: uls = UserLayoutStoreFactory.getUserLayoutStoreImpl();
045: dls = (RDBMDistributedLayoutStore) uls;
046: }
047: return dls;
048: }
049:
050: /**
051: Get the delete set if any from the plf and process each delete command
052: removing any that fail from the delete set so that the delete set is
053: self cleaning.
054: */
055: static void applyAndUpdateDeleteSet(Document plf, Document ilf,
056: IntegrationResult result) {
057:
058: Element dSet = null;
059: try {
060: dSet = getDeleteSet(plf, null, false);
061: } catch (Exception e) {
062: LOG
063: .error(
064: "Exception occurred while getting user's DLM delete-set.",
065: e);
066: }
067:
068: if (dSet == null)
069: return;
070:
071: NodeList deletes = dSet.getChildNodes();
072:
073: for (int i = deletes.getLength() - 1; i >= 0; i--) {
074: if (applyDelete((Element) deletes.item(i), ilf) == false) {
075: dSet.removeChild(deletes.item(i));
076: result.changedPLF = true;
077: } else {
078: result.changedILF = true;
079: }
080: }
081:
082: if (dSet.getChildNodes().getLength() == 0) {
083: plf.getDocumentElement().removeChild(dSet);
084: result.changedPLF = true;
085: }
086: }
087:
088: /**
089: Attempt to apply a single delete command and return true if it succeeds
090: or false otherwise. If the delete is disallowed or the target element
091: no longer exists in the document the delete command fails and returns
092: false.
093: */
094: private static boolean applyDelete(Element delete, Document ilf) {
095: String nodeID = delete.getAttribute(Constants.ATT_NAME);
096:
097: Element e = ilf.getElementById(nodeID);
098:
099: if (e == null)
100: return false;
101:
102: String deleteAllowed = e
103: .getAttribute(Constants.ATT_DELETE_ALLOWED);
104: if (deleteAllowed.equals("false"))
105: return false;
106:
107: Element p = (Element) e.getParentNode();
108: e.setIdAttribute(Constants.ATT_ID, false);
109: p.removeChild(e);
110: return true;
111: }
112:
113: /**
114: Get the delete set if any stored in the root of the document or create
115: it is passed in create flag is true.
116: */
117: private static Element getDeleteSet(Document plf, IPerson person,
118: boolean create) throws PortalException {
119: Node root = plf.getDocumentElement();
120: Node child = root.getFirstChild();
121:
122: while (child != null) {
123: if (child.getNodeName().equals(Constants.ELM_DELETE_SET))
124: return (Element) child;
125: child = child.getNextSibling();
126: }
127:
128: if (create == false)
129: return null;
130:
131: String ID = null;
132:
133: try {
134: ID = getDLS().getNextStructDirectiveId(person);
135: } catch (Exception e) {
136: throw new PortalException("Exception encountered while "
137: + "generating new delete set node "
138: + "Id for userId=" + person.getID(), e);
139: }
140: Element delSet = plf.createElement(Constants.ELM_DELETE_SET);
141: delSet.setAttribute(Constants.ATT_TYPE,
142: Constants.ELM_DELETE_SET);
143: delSet.setAttribute(Constants.ATT_ID, ID);
144: root.appendChild(delSet);
145: return delSet;
146: }
147:
148: /**
149: Create and append a delete directive to delete the node identified by
150: the passed in element id. If this node contains any incorporated
151: elements then they must also have a delete directive added in here to
152: prevent incorporated channels originating in another column from
153: reappearing in that column because the position set entry that pulled
154: them into this column was now removed. (ie: the user moved an inc'd
155: channel to this column and then deleted the column means that the inc'd
156: channel should be deleted also.) This was designed to add a delete
157: directive for each nested element having an ID so as to work for the
158: future case of a tree view.
159: */
160: public static void addDeleteDirective(Element compViewNode,
161: String elementID, IPerson person) throws PortalException {
162: Document plf = (Document) person.getAttribute(Constants.PLF);
163: Element delSet = getDeleteSet(plf, person, true);
164: addDeleteDirective(compViewNode, elementID, person, plf, delSet);
165: }
166:
167: /**
168: This method does the actual work of adding a delete directive and then
169: recursively calling itself for any incoporated children that need to be
170: deleted as well.
171: */
172: private static void addDeleteDirective(Element compViewNode,
173: String elementID, IPerson person, Document plf,
174: Element delSet) throws PortalException {
175: String ID = null;
176:
177: try {
178: ID = getDLS().getNextStructDirectiveId(person);
179: } catch (Exception e) {
180: throw new PortalException("Exception encountered while "
181: + "generating new delete node " + "Id for userId="
182: + person.getID(), e);
183: }
184: Element delete = plf.createElement(Constants.ELM_DELETE);
185: delete.setAttribute(Constants.ATT_TYPE, Constants.ELM_DELETE);
186: delete.setAttribute(Constants.ATT_ID, ID);
187: delete.setAttributeNS(Constants.NS_URI, Constants.ATT_NAME,
188: elementID);
189: delSet.appendChild(delete);
190:
191: // now pass through children and add delete directives for those with
192: // IDs indicating that they were incorporated
193: Element child = (Element) compViewNode.getFirstChild();
194:
195: while (child != null) {
196: String childID = child.getAttribute("ID");
197: if (childID.startsWith(Constants.FRAGMENT_ID_USER_PREFIX))
198: addDeleteDirective(child, childID, person, plf, delSet);
199: child = (Element) child.getNextSibling();
200: }
201: }
202: }
|