/* * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.arsdigita.cms.dispatcher; import com.arsdigita.bebop.Page; import com.arsdigita.bebop.PageState; import com.arsdigita.cms.CMS; import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentItemXMLRenderer; import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ExtraXMLGenerator; import com.arsdigita.cms.SecurityManager; import com.arsdigita.cms.UserDefinedContentItem; import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectTraversal; import com.arsdigita.domain.SimpleDomainObjectTraversalAdapter; import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Party; import com.arsdigita.kernel.permissions.PermissionDescriptor; import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.metadata.DynamicObjectType; import com.arsdigita.persistence.OID; import com.arsdigita.persistence.metadata.Property; import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.xml.Element; import org.apache.log4j.Logger; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; /** *

The default XMLGenerator implementation.

* * @author Michael Pih * @version $Revision: #20 $ $DateTime: 2004/08/17 23:15:09 $ * @version $Id: SimpleXMLGenerator.java 2167 2011-06-19 21:12:12Z pboy $ */ public class SimpleXMLGenerator implements XMLGenerator { private static final Logger s_log = Logger.getLogger(SimpleXMLGenerator.class); public static final String ADAPTER_CONTEXT = SimpleXMLGenerator.class. getName(); /** * jensp 2011-10-23: Sometimes the extra XML is not needed, for example * when embedding the XML of a content item into the XML output of another * content item. The default value {@code true}. To change the value * call {@link #setUseExtraXml(booelan)} after creating an instance of * your generator. */ private boolean useExtraXml = true; /** * jensp 2012-04-18: This value is forwarded to this ExtraXMLGenerators * by calling {@link ExtraXMLGenerator#setListMode(boolean)}. The behavior * triggered by this value depends on the specific implementation of * the {@code ExtraXMLGenerator} */ private boolean listMode = false; /** * Extra attributes for the cms:item element. */ private Map itemAttributes = new LinkedHashMap(); /** * Allows to overwrite the name and the namespace of the XML element * used to wrap the rendered item. */ private String itemElemName = "cms:item"; private String itemElemNs = CMS.CMS_XML_NS; // Register general purpose adaptor for all content items static { s_log.debug("Static initializer starting..."); SimpleDomainObjectTraversalAdapter adapter = new SimpleDomainObjectTraversalAdapter(); adapter.addAssociationProperty("/object/type"); adapter.addAssociationProperty("/object/categories"); DomainObjectTraversal.registerAdapter( ContentItem.BASE_DATA_OBJECT_TYPE, adapter, ADAPTER_CONTEXT); s_log.debug("Static initializer finished"); } public SimpleXMLGenerator() { } public void setUseExtraXml(final boolean useExtraXml) { this.useExtraXml = useExtraXml; } public void setListMode(final boolean listMode) { this.listMode = listMode; } public void addItemAttribute(final String name, final String value) { itemAttributes.put(name, value); } public void setItemElemName(final String itemElemName, final String itemElemNs) { this.itemElemName = itemElemName; this.itemElemNs = itemElemNs; } /** * Generates the XML to render the content panel. * * @param state The page state * @param parent The parent DOM element * @param useContext The use context */ public void generateXML(PageState state, Element parent, String useContext) { ContentSection section = CMS.getContext().getContentSection(); ContentItem item = getContentItem(state); s_log.info("Generate XML for item " + item.getOID()); Party currentParty = Kernel.getContext().getParty(); if (currentParty == null) { currentParty = Kernel.getPublicUser(); } // check if current user can edit the current item (nb privilege is granted on draft item, but live item // has draft as its permission context // // Note that the xml that is generated is only of use if you DO NOT CACHE content pages. // cg. PermissionDescriptor edit = new PermissionDescriptor(PrivilegeDescriptor.get( SecurityManager.CMS_EDIT_ITEM), item, currentParty); if (PermissionService.checkPermission(edit)) { parent.addAttribute("canEdit", "true"); } PermissionDescriptor publish = new PermissionDescriptor(PrivilegeDescriptor.get( SecurityManager.CMS_PUBLISH), item, currentParty); if (PermissionService.checkPermission(publish)) { parent.addAttribute("canPublish", "true"); } String className = item.getDefaultDomainClass(); // Ensure correct subtype of ContentItem is instantiated if (!item.getClass().getName().equals(className)) { s_log.info("Specializing item"); try { item = (ContentItem) DomainObjectFactory.newInstance(new OID(item. getObjectType().getQualifiedName(), item.getID())); } catch (DataObjectNotFoundException ex) { throw new UncheckedWrapperException( (String) GlobalizationUtil.globalize( "cms.dispatcher.cannot_find_domain_object").localize(), ex); } } // Implementing XMLGenerator directly is now deprecated if (item instanceof XMLGenerator) { s_log.info("Item implements XMLGenerator interface"); XMLGenerator xitem = (XMLGenerator) item; xitem.generateXML(state, parent, useContext); } else if (className.equals("com.arsdigita.cms.UserDefinedContentItem")) { s_log.info("Item is a user defined content item"); UserDefinedContentItem UDItem = (UserDefinedContentItem) item; generateUDItemXML(UDItem, state, parent, useContext); } else { s_log.info("Item is using DomainObjectXMLRenderer"); // This is the preferred method Element content = startElement(useContext, parent); ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(content); renderer.setWrapAttributes(true); renderer.setWrapRoot(false); renderer.setWrapObjects(false); renderer.setRevisitFullObject(true); renderer.walk(item, ADAPTER_CONTEXT); //parent.addContent(content); /* * 2011-08-27 jensp: Introduced to remove the annoying special templates * for MultiPartArticle, SiteProxy and others. The method called * here was already definied but not used. * * 2011-10-23 jensp: It is now possible to disable the use of * extra XML. */ if (useExtraXml) { for (ExtraXMLGenerator generator : item.getExtraXMLGenerators()) { generator.setListMode(listMode); generator.generateXML(item, content, state); } } } } /** * Fetches the current content item. This method can be overridden to * fetch any {@link com.arsdigita.cms.ContentItem}, but by default, * it fetches the ContentItem that is set in the page state * by the dispatcher. * * @param state The page state * @return A content item */ protected ContentItem getContentItem(PageState state) { if (CMS.getContext().hasContentItem()) { return CMS.getContext().getContentItem(); } else { CMSPage page = (CMSPage) state.getPage(); return page.getContentItem(state); } } protected void generateUDItemXML(UserDefinedContentItem UDItem, PageState state, Element parent, String useContext) { Element element = startElement(useContext, parent); Element additionalAttrs = UDItemElement(useContext); element.addAttribute("type", UDItem.getContentType().getLabel()); element.addAttribute("id", UDItem.getID().toString()); element.addAttribute("name", UDItem.getName()); element.addAttribute("title", UDItem.getTitle()); element.addAttribute("javaClass", UDItem.getContentType().getClassName()); DynamicObjectType dot = new DynamicObjectType( UDItem.getSpecificObjectType()); Iterator declaredProperties = dot.getObjectType().getDeclaredProperties(); Property currentProperty = null; Object value = null; while (declaredProperties.hasNext()) { currentProperty = (Property) declaredProperties.next(); value = (Object) UDItem.get(currentProperty.getName()); if (value != null) { element.addContent( UDItemAttrElement(currentProperty.getName(), value.toString())); } else { element.addContent( UDItemAttrElement(currentProperty.getName(), "none specified")); } } //element.addContent(additionalAttrs); //parent.addContent(element); } private Element startElement(String useContext, Element parent) { //Element element = new Element("cms:item", CMS.CMS_XML_NS); //final Element element = new Element(itemElemName, itemElemNs); final Element element = parent.newChildElement(itemElemName, itemElemNs); if (useContext != null) { element.addAttribute("useContext", useContext); } for (Map.Entry attr : itemAttributes.entrySet()) { element.addAttribute(attr.getKey(), attr.getValue()); } return element; } private Element UDItemElement(String useContext) { Element element = new Element("cms:UDItemAttributes", CMS.CMS_XML_NS); /* if ( useContext != null ) { element.addAttribute("useContext", useContext); } */ return element; } private Element UDItemAttrElement(String name, String value) { Element element = new Element("cms:UDItemAttribute", CMS.CMS_XML_NS); element.addAttribute("UDItemAttrName", name); element.addAttribute("UDItemAttrValue", value); return element; } }