001: /* Copyright 2001 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.channels.UserPreferences;
007:
008: import java.io.StringWriter;
009: import java.util.Enumeration;
010: import java.util.Hashtable;
011:
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014: import org.jasig.portal.ChannelRuntimeData;
015: import org.jasig.portal.GeneralRenderingException;
016: import org.jasig.portal.IPrivilegedChannel;
017: import org.jasig.portal.IUserPreferencesManager;
018: import org.jasig.portal.PortalControlStructures;
019: import org.jasig.portal.PortalException;
020: import org.jasig.portal.ResourceMissingException;
021: import org.jasig.portal.StructureStylesheetDescription;
022: import org.jasig.portal.StructureStylesheetUserPreferences;
023: import org.jasig.portal.StylesheetSet;
024: import org.jasig.portal.ThemeStylesheetDescription;
025: import org.jasig.portal.ThemeStylesheetUserPreferences;
026: import org.jasig.portal.UserPreferences;
027: import org.jasig.portal.UserProfile;
028: import org.jasig.portal.layout.IUserLayout;
029: import org.jasig.portal.layout.IUserLayoutManager;
030: import org.jasig.portal.layout.IUserLayoutStore;
031: import org.jasig.portal.layout.UserLayoutManagerFactory;
032: import org.jasig.portal.layout.UserLayoutStoreFactory;
033: import org.jasig.portal.layout.node.IUserLayoutChannelDescription;
034: import org.jasig.portal.layout.node.IUserLayoutNodeDescription;
035: import org.jasig.portal.utils.DocumentFactory;
036: import org.jasig.portal.utils.XSLT;
037: import org.w3c.dom.Document;
038: import org.w3c.dom.Element;
039: import org.xml.sax.ContentHandler;
040:
041: import org.apache.xml.serialize.OutputFormat;
042: import org.apache.xml.serialize.XMLSerializer;
043:
044: /** <p>Manages User Layout and user stylesheet preferences </p>
045: * This is a general UserPreference component. A structure/theme
046: * stylesheet is expected to replace this component with its own
047: * class to make layout/stylesheet preference management more
048: * intuitive.
049: * @author Ken Weiner, kweiner@unicon.net
050: * @author Peter Kharchenko, pkharchenko@unicon.net
051: * @version $Revision: 36729 $
052: */
053: class GPreferencesState extends BaseState {
054: private static final Log log = LogFactory
055: .getLog(GPreferencesState.class);
056: private UserProfile profile;
057: protected ChannelRuntimeData runtimeData;
058: private UserPreferences up = null;
059: private IUserLayoutManager ulm = null;
060: ThemeStylesheetDescription tsd = null;
061: StructureStylesheetDescription ssd = null;
062: protected IUserLayoutStore ulsdb = UserLayoutStoreFactory
063: .getUserLayoutStoreImpl();
064: // these state variables are kept for the use by the internalStates
065:
066: // just a way to refer to the layout element since it doesn't have an ID attribute
067: private String folderID = IUserLayout.ROOT_NODE_NAME;
068: private boolean modified = false; // becomes true after user makes changes to layout
069:
070: /**
071: * Check if the user layout or preferences have been modified.
072: *
073: * @return a <code>boolean</code> value
074: */
075: protected boolean isModified() {
076: return modified;
077: }
078:
079: /**
080: * Set modification state
081: *
082: * @param mod a <code>boolean</code> value
083: */
084: protected void setModified(boolean mod) {
085: this .modified = mod;
086: }
087:
088: /**
089: * Set current folderId.
090: *
091: * @param id a <code>String</code> value
092: */
093: protected void setFolderID(String id) {
094: this .folderID = id;
095: if (folderID == null)
096: folderID = IUserLayout.ROOT_NODE_NAME;
097: }
098:
099: /**
100: * Obtain current folderId
101: *
102: * @return a <code>String</code> value
103: */
104: protected String getFolderID() {
105: if (folderID == null)
106: folderID = IUserLayout.ROOT_NODE_NAME;
107: return this .folderID;
108: }
109:
110: protected String getLayoutRootID() {
111: return IUserLayout.ROOT_NODE_NAME;
112: }
113:
114: public GPreferencesState() {
115: super ();
116: this .internalState = new GBrowseState(this );
117: ulsdb = UserLayoutStoreFactory.getUserLayoutStoreImpl();
118: }
119:
120: /**
121: * Creates a new <code>GPreferencesState</code> for a given context.
122: *
123: * @param context a <code>CUserPreferences</code> value
124: */
125: public GPreferencesState(CUserPreferences context) {
126: super (context);
127: this .internalState = new GBrowseState(this );
128: }
129:
130: public GPreferencesState(CUserPreferences context, UserProfile p) {
131: this .profile = p;
132: // initialize in a browse state
133: this .internalState = new GBrowseState(this );
134: }
135:
136: protected IUserLayoutManager getUserLayoutManager()
137: throws PortalException {
138: if (this .ulm == null) {
139: IUserPreferencesManager upm = context
140: .getUserPreferencesManager();
141: // If the we are editing the current user layout, get a copy of the current user layout,
142: // otherwise get it from the database or other persistant storage
143: if (modifyingCurrentUserLayout()) {
144: // get it from the preferences manager
145: this .ulm = upm.getUserLayoutManager();
146: } else {
147: // construct a new one
148: this .ulm = UserLayoutManagerFactory
149: .getUserLayoutManager(upm.getPerson(), context
150: .getCurrentUserPreferences()
151: .getProfile());
152: }
153: }
154: return this .ulm;
155: }
156:
157: private boolean modifyingCurrentUserLayout() throws PortalException {
158: // check if we're editing the same layout (note: this relies on the layout Ids to be meaningful, which
159: // is not entirely true with the current "template user layout" feature. Hopefully this will go away soon.
160: // return (context.getUserPreferencesManager().getCurrentProfile().getProfileId()==context.getEditedUserProfile().getProfileId() && context.getUserPreferencesManager().getCurrentProfile().isSystemProfile()==context.getEditedUserProfile().isSystemProfile());
161: return (context.getUserPreferencesManager().getCurrentProfile()
162: .getLayoutId() == context.getEditedUserProfile()
163: .getLayoutId());
164: }
165:
166: protected IUserPreferencesManager getUserPreferencesManager() {
167: return context.getUserPreferencesManager();
168: }
169:
170: protected UserPreferences getUserPreferences()
171: throws ResourceMissingException, PortalException {
172: if (up == null) {
173: // load UserPreferences from the DB
174: try {
175: up = ulsdb.getUserPreferences(context
176: .getUserPreferencesManager().getPerson(), this
177: .getProfile());
178: up.synchronizeWithUserLayoutXML(this
179: .getUserLayoutManager().getUserLayoutDOM());
180: } catch (Exception e) {
181: throw new PortalException(e);
182: }
183: }
184: return up;
185: }
186:
187: protected ThemeStylesheetDescription getThemeStylesheetDescription()
188: throws PortalException {
189: if (tsd == null) {
190: ThemeStylesheetUserPreferences ssup = up
191: .getThemeStylesheetUserPreferences();
192: try {
193: tsd = ulsdb.getThemeStylesheetDescription(ssup
194: .getStylesheetId());
195: } catch (Exception e) {
196: throw new PortalException(e);
197: }
198: }
199: return tsd;
200: }
201:
202: protected StructureStylesheetDescription getStructureStylesheetDescription()
203: throws ResourceMissingException, PortalException {
204: if (ssd == null) {
205: StructureStylesheetUserPreferences fsup = this
206: .getUserPreferences()
207: .getStructureStylesheetUserPreferences();
208: try {
209: ssd = ulsdb.getStructureStylesheetDescription(fsup
210: .getStylesheetId());
211: } catch (Exception e) {
212: throw new PortalException(e);
213: }
214: }
215: return ssd;
216: }
217:
218: public void setPortalControlStructures(PortalControlStructures pcs)
219: throws PortalException {
220: if (this .internalState != null) {
221: this .internalState.setPortalControlStructures(pcs);
222: }
223: }
224:
225: protected StylesheetSet getStylesheetSet() {
226: return context.getStylesheetSet();
227: }
228:
229: protected UserProfile getProfile() {
230: if (profile == null)
231: profile = context.getUserPreferencesManager()
232: .getCurrentProfile();
233: return profile;
234: }
235:
236: public void setRuntimeData(ChannelRuntimeData rd)
237: throws PortalException {
238: this .runtimeData = rd;
239: String action = runtimeData.getParameter("action");
240: if (action != null) {
241: if (action.equals("submitEditChoice")) {
242: String manageTarget = runtimeData
243: .getParameter("userPreferencesAction");
244: if (manageTarget.equals("layout")) {
245: this .folderID = this .getLayoutRootID();
246: // browse mode
247: GBrowseState bstate = new GBrowseState(this );
248: bstate.setRuntimeData(rd);
249: this .internalState = bstate;
250: } else if (manageTarget.equals("gpref")) {
251: // invoke gpref mode
252: GGlobalPrefsState pstate = new GGlobalPrefsState(
253: this );
254: pstate.setRuntimeData(rd);
255: this .internalState = pstate;
256: }
257: }
258: }
259:
260: if (this .internalState != null) {
261: this .internalState.setRuntimeData(rd);
262: }
263: }
264:
265: public void renderXML(ContentHandler out) throws PortalException {
266: if (this .internalState != null) {
267: this .internalState.renderXML(out);
268: } else {
269: log
270: .error("CUserPreferences.GPreferencesState::renderXML() : no internal state !");
271: }
272: }
273:
274: protected class GEditLayoutItemState extends BaseState {
275: protected GPreferencesState context;
276: private String editElementID;
277:
278: public GEditLayoutItemState(GPreferencesState context) {
279: this .context = context;
280: }
281:
282: public void setRuntimeData(ChannelRuntimeData rd)
283: throws PortalException {
284: String action = runtimeData.getParameter("action");
285: if (action != null) {
286: if (action.equals("editElement")) {
287: editElementID = runtimeData
288: .getParameter("folderID");
289: } else if (action.equals("submitEditValues")) {
290: String submit = runtimeData.getParameter("submit");
291: if (submit.equals("Cancel")) {
292: // return to the browse state
293: IPrivilegedChannel bstate = new GBrowseState(
294: context);
295: bstate.setRuntimeData(rd);
296: context.setState(bstate);
297: } else if (submit.equals("Save")) {
298: prepareSaveEditedItem();
299: }
300: }
301: }
302: }
303:
304: private void prepareSaveEditedItem() throws PortalException {
305: // update node name
306: IUserLayoutNodeDescription node = getUserLayoutManager()
307: .getNode(editElementID);
308: node.setName(runtimeData.getParameter("name"));
309: getUserLayoutManager().updateNode(node);
310:
311: // reset the name
312: if (node instanceof IUserLayoutChannelDescription) {
313: // target is a channel
314: StructureStylesheetUserPreferences ssup = context
315: .getUserPreferences()
316: .getStructureStylesheetUserPreferences();
317: for (Enumeration ce = ssup.getChannelAttributeNames(); ce
318: .hasMoreElements();) {
319: String atName = (String) ce.nextElement();
320: String atValue = runtimeData.getParameter(atName);
321: if (atValue.equals(context
322: .getStructureStylesheetDescription()
323: .getChannelAttributeDefaultValue(atName))) {
324: atValue = null;
325: }
326:
327: ssup.setChannelAttributeValue(editElementID,
328: atName, atValue);
329: }
330: ThemeStylesheetUserPreferences tsup = context
331: .getUserPreferences()
332: .getThemeStylesheetUserPreferences();
333: for (Enumeration ca = tsup.getChannelAttributeNames(); ca
334: .hasMoreElements();) {
335: String atName = (String) ca.nextElement();
336: String atValue = runtimeData.getParameter(atName);
337: if (atValue.equals(context
338: .getThemeStylesheetDescription()
339: .getChannelAttributeDefaultValue(atName))) {
340: atValue = null;
341: }
342: tsup.setChannelAttributeValue(editElementID,
343: atName, atValue);
344: }
345: } else {
346: // target is a folder
347: StructureStylesheetUserPreferences ssup = context
348: .getUserPreferences()
349: .getStructureStylesheetUserPreferences();
350: for (Enumeration fe = ssup.getFolderAttributeNames(); fe
351: .hasMoreElements();) {
352: String atName = (String) fe.nextElement();
353: String atValue = runtimeData.getParameter(atName);
354: if (atValue.equals(context
355: .getStructureStylesheetDescription()
356: .getFolderAttributeDefaultValue(atName))) {
357: atValue = null;
358: }
359: ssup.setFolderAttributeValue(editElementID, atName,
360: atValue);
361: }
362: }
363: context.setModified(true);
364: // get back to browse mode
365: IPrivilegedChannel bstate = new GBrowseState(context);
366: bstate.setRuntimeData(runtimeData);
367: context.setState(bstate);
368: }
369:
370: public void renderXML(ContentHandler out)
371: throws PortalException {
372: IUserLayoutNodeDescription node = getUserLayoutManager()
373: .getNode(editElementID);
374: String elType = "folder";
375: if (node instanceof IUserLayoutChannelDescription) {
376: elType = "channel";
377: }
378:
379: // construct the descriptive XML
380: Document doc = DocumentFactory.getNewDocument();
381: Element edEl = doc.createElement("editelement");
382: Element typeEl = doc.createElement("type");
383: if (elType.equals("folder")) {
384: typeEl.appendChild(doc.createTextNode("folder"));
385: } else {
386: typeEl.appendChild(doc.createTextNode("channel"));
387: }
388:
389: edEl.appendChild(typeEl);
390: Element nameEl = doc.createElement("name");
391: nameEl.appendChild(doc.createTextNode(node.getName()));
392: edEl.appendChild(nameEl);
393: // determine element type
394: if (elType.equals("folder")) {
395: // target is a folder
396: StructureStylesheetUserPreferences ssup = context
397: .getUserPreferences()
398: .getStructureStylesheetUserPreferences();
399: Element saEl = doc.createElement("structureattributes");
400: for (Enumeration fe = ssup.getFolderAttributeNames(); fe
401: .hasMoreElements();) {
402: Element atEl = doc.createElement("attribute");
403: Element atNameEl = doc.createElement("name");
404: String atName = (String) fe.nextElement();
405: atNameEl.appendChild(doc.createTextNode(atName));
406: atEl.appendChild(atNameEl);
407: Element valueEl = doc.createElement("value");
408: String value = ssup.getFolderAttributeValue(
409: editElementID, atName);
410: if (value == null) {
411: // set the default value
412: value = context
413: .getStructureStylesheetDescription()
414: .getFolderAttributeDefaultValue(atName);
415: }
416: valueEl.appendChild(doc.createTextNode(value));
417: atEl.appendChild(valueEl);
418: Element descrEl = doc.createElement("description");
419: descrEl
420: .appendChild(doc
421: .createTextNode(context
422: .getStructureStylesheetDescription()
423: .getFolderAttributeWordDescription(
424: atName)));
425: atEl.appendChild(descrEl);
426: saEl.appendChild(atEl);
427: }
428: edEl.appendChild(saEl);
429: } else if (elType.equals("channel")) {
430: // target is a channel
431: StructureStylesheetUserPreferences ssup = context
432: .getUserPreferences()
433: .getStructureStylesheetUserPreferences();
434: Element saEl = doc.createElement("structureattributes");
435: for (Enumeration ce = ssup.getChannelAttributeNames(); ce
436: .hasMoreElements();) {
437: Element atEl = doc.createElement("attribute");
438: Element atNameEl = doc.createElement("name");
439: String atName = (String) ce.nextElement();
440: atNameEl.appendChild(doc.createTextNode(atName));
441: atEl.appendChild(atNameEl);
442: Element valueEl = doc.createElement("value");
443: String value = ssup.getChannelAttributeValue(
444: editElementID, atName);
445: if (value == null) {
446: value = context
447: .getStructureStylesheetDescription()
448: .getChannelAttributeDefaultValue(atName);
449: }
450: valueEl.appendChild(doc.createTextNode(value));
451: atEl.appendChild(valueEl);
452: Element descrEl = doc.createElement("description");
453: descrEl
454: .appendChild(doc
455: .createTextNode(context
456: .getStructureStylesheetDescription()
457: .getChannelAttributeWordDescription(
458: atName)));
459: atEl.appendChild(descrEl);
460: saEl.appendChild(atEl);
461: }
462: edEl.appendChild(saEl);
463: ThemeStylesheetUserPreferences tsup = context
464: .getUserPreferences()
465: .getThemeStylesheetUserPreferences();
466: Element taEl = doc.createElement("themeattributes");
467: for (Enumeration ce = tsup.getChannelAttributeNames(); ce
468: .hasMoreElements();) {
469: Element atEl = doc.createElement("attribute");
470: Element atNameEl = doc.createElement("name");
471: String atName = (String) ce.nextElement();
472: atNameEl.appendChild(doc.createTextNode(atName));
473: atEl.appendChild(atNameEl);
474: Element valueEl = doc.createElement("value");
475: String value = tsup.getChannelAttributeValue(
476: editElementID, atName);
477: if (value == null) {
478: value = context
479: .getThemeStylesheetDescription()
480: .getChannelAttributeDefaultValue(atName);
481: }
482: valueEl.appendChild(doc.createTextNode(value));
483: atEl.appendChild(valueEl);
484: Element descrEl = doc.createElement("description");
485: descrEl
486: .appendChild(doc
487: .createTextNode(context
488: .getThemeStylesheetDescription()
489: .getChannelAttributeWordDescription(
490: atName)));
491: atEl.appendChild(descrEl);
492: taEl.appendChild(atEl);
493: }
494: edEl.appendChild(taEl);
495: }
496: doc.appendChild(edEl);
497: // debug printout of the prepared xml
498: try {
499: StringWriter outString = new StringWriter();
500: /* TODO: This should be reviewed at some point to see if we can use the
501: * DOM3 LS capability and hence a standard way of doing this rather
502: * than using an internal implementation class.
503: */
504: OutputFormat format = new OutputFormat();
505: format.setOmitXMLDeclaration(true);
506: format.setIndenting(true);
507: XMLSerializer xsl = new XMLSerializer(outString, format);
508: xsl.serialize(doc);
509: log.debug(outString.toString());
510: } catch (Exception e) {
511: log.debug(e, e);
512: }
513: StylesheetSet set = context.getStylesheetSet();
514: if (set == null) {
515: throw new GeneralRenderingException(
516: "Unable to determine the stylesheet list");
517: }
518: String xslURI = set.getStylesheetURI("editItem",
519: runtimeData.getBrowserInfo());
520: if (xslURI != null) {
521: XSLT xslt = XSLT.getTransformer(this , runtimeData
522: .getLocales());
523: xslt.setXML(doc);
524: xslt.setXSL(this .getClass().getResource(xslURI)
525: .toString());
526: xslt.setTarget(out);
527: xslt.setStylesheetParameter("baseActionURL",
528: runtimeData.getBaseActionURL());
529: xslt.transform();
530: } else {
531: throw new ResourceMissingException("", "stylesheet",
532: "Unable to find stylesheet to display content for this media");
533: }
534: }
535: }
536:
537: protected class GGlobalPrefsState extends BaseState {
538: ChannelRuntimeData runtimeData;
539: protected GPreferencesState context;
540:
541: public GGlobalPrefsState(GPreferencesState context) {
542: this .context = context;
543: }
544:
545: public void setRuntimeData(ChannelRuntimeData rd)
546: throws PortalException {
547: this .runtimeData = rd;
548: // internal state handling
549: String action = runtimeData.getParameter("action");
550: if (action != null) {
551: if (action.equals("submitEditValues")) {
552: String submit = runtimeData.getParameter("submit");
553: if (submit == null || submit.equals("Save")) {
554: prepareSaveEditGPrefs();
555: } else if (submit.equals("Cancel")) {
556: IPrivilegedChannel bstate = new GBrowseState(
557: context);
558: bstate.setRuntimeData(runtimeData);
559: context.setState(bstate);
560: }
561: }
562: }
563: }
564:
565: public void renderXML(ContentHandler out)
566: throws PortalException {
567: // construct gpref XML
568: Document doc = DocumentFactory.getNewDocument();
569: Element edEl = doc.createElement("gpref");
570: StructureStylesheetUserPreferences ssup = context
571: .getUserPreferences()
572: .getStructureStylesheetUserPreferences();
573: Element spEl = doc.createElement("structureparameters");
574: for (Enumeration e = context
575: .getStructureStylesheetDescription()
576: .getStylesheetParameterNames(); e.hasMoreElements();) {
577: Element atEl = doc.createElement("parameter");
578: Element atNameEl = doc.createElement("name");
579: String atName = (String) e.nextElement();
580: atNameEl.appendChild(doc.createTextNode(atName));
581: atEl.appendChild(atNameEl);
582: Element valueEl = doc.createElement("value");
583: String value = ssup.getParameterValue(atName);
584: if (value == null) {
585: // set the default value
586: value = context.getStructureStylesheetDescription()
587: .getStylesheetParameterDefaultValue(atName);
588: }
589: valueEl.appendChild(doc.createTextNode(value));
590: atEl.appendChild(valueEl);
591: Element descrEl = doc.createElement("description");
592: descrEl
593: .appendChild(doc.createTextNode(context
594: .getStructureStylesheetDescription()
595: .getStylesheetParameterWordDescription(
596: atName)));
597: atEl.appendChild(descrEl);
598: spEl.appendChild(atEl);
599: }
600: edEl.appendChild(spEl);
601: ThemeStylesheetUserPreferences tsup = context
602: .getUserPreferences()
603: .getThemeStylesheetUserPreferences();
604: Element tpEl = doc.createElement("themeparameters");
605: for (Enumeration e = context
606: .getThemeStylesheetDescription()
607: .getStylesheetParameterNames(); e.hasMoreElements();) {
608: Element atEl = doc.createElement("parameter");
609: Element atNameEl = doc.createElement("name");
610: String atName = (String) e.nextElement();
611: atNameEl.appendChild(doc.createTextNode(atName));
612: atEl.appendChild(atNameEl);
613: Element valueEl = doc.createElement("value");
614: String value = tsup.getParameterValue(atName);
615: if (value == null) {
616: // set the default value
617: value = context.getThemeStylesheetDescription()
618: .getStylesheetParameterDefaultValue(atName);
619: }
620: valueEl.appendChild(doc.createTextNode(value));
621: atEl.appendChild(valueEl);
622: Element descrEl = doc.createElement("description");
623: descrEl
624: .appendChild(doc.createTextNode(context
625: .getThemeStylesheetDescription()
626: .getStylesheetParameterWordDescription(
627: atName)));
628: atEl.appendChild(descrEl);
629: tpEl.appendChild(atEl);
630: }
631: edEl.appendChild(tpEl);
632: doc.appendChild(edEl);
633: // debug printout of the prepared xml
634: try {
635: StringWriter outString = new StringWriter();
636: /* TODO: This should be reviewed at some point to see if we can use the
637: * DOM3 LS capability and hence a standard way of doing this rather
638: * than using an internal implementation class.
639: */
640: OutputFormat format = new OutputFormat();
641: format.setOmitXMLDeclaration(true);
642: format.setIndenting(true);
643: XMLSerializer serializer = new XMLSerializer(outString,
644: format);
645: serializer.serialize(doc);
646: log.debug(outString.toString());
647: } catch (Exception e) {
648: log.debug(e, e);
649: }
650: StylesheetSet set = context.getStylesheetSet();
651: if (set == null) {
652: throw new GeneralRenderingException(
653: "Unable to determine the stylesheet list");
654: }
655: String xslURI = set.getStylesheetURI("editGPrefs",
656: runtimeData.getBrowserInfo());
657: if (xslURI != null) {
658: XSLT xslt = XSLT.getTransformer(this , runtimeData
659: .getLocales());
660: xslt.setXML(doc);
661: xslt.setXSL(this .getClass().getResource(xslURI)
662: .toString());
663: xslt.setTarget(out);
664: xslt.setStylesheetParameter("baseActionURL",
665: runtimeData.getBaseActionURL());
666: xslt.transform();
667: } else {
668: throw new ResourceMissingException("", "stylesheet",
669: "Unable to find stylesheet to display content for this media");
670: }
671: }
672:
673: private void prepareSaveEditGPrefs() throws PortalException {
674: StructureStylesheetUserPreferences ssup = context
675: .getUserPreferences()
676: .getStructureStylesheetUserPreferences();
677: for (Enumeration e = context
678: .getStructureStylesheetDescription()
679: .getStylesheetParameterNames(); e.hasMoreElements();) {
680: String parName = (String) e.nextElement();
681: String value = runtimeData.getParameter(parName);
682: if (value == null) {
683: ssup
684: .putParameterValue(
685: parName,
686: context
687: .getStructureStylesheetDescription()
688: .getStylesheetParameterDefaultValue(
689: parName));
690: } else {
691: ssup.putParameterValue(parName, value);
692: // log.debug("CUserPreferences.GGlobalPrefsState::prepareSaveEditGPrefs() : setting sparameter "+parName+"=\""+value+"\".");
693: }
694: }
695: ThemeStylesheetUserPreferences tsup = context
696: .getUserPreferences()
697: .getThemeStylesheetUserPreferences();
698: for (Enumeration e = context
699: .getThemeStylesheetDescription()
700: .getStylesheetParameterNames(); e.hasMoreElements();) {
701: String parName = (String) e.nextElement();
702: String value = runtimeData.getParameter(parName);
703: if (value == null) {
704: tsup
705: .putParameterValue(
706: parName,
707: context
708: .getThemeStylesheetDescription()
709: .getStylesheetParameterDefaultValue(
710: parName));
711: } else {
712: tsup.putParameterValue(parName, value);
713: // log.debug("CUserPreferences.GGlobalPrefsState::prepareSaveEditGPrefs() : setting tparameter "+parName+"=\""+value+"\".");
714: }
715: }
716: context.setModified(true);
717: IPrivilegedChannel bstate = new GBrowseState(context);
718: bstate.setRuntimeData(runtimeData);
719: context.setState(bstate);
720: }
721: }
722:
723: protected class GBrowseState extends BaseState {
724: ChannelRuntimeData runtimeData;
725: protected GPreferencesState context;
726:
727: public GBrowseState(GPreferencesState context) {
728: this .context = context;
729: }
730:
731: public void setRuntimeData(ChannelRuntimeData rd)
732: throws PortalException {
733: this .runtimeData = rd;
734: // internal state handling
735: String action = runtimeData.getParameter("action");
736: if (action != null) {
737: if (action.equals("browse")) {
738: String runtimeFolderID = runtimeData
739: .getParameter("folderID");
740: if (runtimeFolderID != null) {
741: context.setFolderID(runtimeFolderID);
742: }
743: } else if (action.equals("move")) {
744: IPrivilegedChannel mts = new GMoveToState(context);
745: mts.setRuntimeData(rd);
746: context.setState(mts);
747: } else if (action.equals("reorder"))
748: prepareReorder();
749: else if (action.equals("saveChanges")) {
750: prepareSaveChanges();
751: } else if (action.equals("editElement")) {
752: IPrivilegedChannel eli = new GEditLayoutItemState(
753: context);
754: eli.setRuntimeData(rd);
755: context.setState(eli);
756: }
757: }
758: }
759:
760: public void renderXML(ContentHandler out)
761: throws PortalException {
762: StylesheetSet set = context.getStylesheetSet();
763: if (set == null) {
764: throw new GeneralRenderingException(
765: "Unable to determine the stylesheet list");
766: }
767: String xslURI = null;
768: xslURI = set.getStylesheetURI("browse", runtimeData
769: .getBrowserInfo());
770: Hashtable params = new Hashtable();
771: params.put("folderID", context.getFolderID());
772: params.put("modified", new Boolean(context.isModified()));
773: params.put("baseActionURL", runtimeData.getBaseActionURL());
774: params.put("profileName", context.getProfile()
775: .getProfileName());
776: if (context.getProfile().isSystemProfile()) {
777: params.put("profileType", "system");
778: } else {
779: params.put("profileType", "user");
780: }
781: if (xslURI != null) {
782: XSLT xslt = XSLT.getTransformer(this , runtimeData
783: .getLocales());
784: xslt.setXML(context.getUserLayoutManager()
785: .getUserLayoutDOM());
786: xslt.setXSL(this .getClass().getResource(xslURI)
787: .toString());
788: xslt.setTarget(out);
789: xslt.setStylesheetParameters(params);
790: xslt.transform();
791: } else {
792: throw new ResourceMissingException("", "stylesheet",
793: "Unable to find stylesheet to display content for this media");
794: }
795: }
796:
797: private void prepareSaveChanges() throws PortalException {
798: context.setFolderID(context.getLayoutRootID());
799: context.setModified(false);
800: // relate changes back to the UserPreferencesManager if the profile that's being
801: // edited is the current profile.
802: // changes in userLayoutXML are always related back to the UserPreferencesManager.
803: // (unless profile-specific layouts will be introduced)
804: if (context.getUserPreferencesManager().getCurrentProfile() == context
805: .getProfile()) {
806: context.getUserPreferencesManager()
807: .setNewUserLayoutAndUserPreferences(
808: context.getUserLayoutManager(),
809: context.getUserPreferences());
810: } else {
811: // do a database save on the preferences
812: try {
813: // persist layout
814: context.getUserLayoutManager().saveUserLayout();
815: ulsdb.putUserPreferences(context
816: .getUserPreferencesManager().getPerson(),
817: context.getUserPreferences());
818: } catch (Exception e) {
819: throw new PortalException(e);
820: }
821: }
822: }
823:
824: private void prepareReorder() throws PortalException {
825: String folderID = runtimeData.getParameter("elementID"); // the folder or channel ID
826: String direction = runtimeData.getParameter("dir"); // "up" or "down"
827:
828: IUserLayoutManager lm = context.getUserLayoutManager();
829: if (direction.equals("up")) {
830: String prevSiblingId = lm
831: .getPreviousSiblingId(folderID);
832: if (prevSiblingId != null) {
833: lm.moveNode(folderID, lm.getParentId(folderID),
834: prevSiblingId);
835: }
836: // for (prev = element.getPreviousSibling(); prev != null && prev.getNodeType() != Node.ELEMENT_NODE && (!prev.getNodeName().equals("channel") || !prev.getNodeName().equals("folder")); prev = prev.getPreviousSibling());
837: } else if (direction.equals("down")) {
838: String nextSiblingId = lm.getNextSiblingId(folderID);
839: if (nextSiblingId != null) {
840: lm.moveNode(folderID, lm.getParentId(folderID),
841: nextSiblingId);
842: }
843: // for(next = element.getNextSibling(); next != null && next.getNodeType() != Node.ELEMENT_NODE && (!next.getNodeName().equals("channel") || !next.getNodeName().equals("folder")); next = next.getNextSibling());
844: }
845: context.setModified(true);
846: }
847: }
848:
849: protected class GMoveToState extends BaseState {
850: private String[] moveIDs = null; // contains the IDs of channels/folders to be moved
851: protected ChannelRuntimeData runtimeData;
852: protected GPreferencesState context;
853:
854: public GMoveToState(GPreferencesState context) {
855: this .context = context;
856: }
857:
858: public void setRuntimeData(ChannelRuntimeData rd)
859: throws PortalException {
860: this .runtimeData = rd;
861: String action = runtimeData.getParameter("action");
862: if (action != null) {
863: if (action.equals("cancel")) {
864: // prepareCancel ();
865: } else if (action.equals("move"))
866: prepareMove();
867: else if (action.equals("moveTo"))
868: prepareMoveTo();
869: }
870: }
871:
872: public void renderXML(ContentHandler out)
873: throws PortalException {
874: StylesheetSet set = context.getStylesheetSet();
875: if (set == null)
876: throw new GeneralRenderingException(
877: "Unable to determine the stylesheet list");
878: String xslURI = set.getStylesheetURI("moveTo", runtimeData
879: .getBrowserInfo());
880: if (xslURI != null) {
881: XSLT xslt = XSLT.getTransformer(this , runtimeData
882: .getLocales());
883: xslt.setXML(context.getUserLayoutManager()
884: .getUserLayoutDOM());
885: xslt.setXSL(this .getClass().getResource(xslURI)
886: .toString());
887: xslt.setTarget(out);
888: xslt.setStylesheetParameter("baseActionURL",
889: runtimeData.getBaseActionURL());
890: xslt.transform();
891: } else
892: throw new ResourceMissingException("", "stylesheet",
893: "Unable to find stylesheet to display content for this media");
894: }
895:
896: private void prepareMove() {
897: // getParameterValues() should be a method in ChannelRuntimeData.
898: // For now, I'll use the request object -- ask Peter about this!
899: moveIDs = runtimeData.getParameterValues("move");
900: }
901:
902: private void prepareMoveTo() throws PortalException {
903: String destinationID = runtimeData
904: .getParameter("destination");
905: for (int i = 0; i < moveIDs.length; i++) {
906: getUserLayoutManager().moveNode(moveIDs[i],
907: destinationID, null);
908: }
909: context.setModified(true);
910: IPrivilegedChannel bstate = new GBrowseState(context);
911: bstate.setRuntimeData(runtimeData);
912: context.setState(bstate);
913: }
914: }
915: }
|