0001: /***************************************************************
0002: * This file is part of the [fleXive](R) project.
0003: *
0004: * Copyright (c) 1999-2007
0005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
0006: * All rights reserved
0007: *
0008: * The [fleXive](R) project is free software; you can redistribute
0009: * it and/or modify it under the terms of the GNU General Public
0010: * License as published by the Free Software Foundation;
0011: * either version 2 of the License, or (at your option) any
0012: * later version.
0013: *
0014: * The GNU General Public License can be found at
0015: * http://www.gnu.org/copyleft/gpl.html.
0016: * A copy is found in the textfile GPL.txt and important notices to the
0017: * license from the author are found in LICENSE.txt distributed with
0018: * these libraries.
0019: *
0020: * This library is distributed in the hope that it will be useful,
0021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0023: * GNU General Public License for more details.
0024: *
0025: * For further information about UCS - unique computing solutions gmbh,
0026: * please see the company website: http://www.ucs.at
0027: *
0028: * For further information about [fleXive](R), please see the
0029: * project website: http://www.flexive.org
0030: *
0031: *
0032: * This copyright notice MUST APPEAR in all copies of the file!
0033: ***************************************************************/package com.flexive.war.beans.admin.content;
0034:
0035: import com.flexive.faces.FxJsfUtils;
0036: import com.flexive.faces.beans.ActionBean;
0037: import com.flexive.faces.messages.FxFacesMsgErr;
0038: import com.flexive.faces.messages.FxFacesMsgInfo;
0039: import com.flexive.shared.CacheAdmin;
0040: import com.flexive.shared.EJBLookup;
0041: import com.flexive.shared.FxArrayUtils;
0042: import com.flexive.shared.FxContext;
0043: import com.flexive.shared.content.*;
0044: import com.flexive.shared.exceptions.FxApplicationException;
0045: import com.flexive.shared.interfaces.ContentEngine;
0046: import com.flexive.shared.interfaces.TreeEngine;
0047: import com.flexive.shared.security.ACL;
0048: import com.flexive.shared.security.UserTicket;
0049: import com.flexive.shared.structure.*;
0050: import com.flexive.shared.tree.FxTreeMode;
0051: import com.flexive.shared.tree.FxTreeNode;
0052: import com.flexive.shared.tree.FxTreeNodeEdit;
0053: import com.flexive.shared.value.FxBinary;
0054: import com.flexive.shared.value.FxString;
0055: import com.flexive.shared.workflow.Step;
0056: import com.flexive.shared.workflow.StepDefinition;
0057: import org.apache.commons.lang.StringUtils;
0058: import org.apache.commons.logging.Log;
0059: import org.apache.commons.logging.LogFactory;
0060: import org.apache.myfaces.custom.fileupload.UploadedFile;
0061:
0062: import javax.faces.event.ActionEvent;
0063: import javax.faces.model.SelectItem;
0064: import javax.servlet.http.HttpServletRequest;
0065: import javax.servlet.http.HttpSession;
0066: import java.io.Serializable;
0067: import java.util.ArrayList;
0068: import java.util.Hashtable;
0069: import java.util.List;
0070:
0071: public class ContentEditorBean implements ActionBean, Serializable {
0072: private static final Log LOG = LogFactory
0073: .getLog(ContentEditorBean.class);
0074:
0075: private ContentEngine co;
0076: protected TreeEngine tree;
0077: private List<FxPropertyAssignment> properties;
0078: private List<FxGroupAssignment> groups;
0079: private FxContent content;
0080: private FxContentVersionInfo versionInfo;
0081: private CeDataWrapper data;
0082: private CeDisplayProvider displayProv;
0083: private CeAddElementOptions addElementOptions;
0084: private FxEnvironment environment;
0085: private String[] elements;
0086: private long type;
0087: private CeIdGenerator idGenerator;
0088: private FxData element;
0089: private ACL acl;
0090: private ArrayList<SelectItem> steps;
0091: private long id = -1;
0092: private int version = -1;
0093: private FxPK pk;
0094: private List<FxTreeNode> treeNodes;
0095: private boolean readOnly;
0096: private boolean editAble;
0097: private boolean deleteAble;
0098: private long treeNodeParent;
0099: private FxTreeNode treeNode;
0100: private Hashtable<String, String> fileInputValues = new Hashtable<String, String>(
0101: 10);
0102: private String editorActionName;
0103: private String editorActionXpath;
0104: protected boolean isDummy;
0105:
0106: public String getEditorType() {
0107: return "NORMAL";
0108: }
0109:
0110: public void setEditorType(String editorType) {
0111: // dummy
0112: }
0113:
0114: protected String getEditorPage() {
0115: return "contentEditor";
0116: }
0117:
0118: protected String getSessionCacheId() {
0119: return this .getClass().getName();
0120: }
0121:
0122: public ContentEditorBean() {
0123: if (isDummy)
0124: return;
0125: try {
0126: co = EJBLookup.getContentEngine();
0127: tree = EJBLookup.getTreeEngine();
0128: environment = CacheAdmin.getFilteredEnvironment();
0129: FxJsfUtils.getSession().setAttribute(getSessionCacheId(),
0130: this );
0131: } catch (Throwable t) {
0132: new FxFacesMsgErr(t).addToContext();
0133: }
0134: }
0135:
0136: @SuppressWarnings("UnusedDeclaration")
0137: ContentEditorBean(boolean dummy) {
0138: // to create a singleton for lookups
0139: isDummy = true;
0140: }
0141:
0142: public static ContentEditorBean getSingleton() {
0143: return new ContentEditorBean(true);
0144: }
0145:
0146: public String getEditorActionXpath() {
0147: return "";//editorActionXpath;
0148: }
0149:
0150: public void setEditorActionXpath(String editorActionXpath) {
0151: this .editorActionXpath = editorActionXpath;
0152: }
0153:
0154: public void setEditorActionName(String editorActionName) {
0155: this .editorActionName = editorActionName;
0156: }
0157:
0158: public String getEditorActionName() {
0159: return "";//editorActionName;
0160: }
0161:
0162: public boolean isReadOnly() {
0163: return readOnly;
0164: }
0165:
0166: public void setReadOnly(boolean readOnly) {
0167: this .readOnly = readOnly;
0168: }
0169:
0170: public boolean isEditAble() {
0171: return editAble;
0172: }
0173:
0174: public boolean isDeleteAble() {
0175: return deleteAble;
0176: }
0177:
0178: private void processAction() {
0179: if (StringUtils.isBlank(editorActionName)
0180: || StringUtils.isBlank(editorActionXpath)) {
0181: return;
0182: }
0183: try {
0184: final List<FxData> data = content
0185: .getData(editorActionXpath);
0186: setElement(data.get(0));
0187: if (editorActionName.equalsIgnoreCase("addProperty")) {
0188: addElement(null);
0189: } else if (editorActionName
0190: .equalsIgnoreCase("removeProperty")) {
0191: removeElement(null);
0192: }
0193: editorActionName = null;
0194: editorActionXpath = null;
0195: } catch (Exception e) {
0196: LOG.warn("Failed to execute content editor action "
0197: + editorActionName + " for XPath "
0198: + editorActionXpath + ": " + e.getMessage(), e);
0199: }
0200: }
0201:
0202: public void setBinary(String xpath, FxBinary binary) {
0203: try {
0204: FxBinary binProperty = new FxBinary(binary);
0205: content.setValue(xpath, binProperty);
0206: } catch (Throwable t) {
0207: System.err.println("Failed to set binary for xpath="
0208: + xpath + ": " + t.getMessage());
0209: }
0210: }
0211:
0212: protected void finalize() throws Throwable {
0213: super .finalize();
0214: FxJsfUtils.getSession().removeAttribute(getSessionCacheId());
0215: }
0216:
0217: public ContentEngine getContentEngine() {
0218: return co;
0219: }
0220:
0221: public Hashtable<String, String> getFileInputValues() {
0222: return fileInputValues;
0223: }
0224:
0225: public void setFileInputValues(
0226: Hashtable<String, String> fileInputValues) {
0227: this .fileInputValues = fileInputValues;
0228: }
0229:
0230: /**
0231: * Returns the active content editor beans of the calling user session, or null id none is available at the call time
0232: *
0233: * @param request the request
0234: * @return the content editor beans, or null
0235: */
0236: public ContentEditorBean getInstance(HttpServletRequest request) {
0237: return _getInstance(request.getSession());
0238: }
0239:
0240: /**
0241: * Returns the active content editor beans of the calling jsf user session,
0242: * or null id none is available at the call time
0243: *
0244: * @return the content editor beans, or null
0245: */
0246: public ContentEditorBean getInstance() {
0247: return _getInstance(FxJsfUtils.getSession());
0248: }
0249:
0250: /**
0251: * Helper function.
0252: *
0253: * @param session the session
0254: * @return a reference to the content editor beans bound in the session.
0255: */
0256: private ContentEditorBean _getInstance(HttpSession session) {
0257: try {
0258: ContentEditorBean ceb = (ContentEditorBean) session
0259: .getAttribute(getSessionCacheId());
0260: if (ceb == null) {
0261: // Fallback: look under the JSF name
0262: ceb = (ContentEditorBean) session
0263: .getAttribute(getJsfAttributeName());
0264: }
0265: return ceb;
0266: } catch (Throwable t) {
0267: return null;
0268: }
0269: }
0270:
0271: /**
0272: * Returns the name of the beans, like JSF stores it in the session.
0273: *
0274: * @return the jsf name of the beans
0275: */
0276: protected String getJsfAttributeName() {
0277: String splitup[] = this .getClass().getName().split("\\.");
0278: // Take just the beans name, and convert the first char to lowercase
0279: String name = String
0280: .valueOf(
0281: this .getClass().getName().split("\\.")[splitup.length - 1]
0282: .charAt(0)).toLowerCase();
0283: name += splitup[splitup.length - 1].substring(1);
0284: return name;
0285: }
0286:
0287: public String getUserCd() {
0288: try {
0289: long id = Long.valueOf(FxJsfUtils.getRequest()
0290: .getAttribute("cdId").toString());
0291: int vers = Integer.valueOf(FxJsfUtils.getRequest()
0292: .getAttribute("vers").toString());
0293: // type is always 'contactData' here...
0294: this .type = CacheAdmin.getFilteredEnvironment().getType(
0295: FxType.CONTACTDATA).getId();
0296: // clear fields...
0297: release();
0298: if (id != -1) {
0299: this .id = id;
0300: this .version = vers;
0301: // init all necessary fields...as this.id is set no new contact data set will be created but the existing one loaded
0302: _init();
0303: //content = co.load(new FxPK(id, vers));
0304: }
0305: } catch (Exception e) {
0306: // TODO possibly pass some error message to the HTML page
0307: LOG.error("Failed to parse request parameters: "
0308: + e.getMessage(), e);
0309: }
0310: return null;
0311: }
0312:
0313: /**
0314: * {@inheritDoc}
0315: */
0316: public String getParseRequestParameters()
0317: throws FxApplicationException {
0318: processAction(); // execute from content editor javascript
0319: try {
0320: String action = FxJsfUtils.getParameter("action");
0321: if (StringUtils.isBlank(action)) {
0322: return null;
0323: }
0324: if ("newInstance".equals(action)) {
0325: long typeId = FxJsfUtils.getLongParameter("typeId", -1);
0326: if (typeId == -1) {
0327: typeId = CacheAdmin
0328: .getFilteredEnvironment()
0329: .getType(
0330: FxJsfUtils.getParameter("typeName"))
0331: .getId();
0332: }
0333: long nodeId = FxJsfUtils.getLongParameter("nodeId", -1);
0334: release();
0335: setType(typeId);
0336: initNew();
0337: if (nodeId != -1) {
0338: setTreeNodeParent(nodeId);
0339: addTreeNode(null);
0340: }
0341: } else if ("editInstance".equals(action)) {
0342: FxPK newPk;
0343: if (FxJsfUtils.getParameter("pk") != null) {
0344: String split[] = FxJsfUtils.getParameter("pk")
0345: .split("\\.");
0346: Long id = Long.valueOf(split[0].trim());
0347: Integer ver = Integer.valueOf(split[1].trim());
0348: newPk = new FxPK(id, ver);
0349: } else {
0350: newPk = new FxPK(FxJsfUtils.getLongParameter("id"),
0351: FxPK.MAX);
0352: }
0353: release();
0354: setPk(newPk);
0355: load();
0356: setReadOnly(FxJsfUtils.getBooleanParameter("readOnly"));
0357: if (this .readOnly) {
0358: compact();
0359: }
0360: }
0361: // hack!
0362: FxJsfUtils.resetFaceletsComponent("frm");
0363: } catch (Throwable t) {
0364: // TODO possibly pass some error message to the HTML page
0365: LOG.error("Failed to parse request parameters: "
0366: + t.getMessage(), t);
0367: }
0368: return null;
0369: }
0370:
0371: UploadedFile file = null;
0372:
0373: public void setFiletest(UploadedFile file) {
0374: this .file = file;
0375: }
0376:
0377: public UploadedFile getFiletest() {
0378: return file;
0379: }
0380:
0381: public List<FxTreeNode> getTreeNodes() {
0382: return treeNodes;
0383: }
0384:
0385: public void setTreeNodes(List<FxTreeNode> treeNodes) {
0386: this .treeNodes = treeNodes;
0387: }
0388:
0389: public long getTreeNodeParent() {
0390: return treeNodeParent;
0391: }
0392:
0393: public void setTreeNodeParent(long treeNode) {
0394: this .treeNodeParent = treeNode;
0395: }
0396:
0397: public boolean isNew() {
0398: return content == null || this .content.getPk() == null
0399: || this .content.getPk().isNew();
0400: }
0401:
0402: public FxTreeNode getTreeNode() {
0403: return treeNode;
0404: }
0405:
0406: public void setTreeNode(FxTreeNode treeNode) {
0407: this .treeNode = treeNode;
0408: }
0409:
0410: /**
0411: * Ajax call for tree nodes.
0412: *
0413: * @param event the event
0414: */
0415: public void removeTreeNode(ActionEvent event) {
0416: if (readOnly)
0417: return;
0418: FxJsfUtils.resetFaceletsComponent("frm:treeNodes");
0419: for (FxTreeNode node : treeNodes) {
0420: if (node.getId() == treeNode.getId())
0421: node.setMarkForDelete(true);
0422: }
0423: }
0424:
0425: /**
0426: * Ajax call for tree nodes.
0427: *
0428: * @param event the event
0429: */
0430: public void addTreeNode(ActionEvent event) {
0431: if (readOnly)
0432: return;
0433: FxJsfUtils.resetFaceletsComponent("frm:treeNodes");
0434: addTreeNode(treeNodeParent);
0435: }
0436:
0437: public void addTreeNode(long _node) {
0438: try {
0439: // Only add the path if it does not already exist
0440: for (FxTreeNode node : treeNodes) {
0441: if (node.getParentNodeId() == _node) {
0442: if (node.isMarkForDelete()) {
0443: // was removed before .. just take it in again
0444: node.setMarkForDelete(false);
0445: return;
0446: } else {
0447: // exists
0448: return;
0449: }
0450: }
0451: }
0452:
0453: // Add the path if the parent node is valid
0454: try {
0455: FxTreeNode tn = tree.getNode(FxTreeMode.Edit, _node);
0456: if (tn != null)
0457: treeNodes.add(FxTreeNode
0458: .createNewTemporaryChildNode(tn));
0459: } catch (Throwable t) {
0460: /* ignore */
0461: }
0462: } catch (Throwable t) {
0463: new FxFacesMsgErr(t).addToContext();
0464: }
0465: }
0466:
0467: public void setType(long type) {
0468: this .type = type;
0469: }
0470:
0471: public String initNew() {
0472: release();
0473: _init();
0474: return null;
0475: }
0476:
0477: public FxPK getPk() {
0478: return pk;
0479: }
0480:
0481: public void setPk(FxPK pk) {
0482: this .pk = pk;
0483: if (pk != null) {
0484: this .id = pk.getId();
0485: this .version = pk.getVersion();
0486: }
0487: }
0488:
0489: public String load() {
0490: content = null;
0491: _init();
0492: return getEditorPage();
0493: }
0494:
0495: public String loadUserContent() {
0496: content = null;
0497: _init();
0498: return "showContentEditor";
0499: }
0500:
0501: public String reload() {
0502: content = null;
0503: _init();
0504: //return getEditorPage();
0505: FxJsfUtils.resetFaceletsComponent("frm:all");
0506: return null;
0507: }
0508:
0509: public long getId() {
0510: return id;
0511: }
0512:
0513: public void setId(long id) {
0514: this .id = id;
0515: }
0516:
0517: public int getVersion() {
0518: return version;
0519: }
0520:
0521: public void setVersion(int version) {
0522: this .version = version;
0523: }
0524:
0525: public Boolean _init() {
0526: if (!isInitialized()) {
0527: try {
0528: environment = CacheAdmin.getFilteredEnvironment();
0529: if (id != -1) {
0530: FxPK pk = (version == -1) ? new FxPK(id, FxPK.MAX)
0531: : new FxPK(id, version);
0532: // Load the content itself
0533: content = co.load(pk);
0534: content.loadReferences(co);
0535: type = content.getTypeId();
0536: version = content.getVersion();
0537: versionInfo = co.getContentVersionInfo(pk);
0538: // Load the tree nodes assigned to this content
0539: initTreeData(pk.getId());
0540: } else {
0541: // Create a new empty content
0542: content = co.initialize(type);
0543: versionInfo = FxContentVersionInfo.createEmpty();
0544: version = FxPK.MAX;
0545: treeNodes = new ArrayList<FxTreeNode>(5);
0546: }
0547: FxType fxType = environment.getType(type);
0548: properties = fxType.getAssignedProperties();
0549: groups = fxType.getAssignedGroups();
0550: acl = CacheAdmin.getEnvironment().getACL(
0551: content.getAclId());
0552: data = new CeDataWrapper(this );
0553: displayProv = new CeDisplayProvider(this );
0554: idGenerator = new CeIdGenerator();
0555: addElementOptions = new CeAddElementOptions(this );
0556: _initSteps();
0557: editAble = true;
0558: deleteAble = true;
0559: if (steps == null || steps.size() == 0) {
0560: editAble = false;
0561: readOnly = true;
0562: if (id == -1) {
0563: new FxFacesMsgErr("Content.err.noStepAccess")
0564: .addToContext();
0565: release();
0566: return null;
0567: }
0568: }
0569: FxContentSecurityInfo si = fxType.usePermissions()
0570: && id != -1 ? co.getContentSecurityInfo(content
0571: .getPk()) : null;
0572: if (editAble && id != -1) {
0573: if (fxType.usePermissions())
0574: editAble = FxPermissionUtils.checkPermission(
0575: FxContext.get().getTicket(),
0576: ACL.Permission.EDIT, si, false);
0577: }
0578: if (fxType.usePermissions() && id != -1)
0579: deleteAble = FxPermissionUtils.checkPermission(
0580: FxContext.get().getTicket(),
0581: ACL.Permission.DELETE, si, false);
0582: return true;
0583: } catch (Throwable t) {
0584: release();
0585: new FxFacesMsgErr(t).addToContext();
0586: return null;
0587: }
0588: } else {
0589: return false;
0590: }
0591: }
0592:
0593: private void initTreeData(long _id) {
0594: // Load the tree nodes assigned to this content
0595: try {
0596: treeNodes = tree
0597: .getNodesWithReference(FxTreeMode.Edit, _id);
0598: } catch (Throwable t) {
0599: new FxFacesMsgErr(t).addToContext();
0600: }
0601: }
0602:
0603: /**
0604: * Determines all possible steps for the current content.
0605: */
0606: public void _initSteps() {
0607: UserTicket ticket = FxContext.get().getTicket();
0608: FxType fxType = environment.getType(type);
0609:
0610: List<Step> steps;
0611: boolean isNew = content.getPk().isNew();
0612: if (isNew) {
0613: steps = fxType.getWorkflow().getSteps();
0614: } else {
0615: steps = fxType.getWorkflow()
0616: .getTargets(content.getStepId());
0617: if (steps.size() == 0
0618: || !steps.contains(environment.getStep(content
0619: .getStepId())))
0620: steps.add(environment.getStep(content.getStepId()));
0621: }
0622: ArrayList<SelectItem> result = new ArrayList<SelectItem>(steps
0623: .size());
0624: for (Step step : steps) {
0625: if (!fxType.useStepPermissions()
0626: || (isNew ? ticket.mayCreateACL(step.getAclId(),
0627: content.getLifeCycleInfo().getCreatorId())
0628: : ticket.mayEditACL(step.getAclId(),
0629: content.getLifeCycleInfo()
0630: .getCreatorId()))) {
0631: StepDefinition def = environment.getStepDefinition(step
0632: .getStepDefinitionId());
0633: result.add(new SelectItem(String.valueOf(step.getId()),
0634: def.getLabel().getDefaultTranslation()));
0635: }
0636: }
0637: result.trimToSize();
0638: this .steps = result;
0639: }
0640:
0641: /**
0642: * Gets the acl used by the content
0643: *
0644: * @return the acl
0645: */
0646: public ACL getAcl() {
0647: return acl;
0648: }
0649:
0650: /**
0651: * Sets the acl used by the content
0652: *
0653: * @param acl the acl
0654: */
0655: public void setAcl(ACL acl) {
0656: content.setAclId(acl.getId());
0657: this .acl = acl;
0658: }
0659:
0660: public CeIdGenerator getIdGenerator() {
0661: return idGenerator;
0662: }
0663:
0664: /**
0665: * Returns all editable types.
0666: *
0667: * @return all editable types
0668: */
0669: public List<SelectItem> getEditableTypes() {
0670: List<FxType> types = CacheAdmin.getFilteredEnvironment()
0671: .getTypes(true, true, true, false);
0672: ArrayList<FxType> result = new ArrayList<FxType>(types.size());
0673: for (FxType t : types) {
0674: if (!t.getName().equalsIgnoreCase("ROOT")) {
0675: result.add(t);
0676: }
0677: }
0678: return FxJsfUtils.asSelectListWithLabel(result);
0679: }
0680:
0681: public String cancel() {
0682: String ret;
0683: long _id = id;
0684: int _version = version;
0685: if (content != null && content.getPk().isNew())
0686: ret = null;
0687: else {
0688: ret = getEditorPage();
0689: }
0690: release();
0691: if (ret != null) {
0692: this .id = _id;
0693: this .version = _version;
0694: reload();
0695: this .readOnly = true;
0696: }
0697: return ret;
0698: }
0699:
0700: protected String release() {
0701: FxJsfUtils.resetFaceletsComponent("frm:all");
0702: FxJsfUtils.resetFaceletsComponent("frm:body");
0703: environment = null;
0704: properties = null;
0705: groups = null;
0706: content = null;
0707: data = null;
0708: displayProv = null;
0709: addElementOptions = null;
0710: idGenerator = null;
0711: steps = null;
0712: acl = null;
0713: version = -1;
0714: id = -1;
0715: readOnly = false;
0716: editAble = false;
0717: deleteAble = false;
0718: //return getEditorPage();
0719: return null;
0720: }
0721:
0722: public List<SelectItem> getPossibleWorkflowSteps() {
0723: return steps == null ? new ArrayList<SelectItem>(0) : steps;
0724: }
0725:
0726: public String getStep() {
0727: return content == null ? "-1" : String.valueOf(content
0728: .getStepId());
0729: }
0730:
0731: /**
0732: * @return the label of the current step
0733: */
0734: public String getStepDescription() {
0735: try {
0736: long stepDef = environment.getStep(content.getStepId())
0737: .getStepDefinitionId();
0738: return environment.getStepDefinition(stepDef).getLabel()
0739: .getBestTranslation();
0740: } catch (Throwable t) {
0741: return getStep();
0742: }
0743: }
0744:
0745: public void setStep(String value) {
0746: long stepId = Long.valueOf(value);
0747: content.setStepId(stepId);
0748: }
0749:
0750: public boolean isInitialized() {
0751: return content != null;
0752: }
0753:
0754: public CeDisplayProvider getDisplay() {
0755: return displayProv;
0756: }
0757:
0758: public String getElements() {
0759: return elements == null ? "" : FxArrayUtils.toSeparatedList(
0760: elements, ",");
0761: }
0762:
0763: public void setElements(String elements) {
0764: this .elements = elements == null
0765: || elements.trim().length() == 0 ? new String[0]
0766: : elements.split(",");
0767: }
0768:
0769: public long getType() {
0770: return type;
0771: }
0772:
0773: public String getTypeDisplay() {
0774: String display = environment.getType(type).getDescription()
0775: .getBestTranslation();
0776: if (display == null || display.trim().length() == 0) {
0777: display = environment.getType(type).getName();
0778: }
0779: return display;
0780: }
0781:
0782: public boolean isSupportSecurity() {
0783: return environment.getType(type).usePermissions();
0784: }
0785:
0786: public CeDataWrapper getData() {
0787: return data;
0788: }
0789:
0790: public CeAddElementOptions getAddElementOptions() {
0791: return addElementOptions;
0792: }
0793:
0794: public List<FxData> getDataList() {
0795: return content.getRootGroup().getChildren();
0796: }
0797:
0798: public FxEnvironment getEnvironment() {
0799: return environment;
0800: }
0801:
0802: public List<FxPropertyAssignment> getProperties() {
0803: return properties;
0804: }
0805:
0806: public List<FxGroupAssignment> getGroups() {
0807: return groups;
0808: }
0809:
0810: public FxContent getContent() {
0811: return content;
0812: }
0813:
0814: /**
0815: * Get all available information about versions
0816: *
0817: * @return version info
0818: */
0819: public FxContentVersionInfo getVersionInfo() {
0820: return versionInfo;
0821: }
0822:
0823: /**
0824: * Persists all fields in the session without saving to the database.
0825: *
0826: * @return the next page to render (= the content editor)
0827: */
0828: public String saveInSession() {
0829: processAction();
0830: return getEditorPage();
0831: }
0832:
0833: /**
0834: * Removes all empty elements which are not required.
0835: *
0836: * @return the next page to render (= the content editor)
0837: */
0838: public String compact() {
0839: content.getRootGroup().removeEmptyEntries();
0840: FxJsfUtils.resetFaceletsComponent("frm:all");
0841: return getEditorPage();
0842: }
0843:
0844: /**
0845: * Deletes the instance
0846: *
0847: * @return the next page to render (= the content editor)
0848: */
0849: public String delete() {
0850: try {
0851: long id = content.getPk().getId();
0852: co.remove(content.getPk());
0853: release();
0854: new FxFacesMsgInfo("Content.nfo.deleted", id)
0855: .addToContext();
0856: } catch (Throwable t) {
0857: new FxFacesMsgErr(t).addToContext();
0858: }
0859: //return getEditorPage();
0860: return null;
0861: }
0862:
0863: /**
0864: * Saves the data in a new version.
0865: *
0866: * @return the next page to render (= the content editor)
0867: */
0868: public String saveInNewVersion() {
0869: return _save(true);
0870: }
0871:
0872: /**
0873: * Saves the data.
0874: *
0875: * @return the next page to render (= the content editor)
0876: */
0877: public String save() {
0878: return _save(false);
0879: }
0880:
0881: /**
0882: * Saves the data in the current or in a new version.
0883: *
0884: * @param newVersion if true a new version is created.
0885: * @return the next page to render (=the editor)
0886: */
0887: private String _save(boolean newVersion) {
0888: FxPK pk;
0889: try {
0890: String msg = isNew() ? "Content.nfo.created"
0891: : "Content.nfo.updated";
0892: //Store the content
0893: pk = newVersion ? co.createNewVersion(content) : co
0894: .save(content);
0895: new FxFacesMsgInfo(msg, pk.getId()).addToContext();
0896: // Handle the tree
0897: final List<FxTreeNode> treeNodes = tree
0898: .getNodesWithReference(FxTreeMode.Edit, pk.getId());
0899: for (FxTreeNode node : this .treeNodes) {
0900: if (node.isMarkForDelete()) {
0901: tree.remove(node, false, true);
0902: } else if (node.isTemporary()) {
0903: boolean assignmentExists = false;
0904: for (FxTreeNode child : treeNodes) {
0905: if (child.getParentNodeId() == node
0906: .getParentNodeId()) {
0907: // avoid duplicate tree entries
0908: assignmentExists = true;
0909: }
0910: }
0911: if (!assignmentExists) {
0912: String name = null;
0913: if (content.containsValue("/CAPTION")) {
0914: name = ((FxString) content
0915: .getValue("/CAPTION"))
0916: .getBestTranslation();
0917: }
0918: if (StringUtils.isBlank(name)) {
0919: name = environment.getType(type).getName()
0920: + "_" + pk.getId() + "."
0921: + pk.getVersion();
0922: }
0923: tree
0924: .save(FxTreeNodeEdit.createNew(name)
0925: .setParentNodeId(
0926: node.getParentNodeId())
0927: .setReference(pk).setPosition(
0928: Integer.MIN_VALUE));
0929: }
0930: }
0931: }
0932: // Reload changes
0933: setPk(pk);
0934: reload();
0935: FxJsfUtils.resetFaceletsComponent("frm:all");
0936: } catch (Throwable t) {
0937: new FxFacesMsgErr(t).addToContext();
0938: }
0939: return null;
0940: //return getEditorPage();
0941: }
0942:
0943: public String enableEdit() {
0944: if (!editAble)
0945: return getEditorPage();
0946: reload(); // TODO: locking
0947: setReadOnly(false);
0948: return getEditorPage();
0949: }
0950:
0951: /**
0952: * Ajax call for remove element.
0953: *
0954: * @param event the event
0955: */
0956: public void removeElement(ActionEvent event) {
0957: try {
0958: content.remove(element.getXPathFull());
0959: FxJsfUtils.resetFaceletsComponent("frm:all");
0960: } catch (Throwable t) {
0961: new FxFacesMsgErr(t).addToContext();
0962: }
0963: }
0964:
0965: /**
0966: * Ajax call for addElement.
0967: *
0968: * @param event the event
0969: */
0970: public void addElement(ActionEvent event) {
0971: try {
0972: element.createNew(element.getPos() + 1);
0973: FxJsfUtils.resetFaceletsComponent("frm:all");
0974: } catch (Throwable t) {
0975: new FxFacesMsgErr(t).addToContext();
0976: }
0977: }
0978:
0979: /**
0980: * Ajax call for addElement.
0981: *
0982: * @param event the event
0983: */
0984: public void moveElementUp(ActionEvent event) {
0985: try {
0986: element.getParent()
0987: .moveChild(element.getXPathElement(), -1);
0988: FxJsfUtils.resetFaceletsComponent("frm:all");
0989: } catch (Throwable t) {
0990: new FxFacesMsgErr(t).addToContext();
0991: }
0992: }
0993:
0994: /**
0995: * Ajax call for addElement.
0996: *
0997: * @param event the event
0998: */
0999: public void moveElementDown(ActionEvent event) {
1000: try {
1001: element.getParent()
1002: .moveChild(element.getXPathElement(), +1);
1003: FxJsfUtils.resetFaceletsComponent("frm:all");
1004: } catch (Throwable t) {
1005: new FxFacesMsgErr(t).addToContext();
1006: }
1007: }
1008:
1009: /**
1010: * Ajax call for addElement.
1011: *
1012: * @param event the event
1013: */
1014: public void addChilds(ActionEvent event) {
1015: try {
1016: FxGroupData grp;
1017: int pos;
1018:
1019: if (element instanceof FxGroupData) {
1020: grp = (FxGroupData) element;
1021: pos = 1;
1022: } else {
1023: grp = element.getParent();
1024: pos = element.getPos() + 1;
1025: }
1026:
1027: for (String ele : elements) {
1028: grp.addEmptyChild(ele, pos++);
1029: }
1030: FxJsfUtils.resetFaceletsComponent("frm:all");
1031:
1032: } catch (Throwable t) {
1033: new FxFacesMsgErr(t).addToContext();
1034: }
1035: }
1036:
1037: public FxData getElement() {
1038: return element;
1039: }
1040:
1041: public void setElement(FxData elememt) {
1042: this .element = elememt;
1043: }
1044:
1045: /**
1046: * Gets the display text for a assignment.
1047: *
1048: * @param ass the assignment
1049: * @return the display text
1050: */
1051: protected static FxString getDisplay(FxAssignment ass) {
1052: if (ass == null)
1053: return new FxString("");
1054: String display = ass.getDisplayName();
1055: if ((display == null || display.trim().length() == 0)
1056: && ass instanceof FxPropertyAssignment) {
1057: FxString result = ((FxPropertyAssignment) ass)
1058: .getProperty().getLabel();
1059: return (result == null) ? new FxString(
1060: "[empty displayname]") : result;
1061: }
1062: return new FxString(display);
1063: }
1064:
1065: /**
1066: * Prepare the content for save operation
1067: *
1068: * @throws FxApplicationException on errors
1069: */
1070: public void prepareSave() throws FxApplicationException {
1071: content = getContentEngine().prepareSave(content);
1072: }
1073: }
|