0001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
0002: * See license distributed with this file and
0003: * available online at http://www.uportal.org/license.html
0004: */
0005:
0006: package org.jasig.portal.channels.UserPreferences;
0007:
0008: import java.io.IOException;
0009: import java.io.InputStream;
0010: import java.io.StringWriter;
0011: import java.util.ArrayList;
0012: import java.util.Enumeration;
0013: import java.util.HashMap;
0014: import java.util.Iterator;
0015: import java.util.List;
0016:
0017: import javax.xml.transform.Transformer;
0018: import javax.xml.transform.TransformerFactory;
0019: import javax.xml.transform.dom.DOMSource;
0020: import javax.xml.transform.sax.SAXResult;
0021: import javax.xml.transform.sax.SAXTransformerFactory;
0022: import javax.xml.transform.sax.TransformerHandler;
0023:
0024: import org.jasig.portal.ChannelRegistryManager;
0025: import org.jasig.portal.ChannelRuntimeData;
0026: import org.jasig.portal.ChannelSAXStreamFilter;
0027: import org.jasig.portal.ChannelStaticData;
0028: import org.jasig.portal.GeneralRenderingException;
0029: import org.jasig.portal.IUserPreferencesManager;
0030: import org.jasig.portal.PortalControlStructures;
0031: import org.jasig.portal.PortalException;
0032: import org.jasig.portal.PortalSessionManager;
0033: import org.jasig.portal.StructureAttributesIncorporationFilter;
0034: import org.jasig.portal.StructureStylesheetUserPreferences;
0035: import org.jasig.portal.StylesheetSet;
0036: import org.jasig.portal.UserPreferences;
0037: import org.jasig.portal.UserProfile;
0038: import org.jasig.portal.i18n.LocaleAwareXSLT;
0039: import org.jasig.portal.layout.IUserLayoutManager;
0040: import org.jasig.portal.layout.IUserLayoutStore;
0041: import org.jasig.portal.layout.UserLayoutManagerFactory;
0042: import org.jasig.portal.layout.UserLayoutStoreFactory;
0043: import org.jasig.portal.layout.node.IUserLayoutChannelDescription;
0044: import org.jasig.portal.layout.node.IUserLayoutFolderDescription;
0045: import org.jasig.portal.layout.node.IUserLayoutNodeDescription;
0046: import org.jasig.portal.layout.node.UserLayoutChannelDescription;
0047: import org.jasig.portal.layout.node.UserLayoutFolderDescription;
0048: import org.jasig.portal.serialize.OutputFormat;
0049: import org.jasig.portal.serialize.XMLSerializer;
0050: import org.apache.commons.logging.Log;
0051: import org.apache.commons.logging.LogFactory;
0052: import org.jasig.portal.utils.DocumentFactory;
0053: import org.jasig.portal.utils.ResourceLoader;
0054: import org.jasig.portal.utils.SAX2DuplicatingFilterImpl;
0055: import org.jasig.portal.utils.XSLT;
0056: import org.w3c.dom.Document;
0057: import org.w3c.dom.Element;
0058: import org.w3c.dom.Node;
0059: import org.w3c.dom.NodeList;
0060: import org.xml.sax.ContentHandler;
0061:
0062: /**
0063: * This user preferences component is for use with layouts based
0064: * on the tab-column structure.
0065: * @author Ken Weiner, kweiner@unicon.net
0066: * @version $Revision: 42151 $
0067: */
0068: public class TabColumnPrefsState extends BaseState {
0069: private static final Log log = LogFactory
0070: .getLog(TabColumnPrefsState.class);
0071: protected ChannelStaticData staticData;
0072: protected ChannelRuntimeData runtimeData;
0073: private static final String sslLocation = "/org/jasig/portal/channels/CUserPreferences/tab-column/tab-column.ssl";
0074:
0075: private IUserLayoutManager ulm;
0076: private PortalControlStructures pcs;
0077: private UserPreferences userPrefs;
0078: private UserProfile editedUserProfile;
0079: private static IUserLayoutStore ulStore = UserLayoutStoreFactory
0080: .getUserLayoutStoreImpl();
0081: private StylesheetSet set;
0082:
0083: private String action = "none";
0084: private String activeTab = "none";
0085: private String elementID = "none";
0086: private String newColumnId = null;
0087:
0088: // These can be overridden in a sub-class.
0089: protected static String BLANK_TAB_NAME = "My Tab"; // The tab will take on this name if left blank by the user
0090: protected static String SKINS_PATH = "media/org/jasig/portal/layout/tab-column/nested-tables";
0091:
0092: // Here are all the possible error messages for this channel. Maybe these should be moved to
0093: // a properties file or static parameters. Actually, the error handling written so far isn't
0094: // very good and should be improved. For example, there needs to be a way to let a user know that
0095: // he/she couldn't remove a tab because it was set as unremovable.
0096: private String errorMessage = "Nothing is wrong!";
0097: private static final String errorMessageSetActiveTab = "Problem trying to set the active tab";
0098: private static final String errorMessageRenameTab = "Problem trying to rename tab";
0099: private static final String errorMessageMoveTab = "Problem trying to move the tab";
0100: private static final String errorMessageAddTab = "Problem trying to add a new tab";
0101: private static final String errorMessageDeleteTab = "Problem trying to delete tab";
0102: private static final String errorMessageLockTab = "Problem trying to lock tab";
0103: private static final String errorMessageUnlockTab = "Problem trying to unlock tab";
0104: private static final String errorMessageChangeColumnWidths = "Problem changing column widths";
0105: private static final String errorMessageMoveColumn = "Problem trying to move column";
0106: private static final String errorMessageNewColumn = "Problem trying to add a new column";
0107: private static final String errorMessageDeleteColumn = "Problem trying to delete column";
0108: private static final String errorMessageNewChannel = "Problem trying to add a new channel";
0109: private static final String errorMessageModChannelParams = "Problem trying to modify channel parameters";
0110: private static final String errorMessageMoveChannel = "Problem trying to move channel";
0111: private static final String errorMessageDeleteChannel = "Problem trying to delete channel";
0112:
0113: public TabColumnPrefsState() throws PortalException {
0114: super ();
0115: this .internalState = new DefaultState(this );
0116:
0117: // initialize stylesheet set
0118: set = new StylesheetSet(ResourceLoader.getResourceAsURLString(
0119: this .getClass(), sslLocation));
0120: }
0121:
0122: public TabColumnPrefsState(CUserPreferences context)
0123: throws PortalException {
0124: super (context);
0125: this .internalState = new DefaultState(this );
0126: // initialize stylesheet set
0127: set = new StylesheetSet(ResourceLoader.getResourceAsURLString(
0128: this .getClass(), sslLocation));
0129: }
0130:
0131: public void setStaticData(ChannelStaticData sd)
0132: throws PortalException {
0133: this .staticData = sd;
0134: this .internalState.setStaticData(sd);
0135: }
0136:
0137: public void setRuntimeData(ChannelRuntimeData rd)
0138: throws PortalException {
0139: this .runtimeData = rd;
0140:
0141: // See if a top-level action has been given
0142: String action = rd.getParameter("action");
0143: if (action != null) {
0144: if (action.equals("newChannel")) {
0145: if (!(internalState instanceof NewChannelState)) {
0146: internalState = new NewChannelState(this );
0147: internalState.setStaticData(staticData);
0148: }
0149: } else if (action.equals("manageSkins")) {
0150: if (!(internalState instanceof SelectSkinsState)) {
0151: internalState = new SelectSkinsState(this );
0152: internalState.setStaticData(staticData);
0153: }
0154: } else if (action.equals("resetLayout")) {
0155: if (!(internalState instanceof ResetLayoutState)) {
0156: internalState = new ResetLayoutState(this );
0157: internalState.setStaticData(staticData);
0158: }
0159: } else if (action.equals("managePreferences")) {
0160: internalState = new DefaultState(this );
0161: internalState.setStaticData(staticData);
0162: }
0163: }
0164: internalState.setRuntimeData(rd);
0165:
0166: try {
0167:
0168: // Need this check so that we don't override the column width's we just set
0169: if (internalState instanceof DefaultState) {
0170: if (((DefaultState) internalState).columnHasBeenAdded)
0171: return;
0172: }
0173:
0174: // The profile the user is currently viewing or modifying...
0175: editedUserProfile = context.getEditedUserProfile();
0176: ulm = getUserLayoutManager();
0177: userPrefs = context
0178: .getUserPreferencesFromStore(editedUserProfile);
0179: } catch (Exception e) {
0180: throw new GeneralRenderingException(e);
0181: }
0182: }
0183:
0184: public void setPortalControlStructures(PortalControlStructures pcs)
0185: throws PortalException {
0186: this .pcs = pcs;
0187: }
0188:
0189: public void renderXML(ContentHandler out) throws PortalException {
0190: if (this .internalState != null)
0191: this .internalState.renderXML(out);
0192: else
0193: log
0194: .error("TabColumnPrefsState::renderXML() : No internal state!");
0195: }
0196:
0197: // Helper methods...
0198:
0199: private final IUserLayoutManager getUserLayoutManager()
0200: throws Exception {
0201: IUserPreferencesManager upm = context
0202: .getUserPreferencesManager();
0203: IUserLayoutManager lm = null;
0204: // If the we are editing the current user layout, get a copy of the current user layout,
0205: // otherwise get it from the database or other persistant storage
0206: if (modifyingCurrentUserLayout()) {
0207: // get it from the preferences manager
0208: lm = upm.getUserLayoutManager();
0209: } else {
0210: // construct a new one
0211: lm = UserLayoutManagerFactory.getUserLayoutManager(upm
0212: .getPerson(), context.getCurrentUserPreferences()
0213: .getProfile());
0214: }
0215: return lm;
0216: }
0217:
0218: private final String getActiveTab() {
0219: String activeTab = "none";
0220:
0221: try {
0222: // Get the profile associated with the layout currently being modified
0223: UserPreferences userPrefsFromStore = context
0224: .getUserPreferencesFromStore(context
0225: .getCurrentUserPreferences().getProfile());
0226: activeTab = userPrefsFromStore
0227: .getStructureStylesheetUserPreferences()
0228: .getParameterValue("activeTab");
0229: } catch (Exception e) {
0230: log
0231: .error("TabColumnPrefsState::getAcctiveTab : Unable to retrieve active tab.");
0232: }
0233:
0234: return activeTab;
0235: }
0236:
0237: private final void setActiveTab(String activeTab) throws Exception {
0238: StructureStylesheetUserPreferences ssup = userPrefs
0239: .getStructureStylesheetUserPreferences();
0240: ssup.putParameterValue("activeTab", activeTab);
0241:
0242: // Persist structure stylesheet user preferences
0243: int profileId = editedUserProfile.getProfileId();
0244: ulStore.setStructureStylesheetUserPreferences(staticData
0245: .getPerson(), profileId, ssup);
0246: }
0247:
0248: private final void renameTab(String tabId, String tabName)
0249: throws PortalException {
0250: IUserLayoutFolderDescription tab = (IUserLayoutFolderDescription) ulm
0251: .getNode(tabId);
0252: if (ulm.canUpdateNode(ulm.getNode(tabId))) {
0253: if (tabName == null || tabName.trim().length() == 0) {
0254: tab.setName(BLANK_TAB_NAME);
0255: } else {
0256: tab.setName(tabName);
0257: }
0258: ulm.updateNode(tab);
0259: } else {
0260: throw new PortalException(
0261: "Attempt to rename immutable tab " + tabId
0262: + "has failed");
0263: }
0264: }
0265:
0266: private final void moveTab(String sourceTabId, String method,
0267: String destinationTabId) throws PortalException {
0268: // determine root folder id
0269: String rootNodeId = ulm.getParentId(sourceTabId);
0270:
0271: if (ulm.canMoveNode(sourceTabId, rootNodeId, destinationTabId)) {
0272: if (method.equals("insertBefore")) {
0273: ulm.moveNode(sourceTabId, rootNodeId, destinationTabId);
0274: } else {
0275: ulm.moveNode(sourceTabId, rootNodeId, null);
0276: }
0277: }
0278: }
0279:
0280: /**
0281: * Adds a new tab to the layout.
0282: * @param tabName the name of the tab
0283: * @param method either <code>insertBefore</code> or <code>appendAfter</code>
0284: * @param destinationTabId the column to insert the new column before or append after (may actually be a tab)
0285: * @throws PortalException
0286: */
0287: private final void addTab(String tabName, String method,
0288: String destinationTabId) throws PortalException {
0289:
0290: IUserLayoutFolderDescription newTab = createFolder(tabName);
0291: if (tabName == null || tabName.trim().length() == 0) {
0292: newTab.setName(BLANK_TAB_NAME);
0293: }
0294: String siblingId = null;
0295: if (method.equals("insertBefore"))
0296: siblingId = destinationTabId;
0297: ulm.addNode(newTab, ulm.getRootFolderId(), siblingId);
0298:
0299: // Add a new column to this tab
0300: IUserLayoutFolderDescription newColumn = createFolder("Column");
0301: ulm.addNode(newColumn, newTab.getId(), null);
0302: }
0303:
0304: /**
0305: * This method will remove a column from the user's layout. The column will be added into the layout
0306: * via the "add new column" link within the preferences channel. Clicking on cancel after choosing to add
0307: * a new column will not remove the column hence the introduction of this method.
0308: */
0309: private final void removeNewColumn() {
0310: try {
0311: Document doc = this .ulm.getUserLayoutDOM();
0312: Node nNewColumnNode = doc.getElementById(this .newColumnId);
0313: if (nNewColumnNode != null) {
0314: Node parent = nNewColumnNode.getParentNode();
0315: parent.removeChild(nNewColumnNode);
0316: this .newColumnId = null;
0317: }
0318: } catch (Exception e) {
0319: if (log.isDebugEnabled())
0320: log
0321: .debug("removeNewColumn failed to find new column with id "
0322: + this .newColumnId);
0323: }
0324: }
0325:
0326: /**
0327: * Adds a new column into the layout. Before the column is added,
0328: * a check is done to see whether the destination element is a tab. If it is,
0329: * a new column is inserted first.
0330: * @param method either <code>insertBefore</code> or <code>appendAfter</code>
0331: * @param destinationElementId the column to insert the new column before or append after (may actually be a tab)
0332: * @throws Exception
0333: */
0334: private final void addColumn(String method,
0335: String destinationElementId) throws Exception {
0336: IUserLayoutFolderDescription newColumn = createFolder("Column");
0337: // Insert a column if the destination element is a tab
0338: if (isTab(destinationElementId)) {
0339: ulm.addNode(newColumn, destinationElementId, null);
0340: } else if (isColumn(destinationElementId)) {
0341: String siblingId = null;
0342: if (method.equals("insertBefore")) {
0343: siblingId = destinationElementId;
0344: }
0345: // Returns the node that was just added containing the default width of 100%
0346: IUserLayoutNodeDescription ulnd = ulm.addNode(newColumn,
0347: ulm.getParentId(destinationElementId), siblingId);
0348: // Get the current users layout
0349: Document doc = this .ulm.getUserLayoutDOM();
0350: // Keep track of the new column id incase the user clicks on cancel button
0351: this .newColumnId = ulnd.getId();
0352: Element nE = (Element) doc.getElementById(ulnd.getId());
0353: // Find out how many siblings this node contains
0354: NodeList list = nE.getParentNode().getChildNodes();
0355: if (list != null && list.getLength() > 0)
0356: this .setEvenlyAssignedColumnWidths(list);
0357: }
0358: }
0359:
0360: private final void changeColumnWidths(HashMap columnWidths)
0361: throws Exception {
0362: StructureStylesheetUserPreferences ssup = userPrefs
0363: .getStructureStylesheetUserPreferences();
0364: java.util.Set sColWidths = columnWidths.keySet();
0365: java.util.Iterator iterator = sColWidths.iterator();
0366: while (iterator.hasNext()) {
0367: String folderId = (String) iterator.next();
0368: String newWidth = (String) columnWidths.get(folderId);
0369:
0370: // Only accept widths that are either percentages or integers (fixed widths)
0371: boolean widthIsValid = true;
0372: try {
0373: Integer
0374: .parseInt(newWidth.endsWith("%") ? newWidth
0375: .substring(0, newWidth.indexOf("%"))
0376: : newWidth);
0377: } catch (java.lang.NumberFormatException nfe) {
0378: widthIsValid = false;
0379: }
0380:
0381: if (widthIsValid)
0382: ssup.setFolderAttributeValue(folderId, "width",
0383: newWidth);
0384: else if (log.isDebugEnabled())
0385: log.debug("User id " + staticData.getPerson().getID()
0386: + " entered invalid column width: " + newWidth);
0387:
0388: }
0389:
0390: // Persist structure stylesheet user preferences
0391: saveUserPreferences();
0392: }
0393:
0394: /**
0395: * Moves a column from one position in the layout to another. Before the move is performed,
0396: * a check is done to see whether the source and/or destination elements are tabs. If either
0397: * is a tab, a new column is inserted between it and the channels that it contains before the
0398: * move is carried out.
0399: * @param sourceId the column to move (may actually be a tab)
0400: * @param method either <code>insertBefore</code> or <code>appendAfter</code>
0401: * @param destinationId the column to insert the new column before or append after (may actually be a tab)
0402: * @throws PortalException
0403: */
0404: private final void moveColumn(String sourceId, String method,
0405: String destinationId) throws PortalException {
0406: String siblingId = null;
0407: if (method.equals("insertBefore")) {
0408: siblingId = destinationId;
0409: }
0410: ulm.moveNode(sourceId, ulm.getParentId(destinationId),
0411: siblingId);
0412: }
0413:
0414: /**
0415: * Moves a channel from one position in the layout to another.
0416: * @param sourceChannelSubscribeId the channel to move
0417: * @param method either <code>insertBefore</code> or <code>appendAfter</code>
0418: * @param destinationElementId the ID of the channel to insert the new channel before or append after
0419: * @throws PortalException
0420: */
0421: private final void moveChannel(String sourceChannelSubscribeId,
0422: String method, String destinationElementId)
0423: throws PortalException {
0424: if (isTab(destinationElementId)) {
0425: // create a new column and move channel there
0426: IUserLayoutNodeDescription newColumn = ulm.addNode(
0427: createFolder("Column"), destinationElementId, null);
0428: ulm.moveNode(sourceChannelSubscribeId, newColumn.getId(),
0429: null);
0430: } else if (isColumn(destinationElementId)) {
0431: // move the channel into the column
0432: ulm.moveNode(sourceChannelSubscribeId,
0433: destinationElementId, null);
0434: } else {
0435: // assume that destinationElementId is that of a sibling channel
0436: String siblingId = null;
0437: if (method.equals("insertBefore")) {
0438: siblingId = destinationElementId;
0439: }
0440: ulm.moveNode(sourceChannelSubscribeId, ulm
0441: .getParentId(destinationElementId), siblingId);
0442: }
0443: }
0444:
0445: /**
0446: * Adds a channel to the layout.
0447: * @param newChannel the channel to add
0448: * @param position either <code>before</code> or <code>after</code>
0449: * @param destinationElementId the ID of the channel to insert the new channel before or append after
0450: * @throws PortalException
0451: */
0452: private final void addChannel(Element newChannel, String position,
0453: String destinationElementId) throws PortalException {
0454: IUserLayoutChannelDescription channel = new UserLayoutChannelDescription(
0455: newChannel);
0456: if (isTab(destinationElementId)) {
0457: // create a new column and move channel there
0458: IUserLayoutNodeDescription newColumn = ulm.addNode(
0459: createFolder("Column"), destinationElementId, null);
0460: ulm.addNode(channel, newColumn.getId(), null);
0461: } else if (isColumn(destinationElementId)) {
0462: // move the channel into the column
0463: ulm.addNode(channel, destinationElementId, null);
0464: } else {
0465: // assume that destinationElementId is that of a sibling channel
0466: String siblingId = null;
0467: if (position.equals("before")) {
0468: siblingId = destinationElementId;
0469: }
0470: ulm.addNode(channel, ulm.getParentId(destinationElementId),
0471: siblingId);
0472: }
0473:
0474: // Make sure ChannelManager knows about the new channel
0475: pcs.getChannelManager().instantiateChannel(channel.getId());
0476:
0477: ulm.saveUserLayout();
0478: }
0479:
0480: /**
0481: * Adds a channel to the layout.
0482: * @param selectedChannelSubscribeId the channel to add
0483: * @param position either <code>before</code> or <code>after</code>
0484: * @param destinationElementId the ID of the channel to insert the new channel before or append after
0485: * @throws Exception
0486: */
0487: private final void addChannel(String selectedChannelSubscribeId,
0488: String position, String destinationElementId)
0489: throws Exception {
0490: Document channelRegistry = ChannelRegistryManager
0491: .getChannelRegistry(staticData.getPerson());
0492: Element newChannel = channelRegistry
0493: .getElementById(selectedChannelSubscribeId);
0494: addChannel(newChannel, position, destinationElementId);
0495: }
0496:
0497: /**
0498: * Removes a channel element from the layout
0499: * @param channelSubscribeId the ID attribute of the channel to remove
0500: */
0501: private final void deleteChannel(String channelSubscribeId)
0502: throws Exception {
0503: pcs.getChannelManager().removeChannel(channelSubscribeId);
0504: deleteElement(channelSubscribeId);
0505: }
0506:
0507: /**
0508: * Removes a tab or column element from the layout. To remove
0509: * a channel element, call deleteChannel().
0510: * @param elementId the ID attribute of the element to remove
0511: */
0512: private final void deleteElement(String elementId) throws Exception {
0513: // Need to check if we are about to delete a column, if so, need to reset other columns to appropriate width's
0514: Document doc = this .ulm.getUserLayoutDOM();
0515: Element childElement = (Element) doc.getElementById(elementId);
0516: // determine if this is a column
0517: String whatIsThis = childElement.getAttribute("name");
0518: if (whatIsThis != null && whatIsThis.startsWith("Column")) {
0519: userPrefs.getStructureStylesheetUserPreferences()
0520: .removeFolder(childElement.getAttribute("ID"));
0521: // get the id of the parent (tab)
0522: String tabId = ((Element) childElement.getParentNode())
0523: .getAttribute("ID");
0524: // Found a column .. lets remove the column selected first
0525: ulm.deleteNode(elementId);
0526: // get the updated xml document
0527: doc = this .ulm.getUserLayoutDOM();
0528: // Find out how many siblings this node contains
0529: NodeList list = ((Element) doc.getElementById(tabId))
0530: .getChildNodes();
0531: if (list != null && list.getLength() > 0)
0532: this .setEvenlyAssignedColumnWidths(list);
0533: this .saveUserPreferences();
0534:
0535: } else {
0536: // this is a tab, go ahead and delete it
0537: ulm.deleteNode(elementId);
0538: }
0539: }
0540:
0541: /**
0542: * @param list as a NodeList that contains all columns in current tab
0543: */
0544: private void setEvenlyAssignedColumnWidths(NodeList list) {
0545: // Simply divide the number of columns by 100 and produce an evenly numbered column widths
0546: int columns = list.getLength();
0547: int columnSize = 100 / columns;
0548: int remainder = 100 % columns;
0549: // Traverse through the columns and reset with the new caculated value
0550: StructureStylesheetUserPreferences ssup = userPrefs
0551: .getStructureStylesheetUserPreferences();
0552: for (int i = 0; i < list.getLength(); i++) {
0553: Element c = (Element) list.item(i);
0554: String nId = c.getAttribute("ID");
0555: ssup.setFolderAttributeValue(nId, "width", (i == (list
0556: .getLength() - 1) ? columnSize + remainder + "%"
0557: : columnSize + "%"));
0558: }
0559: }
0560:
0561: private final void updateTabLock(String elementId, boolean locked)
0562: throws Exception {
0563: // NOTE: this method is to be removed soon.
0564: }
0565:
0566: /**
0567: * A folder is a tab if its parent element is the layout element
0568: * @param folderId the id of the folder in question
0569: * @return <code>true</code> if the folder is a tab, otherwise <code>false</code>
0570: */
0571: private final boolean isTab(String folderId) throws PortalException {
0572: // we could be a bit more careful here and actually check the type
0573: return ulm.getRootFolderId().equals(ulm.getParentId(folderId));
0574: }
0575:
0576: /**
0577: * A folder is a column if its parent is a tab element
0578: * @param folderId the id of the folder in question
0579: * @return <code>true</code> if the folder is a column, otherwise <code>false</code>
0580: */
0581: private final boolean isColumn(String folderId)
0582: throws PortalException {
0583: return isTab(ulm.getParentId(folderId));
0584: }
0585:
0586: /**
0587: * Creates a folder element with default attributes. This method can be used
0588: * to create a tab or a column. For tabs, pass the tab name. For column,
0589: * pass an empty String since column names aren't meaningful
0590: * @param name the tab name for tabs and an empty string for columns
0591: * @return the newly created tab or column
0592: */
0593: private final IUserLayoutFolderDescription createFolder(String name) {
0594: String id = "tbd";
0595: IUserLayoutFolderDescription folder = new UserLayoutFolderDescription();
0596: folder.setName(name);
0597: folder.setId(id);
0598: folder.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE);
0599: folder.setHidden(false);
0600: folder.setUnremovable(false);
0601: folder.setImmutable(false);
0602: return folder;
0603: }
0604:
0605: /**
0606: * Finds any parameters in a channel that are determined to be overridable
0607: * by a user.
0608: * @param channelPublishId an identifier to find the selected channel within the channel registry
0609: * @return a list of <parameter> elements whose override attribute is set to true
0610: * @throws org.jasig.portal.PortalException
0611: */
0612: private final List getOverridableChannelParams(
0613: String channelPublishId) throws PortalException {
0614: Document channelRegistry = ChannelRegistryManager
0615: .getChannelRegistry(staticData.getPerson());
0616: Element channel = (Element) channelRegistry
0617: .getElementById(channelPublishId.startsWith("chan") ? channelPublishId
0618: : "chan" + channelPublishId);
0619: List overridableParams = null;
0620:
0621: if (channel != null) {
0622: overridableParams = new ArrayList();
0623:
0624: NodeList params = channel.getElementsByTagName("parameter");
0625: for (int i = 0; i < params.getLength(); i++) {
0626: Element param = (Element) params.item(i);
0627: String override = param.getAttribute("override");
0628: if (override != null && override.equals("yes"))
0629: overridableParams.add(param);
0630: }
0631: } else {
0632: throw new PortalException("Channel " + channelPublishId
0633: + " is missing from the channel registry");
0634: }
0635: return overridableParams;
0636: }
0637:
0638: private void saveUserPreferences() throws PortalException {
0639: userPrefs.getStructureStylesheetUserPreferences()
0640: .putParameterValue("userLayoutRoot",
0641: staticData.getChannelSubscribeId());
0642: IUserPreferencesManager upm = context
0643: .getUserPreferencesManager();
0644: if (modifyingCurrentUserLayout()) {
0645: upm.setNewUserLayoutAndUserPreferences(null, userPrefs);
0646: } else {
0647: try {
0648: ulStore.putUserPreferences(staticData.getPerson(),
0649: userPrefs);
0650: } catch (Exception e) {
0651: throw new PortalException(e);
0652: }
0653: }
0654: }
0655:
0656: private boolean modifyingCurrentUserLayout() throws PortalException {
0657: // check if we're editing the same layout (note: this relies on the layout Ids to be meaningful, which
0658: // is not entirely true with the current "template user layout" feature. Hopefully this will go away soon.
0659: return (context.getUserPreferencesManager().getCurrentProfile()
0660: .getProfileId() == editedUserProfile.getProfileId() && context
0661: .getUserPreferencesManager().getCurrentProfile()
0662: .isSystemProfile() == editedUserProfile
0663: .isSystemProfile());
0664: }
0665:
0666: /**
0667: * A sub-state of TabColumnPrefsState for visualizing the user layout
0668: * in tab-column form.
0669: */
0670: protected class DefaultState extends BaseState {
0671: private static final boolean printXMLToLog = false;
0672: private boolean columnHasBeenAdded = false;
0673: protected TabColumnPrefsState context;
0674:
0675: public DefaultState(TabColumnPrefsState context) {
0676: this .context = context;
0677: }
0678:
0679: public void setRuntimeData(ChannelRuntimeData rd)
0680: throws PortalException {
0681: runtimeData = rd;
0682:
0683: // If the user hasn't clicked on a tab, get persisted active tab
0684: if (activeTab.equals("none"))
0685: activeTab = getActiveTab();
0686:
0687: action = runtimeData.getParameter("action");
0688:
0689: if (action != null) {
0690: // Select tab
0691: if (action.equals("selectTab"))
0692: activeTab = runtimeData.getParameter("activeTab");
0693: // Set active tab
0694: else if (action.equals("setActiveTab")) {
0695: try {
0696: setActiveTab(activeTab);
0697: } catch (Exception e) {
0698: log.error(e, e);
0699: action = "error";
0700: errorMessage = errorMessageSetActiveTab;
0701: }
0702: }
0703: // Rename tab
0704: else if (action.equals("renameTab")) {
0705: try {
0706: String tabId = runtimeData
0707: .getParameter("elementID");
0708: String tabName = runtimeData
0709: .getParameter("tabName");
0710:
0711: renameTab(tabId, tabName);
0712: } catch (Exception e) {
0713: log.error(e, e);
0714: action = "error";
0715: errorMessage = errorMessageRenameTab;
0716: }
0717: }
0718: // Move tab
0719: else if (action.equals("moveTab")) {
0720: try {
0721: String methodAndID = runtimeData
0722: .getParameter("method_ID");
0723:
0724: if (methodAndID != null) {
0725: String sourceTabId = runtimeData
0726: .getParameter("elementID");
0727: int indexOf_ = methodAndID.indexOf("_");
0728: String method = methodAndID.substring(0,
0729: indexOf_); // insertBefore or appendAfter
0730: String destinationTabId = methodAndID
0731: .substring(indexOf_ + 1);
0732:
0733: moveTab(sourceTabId, method,
0734: destinationTabId);
0735: } else
0736: action = "selectTab";
0737: } catch (Exception e) {
0738: log.error(e, e);
0739: action = "error";
0740: errorMessage = errorMessageMoveTab;
0741: }
0742: }
0743: // Add tab
0744: else if (action.equals("addTab")) {
0745: try {
0746: String tabName = runtimeData
0747: .getParameter("tabName");
0748: String methodAndID = runtimeData
0749: .getParameter("method_ID");
0750:
0751: if (methodAndID != null) {
0752: int indexOf_ = methodAndID.indexOf("_");
0753: String method = methodAndID.substring(0,
0754: indexOf_); // insertBefore or appendAfter
0755: String destinationTabId = methodAndID
0756: .substring(indexOf_ + 1);
0757:
0758: addTab(tabName, method, destinationTabId);
0759: } else
0760: action = "newTab";
0761: } catch (Exception e) {
0762: log.error(e, e);
0763: action = "error";
0764: errorMessage = errorMessageAddTab;
0765: }
0766: }
0767: // Delete tab
0768: else if (action.equals("deleteTab")) {
0769: try {
0770: String tabId = runtimeData
0771: .getParameter("elementID");
0772:
0773: deleteElement(tabId);
0774: } catch (Exception e) {
0775: log.error(e, e);
0776: action = "error";
0777: errorMessage = errorMessageDeleteTab;
0778: }
0779: }
0780: // Lock tab
0781: else if (action.equals("lockTab")) {
0782: try {
0783: String tabId = runtimeData
0784: .getParameter("elementID");
0785:
0786: updateTabLock(tabId, true);
0787: } catch (Exception e) {
0788: log.error(e, e);
0789: action = "error";
0790: errorMessage = errorMessageLockTab;
0791: }
0792: }
0793: // Unlock tab
0794: else if (action.equals("unlockTab")) {
0795: try {
0796: String tabId = runtimeData
0797: .getParameter("elementID");
0798:
0799: updateTabLock(tabId, false);
0800: } catch (Exception e) {
0801: log.error(e, e);
0802: action = "error";
0803: errorMessage = errorMessageUnlockTab;
0804: }
0805: }
0806: // Select column
0807: else if (action.equals("selectColumn"))
0808: elementID = runtimeData.getParameter("elementID");
0809: // Change column width(s)
0810: else if (action.equals("columnWidth")) {
0811: try {
0812: HashMap columnWidths = new HashMap();
0813: Enumeration eParams = runtimeData
0814: .getParameterNames();
0815: while (eParams.hasMoreElements()) {
0816: String param = (String) eParams
0817: .nextElement();
0818: String prefix = "columnWidth_";
0819:
0820: if (param.startsWith(prefix)) {
0821: String folderId = param
0822: .substring(prefix.length());
0823: String newWidth = runtimeData
0824: .getParameter(prefix + folderId);
0825: columnWidths.put(folderId, newWidth);
0826: }
0827: }
0828:
0829: changeColumnWidths(columnWidths);
0830: } catch (Exception e) {
0831: log.error(e, e);
0832: action = "error";
0833: errorMessage = errorMessageChangeColumnWidths;
0834: }
0835: }
0836: // Move column
0837: else if (action.equals("moveColumn")) {
0838: String activeTabParam = runtimeData
0839: .getParameter("activeTab");
0840: if (activeTabParam != null)
0841: activeTab = activeTabParam;
0842: }
0843: // Move column here
0844: else if (action.equals("moveColumnHere")) {
0845: try {
0846: // Get the source column if this is a one-step move, otherwise we already
0847: // have it stored as elementID
0848: String sourceId = runtimeData
0849: .getParameter("sourceID");
0850: if (sourceId != null)
0851: elementID = sourceId;
0852:
0853: String method = runtimeData
0854: .getParameter("method");
0855: String destinationId = runtimeData
0856: .getParameter("elementID");
0857:
0858: moveColumn(elementID, method, destinationId);
0859: } catch (Exception e) {
0860: log.error(e, e);
0861: action = "error";
0862: errorMessage = errorMessageMoveColumn;
0863: }
0864: }
0865: // New column
0866: else if (action.equals("newColumn")) {
0867: try {
0868: String method = runtimeData
0869: .getParameter("method");
0870: elementID = runtimeData
0871: .getParameter("elementID");
0872: String destinationColumnId = elementID;
0873:
0874: addColumn(method, destinationColumnId);
0875: columnHasBeenAdded = true;
0876: } catch (Exception e) {
0877: log.error(e, e);
0878: action = "error";
0879: errorMessage = errorMessageNewColumn;
0880: }
0881: }
0882: // Add column
0883: else if (action.equals("addColumn")) {
0884: // Currently not implemented...
0885: // We need to assign widths to columns.
0886: // The action addColumn isn't in the stylesheet yet.
0887: }
0888: // Delete column
0889: else if (action.equals("deleteColumn")) {
0890: try {
0891: String columnId = runtimeData
0892: .getParameter("elementID");
0893:
0894: deleteElement(columnId);
0895: } catch (Exception e) {
0896: log.error(e, e);
0897: action = "error";
0898: errorMessage = errorMessageDeleteColumn;
0899: }
0900: }
0901: // Select channel
0902: else if (action.equals("selectChannel")) {
0903: elementID = runtimeData.getParameter("elementID");
0904:
0905: // Modify channel parameters
0906: String subAction = runtimeData
0907: .getParameter("subAction");
0908: if (subAction != null
0909: && subAction.equals("modifyChannelParams")) {
0910: IUserLayoutChannelDescription layoutChannel = (IUserLayoutChannelDescription) ulm
0911: .getNode(elementID);
0912: String channelPublishId = layoutChannel
0913: .getChannelPublishId();
0914:
0915: Document channelRegistry = ChannelRegistryManager
0916: .getChannelRegistry(staticData
0917: .getPerson());
0918: Element channel = (Element) channelRegistry
0919: .getElementById("chan"
0920: + channelPublishId);
0921: List overridableChanParams = getOverridableChannelParams(channelPublishId);
0922: context.internalState = new ParametersState(
0923: context, this , overridableChanParams,
0924: channel);
0925: context.internalState.setStaticData(staticData);
0926: }
0927: }
0928: // Move channel
0929: else if (action.equals("moveChannel")) {
0930: String activeTabParam = runtimeData
0931: .getParameter("activeTab");
0932: if (activeTabParam != null)
0933: activeTab = activeTabParam;
0934: }
0935: // Move channel here
0936: else if (action.equals("moveChannelHere")) {
0937: try {
0938: // Get the source channel if this is a one-step move, otherwise we already
0939: // have it stored as elementID
0940: String sourceId = runtimeData
0941: .getParameter("sourceID");
0942: if (sourceId != null)
0943: elementID = sourceId;
0944:
0945: String method = runtimeData
0946: .getParameter("method");
0947: String destinationId = runtimeData
0948: .getParameter("elementID");
0949:
0950: moveChannel(elementID, method, destinationId);
0951:
0952: // Clear out elementId so the channel doesn't stay highlighted
0953: elementID = null;
0954: } catch (Exception e) {
0955: log.error(e, e);
0956: action = "error";
0957: errorMessage = errorMessageMoveChannel;
0958: }
0959: }
0960: // Delete channel
0961: else if (action.equals("deleteChannel")) {
0962: try {
0963: String channelSubscribeId = runtimeData
0964: .getParameter("elementID");
0965:
0966: deleteChannel(channelSubscribeId);
0967: } catch (Exception e) {
0968: log.error(e, e);
0969: action = "error";
0970: errorMessage = errorMessageDeleteChannel;
0971: }
0972: }
0973: // Cancel
0974: else if (action.equals("cancel")) {
0975: elementID = "none";
0976: // check to see if we added a new column
0977: if (columnHasBeenAdded) {
0978: removeNewColumn();
0979: columnHasBeenAdded = false;
0980: }
0981: }
0982: } else
0983: action = "none";
0984: }
0985:
0986: public void renderXML(ContentHandler out)
0987: throws PortalException {
0988: try {
0989: // Set up chain: userLayout --> Structure Attributes Incorp. Filter --> out
0990: TransformerFactory tFactory = TransformerFactory
0991: .newInstance();
0992: if (tFactory instanceof SAXTransformerFactory) {
0993: SAXTransformerFactory saxTFactory = (SAXTransformerFactory) tFactory;
0994:
0995: // Empty transformer to do the initial dom2sax transition
0996: Transformer emptytr = tFactory.newTransformer();
0997:
0998: // Stylesheet transformer
0999: String xslURI = set.getStylesheetURI("default",
1000: runtimeData.getBrowserInfo());
1001:
1002: // for i18n
1003: xslURI = LocaleAwareXSLT.getLocaleAwareXslUri(
1004: xslURI, runtimeData.getLocales(), this );
1005:
1006: TransformerHandler th = saxTFactory
1007: .newTransformerHandler(XSLT
1008: .getTemplates(ResourceLoader
1009: .getResourceAsURLString(
1010: this .getClass(),
1011: xslURI)));
1012: th.setResult(new SAXResult(out));
1013: Transformer sstr = th.getTransformer();
1014:
1015: // Set the parameters
1016: sstr.setParameter("baseActionURL", runtimeData
1017: .getBaseActionURL());
1018: sstr.setParameter("activeTab", activeTab);
1019: sstr.setParameter("action", action);
1020: sstr.setParameter("elementID",
1021: elementID != null ? elementID : "none");
1022: sstr.setParameter("errorMessage", errorMessage);
1023:
1024: StructureStylesheetUserPreferences ssup = userPrefs
1025: .getStructureStylesheetUserPreferences();
1026: StructureAttributesIncorporationFilter saif = new StructureAttributesIncorporationFilter(
1027: th, ssup);
1028:
1029: // Put a duplicating filter before th
1030: StringWriter sw = null;
1031: OutputFormat outputFormat = null;
1032: if (printXMLToLog) {
1033: sw = new StringWriter();
1034: outputFormat = new OutputFormat();
1035: outputFormat.setIndenting(true);
1036: XMLSerializer debugSerializer = new XMLSerializer(
1037: sw, outputFormat);
1038: SAX2DuplicatingFilterImpl dupFilter = new SAX2DuplicatingFilterImpl(
1039: th, debugSerializer);
1040: dupFilter.setParent(saif);
1041: }
1042:
1043: // Incorporate channel registry document into userLayout if user is in the subscribe process
1044: if (action.equals("newChannel")) {
1045: Node channelRegistry = ChannelRegistryManager
1046: .getChannelRegistry(
1047: staticData.getPerson())
1048: .getDocumentElement();
1049: // start document manually
1050: saif.startDocument();
1051: // output layout
1052: ulm.getUserLayout(new ChannelSAXStreamFilter(
1053: (ContentHandler) saif));
1054: emptytr
1055: .transform(
1056: new DOMSource(channelRegistry),
1057: new SAXResult(
1058: new ChannelSAXStreamFilter(
1059: (ContentHandler) saif)));
1060: // end document manually
1061: saif.endDocument();
1062: } else {
1063: //if (action.equals("moveChannelHere"))
1064: //System.out.println(org.jasig.portal.utils.XML.serializeNode(userLayout));
1065:
1066: // Begin SAX chain
1067: // emptytr.transform(new DOMSource(), new SAXResult(saif));
1068: ulm.getUserLayout((ContentHandler) saif);
1069: }
1070:
1071: // Debug piece to print out the recorded pre-structure transformation XML
1072: if (printXMLToLog) {
1073: log
1074: .debug("TablColumnPrefsState::renderXML() : XML incoming to the structure transformation :\n\n"
1075: + sw.toString() + "\n\n");
1076: }
1077:
1078: } else {
1079: log
1080: .error("TablColumnPrefsState::renderXML() : Unable to obtain SAX Transformer Factory ! Check your TRAX configuration.");
1081: }
1082: } catch (Exception e) {
1083: log.error(e, e);
1084: throw new GeneralRenderingException(e);
1085: }
1086: }
1087: }
1088:
1089: /**
1090: * A sub-state of TabColumnPrefsState for resetting layout
1091: */
1092: protected class ResetLayoutState extends BaseState {
1093: protected TabColumnPrefsState context;
1094:
1095: public ResetLayoutState(TabColumnPrefsState context) {
1096: this .context = context;
1097: }
1098:
1099: public void setRuntimeData(ChannelRuntimeData rd)
1100: throws PortalException {
1101: try {
1102: editedUserProfile.setLayoutId(0);
1103: ulStore.updateUserProfile(staticData.getPerson(),
1104: editedUserProfile);
1105: ulm.loadUserLayout();
1106: } catch (Exception e) {
1107: throw new PortalException(e);
1108: }
1109: // return to the default state
1110: BaseState df = new DefaultState(context);
1111: df.setStaticData(staticData);
1112: context.setState(df);
1113: }
1114: }
1115:
1116: /**
1117: * A sub-state of TabColumnPrefsState for selecting skins
1118: */
1119: protected class SelectSkinsState extends BaseState {
1120: protected TabColumnPrefsState context;
1121:
1122: public SelectSkinsState(TabColumnPrefsState context) {
1123: this .context = context;
1124: }
1125:
1126: public void setRuntimeData(ChannelRuntimeData rd)
1127: throws PortalException {
1128: runtimeData = rd;
1129: String action = runtimeData.getParameter("action");
1130: if (action != null) {
1131: if (runtimeData.getParameter("submitSave") != null) {
1132: // save
1133: String skinName = runtimeData
1134: .getParameter("skinName");
1135: userPrefs.getThemeStylesheetUserPreferences()
1136: .putParameterValue("skin", skinName);
1137: // save user preferences
1138: saveUserPreferences();
1139: // reset state
1140: BaseState df = new DefaultState(context);
1141: df.setStaticData(staticData);
1142: context.setState(df);
1143: } else if (runtimeData.getParameter("submitCancel") != null) {
1144: // return to the default state
1145: BaseState df = new DefaultState(context);
1146: df.setStaticData(staticData);
1147: context.setState(df);
1148: }
1149: }
1150: }
1151:
1152: public void renderXML(ContentHandler out)
1153: throws PortalException {
1154: InputStream xmlStream = null;
1155: try {
1156: xmlStream = PortalSessionManager
1157: .getResourceAsStream(SKINS_PATH
1158: + "/skinList.xml");
1159: String currentSkin = userPrefs
1160: .getThemeStylesheetUserPreferences()
1161: .getParameterValue("skin");
1162:
1163: XSLT xslt = XSLT.getTransformer(this , runtimeData
1164: .getLocales());
1165: xslt.setXML(xmlStream);
1166: xslt.setXSL(sslLocation, "skinList", runtimeData
1167: .getBrowserInfo());
1168: xslt.setTarget(out);
1169: xslt.setStylesheetParameter("skinsPath", SKINS_PATH);
1170: xslt.setStylesheetParameter("baseActionURL",
1171: runtimeData.getBaseActionURL());
1172: if (currentSkin != null)
1173: xslt.setStylesheetParameter("currentSkin",
1174: currentSkin);
1175: xslt.transform();
1176: } finally {
1177: try {
1178: if (xmlStream != null)
1179: xmlStream.close();
1180: } catch (IOException exception) {
1181: log
1182: .error(
1183: "TabColumnPrefsState:renderXML()::unable to close InputStream ",
1184: exception);
1185: }
1186: }
1187: }
1188: }
1189:
1190: /**
1191: * A sub-state of TabColumnPrefsState for choosing a new channel (formerly subscribe)
1192: */
1193: protected class NewChannelState extends BaseState {
1194: protected TabColumnPrefsState context;
1195: private String position = "none";
1196: private String catID = "top";
1197:
1198: public NewChannelState(TabColumnPrefsState context) {
1199: this .context = context;
1200: }
1201:
1202: public void setRuntimeData(ChannelRuntimeData rd)
1203: throws PortalException {
1204: runtimeData = rd;
1205: String action = runtimeData.getParameter("action");
1206: if (action != null) {
1207: if (action.equals("cancel")) {
1208: returnToDefaultState();
1209: } else {
1210: // User clicked "?"
1211: if (runtimeData.getParameter("channelMoreInfo") != null) {
1212: // Implement channel preview here!
1213: String selectedChannel = runtimeData
1214: .getParameter("selectedChannel");
1215: // Do more...
1216: } else if (runtimeData.getParameter("addChannel") != null) {
1217: // User clicked "Add"
1218: String selectedChannel = runtimeData
1219: .getParameter("selectedChannel");
1220: if (selectedChannel != null) {
1221: try {
1222: // Determine whether channel has overridable parameters
1223: List overridableChanParams = getOverridableChannelParams(selectedChannel);
1224: if (overridableChanParams.isEmpty()) {
1225: addChannel(selectedChannel,
1226: position, elementID);
1227: returnToDefaultState();
1228: } else { // present user with screen to specify subscribe-time params
1229: Document channelRegistry = ChannelRegistryManager
1230: .getChannelRegistry(staticData
1231: .getPerson());
1232: Element channel = (Element) channelRegistry
1233: .getElementById(selectedChannel);
1234: context.internalState = new ParametersState(
1235: context, this ,
1236: overridableChanParams,
1237: channel, position,
1238: elementID);
1239: context.internalState
1240: .setStaticData(staticData);
1241: }
1242: } catch (Exception e) {
1243: errorMessage = errorMessageNewChannel;
1244: }
1245: }
1246: } else {
1247: // Collect the position and element ID the first time
1248: String passedPosition = runtimeData
1249: .getParameter("position");
1250: String passedElementID = runtimeData
1251: .getParameter("elementID");
1252: if (passedPosition != null)
1253: position = passedPosition;
1254: if (passedElementID != null)
1255: elementID = passedElementID;
1256:
1257: // User clicked "Go"
1258: String selectedCategory = runtimeData
1259: .getParameter("selectedCategory");
1260: if (selectedCategory != null
1261: && selectedCategory.trim().length() > 0)
1262: catID = selectedCategory;
1263: }
1264: }
1265: }
1266: }
1267:
1268: public void renderXML(ContentHandler out)
1269: throws PortalException {
1270: Document doc = ChannelRegistryManager
1271: .getChannelRegistry(staticData.getPerson());
1272:
1273: XSLT xslt = XSLT.getTransformer(this , runtimeData
1274: .getLocales());
1275: xslt.setXML(doc);
1276: xslt.setXSL(sslLocation, "newChannel", runtimeData
1277: .getBrowserInfo());
1278: xslt.setTarget(out);
1279: xslt.setStylesheetParameter("baseActionURL", runtimeData
1280: .getBaseActionURL());
1281: xslt.setStylesheetParameter("elementID", elementID);
1282: xslt.setStylesheetParameter("position", position);
1283: xslt.setStylesheetParameter("catID", catID);
1284: xslt.setStylesheetParameter("errorMessage", errorMessage);
1285: xslt.transform();
1286: }
1287:
1288: private void returnToDefaultState() throws PortalException {
1289: // Reset global variables
1290: elementID = "none";
1291: position = "none";
1292: action = "none";
1293:
1294: BaseState defaultState = new DefaultState(context);
1295: defaultState.setStaticData(staticData);
1296: context.setState(defaultState);
1297: }
1298: }
1299:
1300: /**
1301: * A sub-state of TabColumnPrefsState for setting channel parameters
1302: */
1303: protected class ParametersState extends BaseState {
1304: protected TabColumnPrefsState context;
1305: protected BaseState previousState;
1306: private List overridableChanParams;
1307: private Element registryChannel;
1308: private String position;
1309: private String destinationElementId;
1310:
1311: private boolean error = false;
1312:
1313: public ParametersState(TabColumnPrefsState context,
1314: BaseState previousState, List overridableChanParams,
1315: Element registryChannel) {
1316: this .context = context;
1317: this .previousState = previousState;
1318: this .overridableChanParams = overridableChanParams;
1319: this .registryChannel = registryChannel;
1320: }
1321:
1322: public ParametersState(TabColumnPrefsState context,
1323: BaseState previousState, List overridableChanParams,
1324: Element registryChannel, String position,
1325: String destinationElementId) {
1326: this (context, previousState, overridableChanParams,
1327: registryChannel);
1328: this .position = position;
1329: this .destinationElementId = destinationElementId;
1330: }
1331:
1332: public void setRuntimeData(ChannelRuntimeData rd)
1333: throws PortalException {
1334: runtimeData = rd;
1335: String action = runtimeData.getParameter("uPTCUP_action");
1336: if (action != null) {
1337: if (action.equals("back")) {
1338: context.setState(previousState);
1339: } else if (action.equals("finished")) {
1340: applyChanges(); // Add or modify the channel
1341: returnToDefaultState();
1342: } else if (action.equals("cancel")) {
1343: returnToDefaultState();
1344: }
1345: }
1346: }
1347:
1348: public void renderXML(ContentHandler out)
1349: throws PortalException {
1350: XSLT xslt = XSLT.getTransformer(this , runtimeData
1351: .getLocales());
1352: xslt.setXML(getParametersDoc());
1353: xslt.setXSL(sslLocation, "parameters", runtimeData
1354: .getBrowserInfo());
1355: xslt.setTarget(out);
1356: xslt.setStylesheetParameter("baseActionURL", runtimeData
1357: .getBaseActionURL());
1358: if (error)
1359: xslt.setStylesheetParameter("errorMessage",
1360: errorMessage);
1361: xslt.transform();
1362: }
1363:
1364: private void returnToDefaultState() throws PortalException {
1365: // Reset global variables
1366: elementID = "none";
1367: position = "none";
1368: action = "none";
1369:
1370: BaseState defaultState = new DefaultState(context);
1371: defaultState.setStaticData(staticData);
1372: context.setState(defaultState);
1373: }
1374:
1375: private void applyChanges() {
1376: // Finally, add the channel to the layout or modify it if it is already there
1377: try {
1378: if (previousState instanceof NewChannelState) {
1379: processParams(registryChannel);
1380: context.addChannel(registryChannel, position,
1381: destinationElementId);
1382: } else if (previousState instanceof DefaultState) {
1383: updateParams((IUserLayoutChannelDescription) ulm
1384: .getNode(elementID));
1385: }
1386:
1387: } catch (Exception e) {
1388: error = true;
1389: errorMessage = errorMessageModChannelParams;
1390: }
1391: }
1392:
1393: private void updateParams(IUserLayoutChannelDescription cd)
1394: throws PortalException {
1395: // Process params
1396: Iterator iter = overridableChanParams.iterator();
1397: while (iter.hasNext()) {
1398: Element parameterE = (Element) iter.next();
1399: String paramName = parameterE.getAttribute("name");
1400: String paramValue = runtimeData.getParameter(paramName);
1401: cd.setParameterValue(paramName, paramValue);
1402: }
1403: ulm.updateNode(cd);
1404: }
1405:
1406: private void processParams(Element channel) {
1407: // Process params
1408: Iterator iter = overridableChanParams.iterator();
1409: while (iter.hasNext()) {
1410: Element parameterE = (Element) iter.next();
1411: String paramName = parameterE.getAttribute("name");
1412: String paramValue = runtimeData.getParameter(paramName);
1413:
1414: // Find param within channel and update it
1415: NodeList params = channel
1416: .getElementsByTagName("parameter");
1417: for (int i = 0; i < params.getLength(); i++) {
1418: Element paramE = (Element) params.item(i);
1419: if (paramE.getAttribute("name").equals(paramName)) {
1420: paramE.setAttribute("value", paramValue);
1421: break;
1422: }
1423: }
1424: }
1425: }
1426:
1427: private Document getParametersDoc() throws PortalException {
1428: Document doc = DocumentFactory.getNewDocument();
1429:
1430: // Top-level element
1431: Element userPrefParamsE = doc
1432: .createElement("userPrefParams");
1433:
1434: if (previousState instanceof NewChannelState)
1435: userPrefParamsE.appendChild(doc.importNode(
1436: registryChannel, true));
1437: else if (previousState instanceof DefaultState) {
1438: IUserLayoutNodeDescription node = ulm
1439: .getNode(elementID);
1440: userPrefParamsE.appendChild(node.getXML(doc));
1441: }
1442:
1443: // CPD
1444: Document cpd = ChannelRegistryManager
1445: .getCPD(registryChannel.getAttribute("typeID"));
1446: if (cpd != null)
1447: userPrefParamsE.appendChild(doc.importNode(cpd
1448: .getDocumentElement(), true));
1449:
1450: doc.appendChild(userPrefParamsE);
1451: return doc;
1452: }
1453: }
1454:
1455: }
|