diff --git a/ccm-cms/src/com/arsdigita/cms/ContentItemXMLRenderer.java b/ccm-cms/src/com/arsdigita/cms/ContentItemXMLRenderer.java index 2f8c470df..4ba983a78 100644 --- a/ccm-cms/src/com/arsdigita/cms/ContentItemXMLRenderer.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentItemXMLRenderer.java @@ -34,6 +34,7 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer { // It's purpose is to test for ContentBundle objects and if found, replace // that object with the negotiated version of the content item. // Otherwise this methd will do nothing. + @Override protected void walk(final DomainObjectTraversalAdapter adapter, final DomainObject obj, final String path, diff --git a/ccm-cms/src/com/arsdigita/cms/CustomizableContentItemXMLRenderer.java b/ccm-cms/src/com/arsdigita/cms/CustomizableContentItemXMLRenderer.java new file mode 100644 index 000000000..d8d95bbaa --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/CustomizableContentItemXMLRenderer.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2010 Jens Pelzetter, + * for the Center of Social Politics of the University of Bremen + * + * 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; + +import com.arsdigita.cms.dispatcher.SimpleXMLGenerator; +import com.arsdigita.dispatcher.DispatcherHelper; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.domain.DomainObjectTraversal; +import com.arsdigita.domain.DomainObjectTraversalAdapter; +import com.arsdigita.domain.DomainObjectXMLRenderer; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.persistence.DataAssociation; +import com.arsdigita.persistence.DataAssociationCursor; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.metadata.Property; +import com.arsdigita.web.ParameterMap; +import com.arsdigita.web.URL; +import com.arsdigita.web.Web; +import com.arsdigita.xml.Element; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.apache.log4j.Logger; + +/** + * A renderer which allows some customization of the rendering of + * data associations form the using component and therefore from a JSP file. + * + * @author Jens Pelzetter + */ +public class CustomizableContentItemXMLRenderer + extends DomainObjectXMLRenderer { + + private static final Logger s_log = Logger.getLogger( + CustomizableContentItemXMLRenderer.class); + private int m_pageSize = 20; + private String m_order; + private List m_filters; + + public CustomizableContentItemXMLRenderer(Element root) { + super(root); + m_filters = new ArrayList(); + } + + public void setPageSize(int pageSize) { + m_pageSize = pageSize; + } + + /** + * Set an order for the rendered data association(s). + * + * @param order + */ + public void setOrder(String order) { + m_order = order; + } + + /** + * Sets some filters for the rendered data associations. + * + * @param filters + */ + public void setFilters(List filters) { + m_filters = filters; + } + + /** + * Adds a filter to use for the rendered data associations. + * + * @param filter + */ + public void addFilter(String filter) { + m_filters.add(filter); + } + + /** + * Public variant of the + * {@link DomainObjectTraversal#walk(DomainObject, String, DomainObjectTraversalAdapter)} + * method. This allows it to pass an customized + * {@link DomainObjectTraversalAdapter} to the renderer which is than used + * instead of the registered TraversalAdapter. + * + * @param dobj + * @param context + * @param adapter + */ + @Override + public void walk(final DomainObject dobj, + final String context, + final DomainObjectTraversalAdapter adapter) { + super.walk(dobj, context, adapter); + } + + /** + * Copied from {@link ContentItemXMLRenderer}. + * + * @param adapter + * @param obj + * @param path + * @param context + * @param linkObject + */ + @Override + protected void walk(final DomainObjectTraversalAdapter adapter, + final DomainObject obj, + final String path, + final String context, + final DomainObject linkObject) { + + DomainObject nObj = obj; + + if (nObj instanceof ContentBundle) { + + nObj = ((ContentBundle) obj).negotiate(DispatcherHelper.getRequest(). + getLocales()); + } + + + super.walk(adapter, nObj, path, context, linkObject); + } + + /** + * Renders data associations using the provided page size to create a + * paginator (if the page size is greater than 0, set the page size to 0 or + * less to disable the paginator) and the provided order and filters to + * render data associations. + * + * @param adapter + * @param obj + * @param path + * @param context + * @param prop + * @param propName + * @param propValue + */ + @Override + protected void walkDataAssociations(DomainObjectTraversalAdapter adapter, + DomainObject obj, + String path, + String context, + Property prop, + String propName, + Object propValue) { + s_log.debug(String.format("%s is a DataAssociation", prop.getName())); + + if (m_pageSize <= 0) { + s_log.debug("pageSize is 0 or less, not using Paginator."); + super.walkDataAssociations(adapter, + obj, + path, + context, + prop, + propName, + propValue); + } else { + s_log.debug(String.format("Rendering DataAssociation using a " + + "paginator with a " + + "page size of %d", m_pageSize)); + + beginAssociation(obj, path, prop); + + DataAssociationCursor daCursor = ((DataAssociation) propValue). + getDataAssociationCursor(); + + if (daCursor.size() == 0) { + s_log.debug("No items to show, finishing assoication and " + + "returning."); + endAssociation(obj, path, prop); + return; + } + + s_log.debug("Walking daCursor..."); + s_log.debug(String.format("daCursor.size() = %d", daCursor.size())); + + //Add filters and order + if (m_order != null) { + daCursor.addOrder(m_order); + } + for (String filter : m_filters) { + daCursor.addFilter(filter); + } + + //Build paginator + + //Get pageNumber from request URL + URL requestUrl = Web.getContext().getRequestURL(); + String pageNumberValue = requestUrl.getParameter("pageNumber"); + long pageNumber; + if (pageNumberValue == null) { + pageNumber = 1; + } else { + pageNumber = Long.parseLong(pageNumberValue); + } + + long objectCount = daCursor.size(); + int pageCount = (int) Math.ceil((double) objectCount + / (double) m_pageSize); + + if (pageNumber < 1) { + pageNumber = 1; + } + + if (pageNumber > pageCount) { + if (pageCount == 0) { + pageNumber = 1; + } else { + pageNumber = pageCount; + } + } + + long begin = ((pageNumber - 1) * m_pageSize); + int count = (int) Math.min(m_pageSize, (objectCount - begin)); + long end = begin + count; + + s_log.debug("Calculted the following values for the paginator:"); + s_log.debug(String.format("pageNumber = %d", pageNumber)); + s_log.debug(String.format("objectCount = %d", objectCount)); + s_log.debug(String.format("pageCount = %d", pageCount)); + s_log.debug(String.format("begin = %d", begin)); + s_log.debug(String.format("count = %d", count)); + s_log.debug(String.format("end = %d", end)); + + if (count != 0) { + daCursor.setRange(new Integer((int) begin + 1), + new Integer((int) end + 1)); + } + + /*Element paginator = newElement(getCurrentElement(), + "nav:paginator");*/ + Element paginator = + new Element("nav:paginator", + "http://ccm.redhat.com/london/navigation"); + getCurrentElement().addContent(paginator); + + ParameterMap map = new ParameterMap(); + + if (requestUrl.getParameterMap() != null) { + Iterator current = requestUrl.getParameterMap().keySet(). + iterator(); + while (current.hasNext()) { + String key = (String) current.next(); + if (key.equals("pageNumber")) { + continue; + } + map.setParameterValues(key, requestUrl.getParameterValues( + key)); + } + } + + paginator.addAttribute("pageParam", "pageNumber"); + paginator.addAttribute("baseURL", + URL.there(requestUrl.getPathInfo(), + map).toString()); + paginator.addAttribute("pageNumber", + new Long(pageNumber).toString()); + paginator.addAttribute("pageCount", + new Long(pageCount).toString()); + paginator.addAttribute("pageSize", new Long(m_pageSize).toString()); + paginator.addAttribute("objectBegin", new Long(begin + 1).toString()); + paginator.addAttribute("objectEnd", new Long(end).toString()); + paginator.addAttribute("objectCount", + new Long(objectCount).toString()); + + int index = 0; + while (daCursor.next()) { + DataObject dobj = daCursor.getDataObject(); + ACSObject object = null; + object = (ACSObject) DomainObjectFactory.newInstance(dobj); + + //Element item = newElement(paginator, "item"); + //Element item = newElement(paginator, propName); + //appendToPath(path, "paginator"); + //Element itemPath = newElement(item, "path"); + //itemPath.setText(getStableURL(dobj, object)); + + //generateItemXML(item, dobj, object, index); + DataObject link = daCursor.getLink(); + DomainObject linkObj = null; + if (link != null) { + linkObj = new LinkDomainObject(link); + } + walk(adapter, + DomainObjectFactory.newInstance(daCursor.getDataObject()), + appendToPath(path, propName), + context, + linkObj); + + index++; + } + + //endPaginator(); + endAssociation(obj, path, prop); + } + } + + protected String getStableURL(DataObject dobj, ACSObject obj) { + OID oid = new OID((String) dobj.get(ACSObject.OBJECT_TYPE), + dobj.get(ACSObject.ID)); + + return String.format("/redirect/?oid=%s", oid.toString()); + } + + /*protected void generateItemXML(Element item, + DataObject dobj, + ACSObject obj, + int index) { + if (obj != null) { + ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(item); + renderer.setRevisitFullObject(false); + renderer.setWrapAttributes(true); + renderer.setWrapRoot(false); + renderer.setWrapObjects(false); + renderer.walk(obj, SimpleXMLGenerator.ADAPTER_CONTEXT); + } + }*/ + + /*protected Element beginPaginator() { + Element element = newElement(getCurrentElement(), "nav:paginator"); + getElementStack().push(getCurrentElement()); + setCurrentElement(element); + return element; + } + + protected Element endPaginator() { + setCurrentElement((Element) getElementStack().pop()); + return getCurrentElement(); + }*/ +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java index 8fc395a95..9666964a3 100644 --- a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java @@ -27,17 +27,19 @@ import com.arsdigita.persistence.DataCollection; * @author Jens Pelzetter */ public class GenericOrganizationalUnitPersonCollection extends DomainCollection { - + public static final String PERSON_ROLE = "link.role_name"; public GenericOrganizationalUnitPersonCollection( DataCollection dataCollection) { super(dataCollection); + dataCollection.addOrder( + "surname asc, givenname asc, titlepre asc, titlepost asc"); } - /** * Gets the name of the role of this orgaunit-person link + * @return */ public String getRoleName() { return (String) m_dataCollection.get(PERSON_ROLE); diff --git a/ccm-cms/src/com/arsdigita/cms/dispatcher/ContentPanel.java b/ccm-cms/src/com/arsdigita/cms/dispatcher/ContentPanel.java index f8f15b77b..a0ccb548a 100755 --- a/ccm-cms/src/com/arsdigita/cms/dispatcher/ContentPanel.java +++ b/ccm-cms/src/com/arsdigita/cms/dispatcher/ContentPanel.java @@ -44,12 +44,13 @@ public class ContentPanel extends SimpleComponent { } /** - * Fetches an XML Generator. This method can be overidden to fetch + * Fetches an XML Generator. This method can be overridden to fetch * any {@link com.arsdigita.cms.dispatcher.XMLGenerator}, but by default, * it fetches the XMLGenerator registered to the current * {@link com.arsdigita.cms.ContentSection}. * * @param state The page state + * @return The XMLGenerator used by this Content Panel */ protected XMLGenerator getXMLGenerator(PageState state) { ContentSection section = CMS.getContext().getContentSection(); @@ -64,9 +65,11 @@ public class ContentPanel extends SimpleComponent { * @param parent The parent DOM element * @see com.arsdigita.cms.dispatcher.XMLGenerator */ + @Override public void generateXML(PageState state, Element parent) { if (isVisible(state)) { - Element content = parent.newChildElement("cms:contentPanel", CMS.CMS_XML_NS); + Element content = parent.newChildElement("cms:contentPanel", + CMS.CMS_XML_NS); exportAttributes(content); // Generate path information about the content item @@ -78,7 +81,7 @@ public class ContentPanel extends SimpleComponent { xmlGenerator.generateXML(state, content, null); } } - + /** * Generate information about the path to this content item. * @@ -86,23 +89,27 @@ public class ContentPanel extends SimpleComponent { * @param parent the element that will contain the path info */ protected void generatePathInfoXML(PageState state, Element parent) { - Element pathInfo = parent.newChildElement("cms:pathInfo", CMS.CMS_XML_NS); - + Element pathInfo = + parent.newChildElement("cms:pathInfo", CMS.CMS_XML_NS); + if (CMS.getContext().hasContentSection()) { pathInfo.newChildElement("cms:sectionPath", CMS.CMS_XML_NS).setText( CMS.getContext().getContentSection().getPath()); } String url = DispatcherHelper.getRequestContext().getRemainingURLPart(); if (url.startsWith(CMSDispatcher.PREVIEW)) { - pathInfo.newChildElement("cms:previewPath", CMS.CMS_XML_NS).setText(ContentSectionServlet.PREVIEW); + pathInfo.newChildElement("cms:previewPath", CMS.CMS_XML_NS).setText( + ContentSectionServlet.PREVIEW); } pathInfo.newChildElement("cms:templatePrefix", CMS.CMS_XML_NS).setText( "/" + AbstractItemResolver.TEMPLATE_CONTEXT_PREFIX); if (CMS.getContext().hasContentItem()) { ContentItem item = CMS.getContext().getContentItem(); - ContentItem bundle = (ContentItem) item.getDraftVersion().getParent(); - pathInfo.newChildElement("cms:itemPath", CMS.CMS_XML_NS).setText("/" + bundle.getPath()); + ContentItem bundle = + (ContentItem) item.getDraftVersion().getParent(); + pathInfo.newChildElement("cms:itemPath", CMS.CMS_XML_NS).setText("/" + bundle. + getPath()); } } } diff --git a/ccm-core/src/com/arsdigita/domain/DomainObjectTraversal.java b/ccm-core/src/com/arsdigita/domain/DomainObjectTraversal.java index 2dbe63494..a06597e81 100755 --- a/ccm-core/src/com/arsdigita/domain/DomainObjectTraversal.java +++ b/ccm-core/src/com/arsdigita/domain/DomainObjectTraversal.java @@ -102,7 +102,7 @@ public abstract class DomainObjectTraversal { } /** - * Unregisteres a traversal adapter for an object type in a + * Unregisters a traversal adapter for an object type in a * given context * * @param type the object type whose items will be traversed @@ -131,14 +131,14 @@ public abstract class DomainObjectTraversal { */ public static void registerAdapter(final String type, final DomainObjectTraversalAdapter adapter, - final String context) { + final String context) { registerAdapter(SessionManager.getMetadataRoot().getObjectType(type), adapter, context); } /** - * Unregisteres a traversal adapter for an object type in a + * Unregisters a traversal adapter for an object type in a * given context * * @param type the object type whose items will be traversed @@ -159,7 +159,7 @@ public abstract class DomainObjectTraversal { */ public static DomainObjectTraversalAdapter lookupAdapter( final ObjectType type, - final String context) { + final String context) { Assert.exists(type, ObjectType.class); Assert.exists(context, String.class); if (s_log.isDebugEnabled()) { @@ -252,7 +252,8 @@ public abstract class DomainObjectTraversal { final String path, final String context, final DomainObject linkObject) { - s_log.debug(String.format("Walking with path %s and context %s...", path, context)); + s_log.debug(String.format("Walking with path %s and context %s...", path, + context)); OID oid = obj.getOID(); OID linkOid = null; if (linkObject != null) { @@ -311,8 +312,8 @@ public abstract class DomainObjectTraversal { if (prop.isAttribute()) { handleAttribute(obj, path, prop); - // Property is a DataObject, so start recursion } else if (propValue instanceof DataObject) { + // Property is a DataObject, so start recursion if (s_log.isDebugEnabled()) { s_log.debug(prop.getName() + " is a DataObject"); } @@ -355,31 +356,40 @@ public abstract class DomainObjectTraversal { } } else { - - if (s_log.isDebugEnabled()) { - s_log.debug(prop.getName() + " is a DataAssociation"); + //2010-11-08: Moved to seperate Methods to allow simple + //extending of the handling of data assocications + /*if (s_log.isDebugEnabled()) { + s_log.debug(prop.getName() + " is a DataAssociation"); } beginAssociation(obj, path, prop); DataAssociationCursor daCursor = - ((DataAssociation) propValue). - getDataAssociationCursor(); + ((DataAssociation) propValue). + getDataAssociationCursor(); while (daCursor.next()) { - s_log.debug("Processing data assoication cursor..."); - DataObject link = daCursor.getLink(); - DomainObject linkObj = null; - if (link != null) { - linkObj = new LinkDomainObject(link); - } - walk(adapter, - DomainObjectFactory.newInstance(daCursor. - getDataObject()), - appendToPath(path, propName), - context, - linkObj); + s_log.debug("Processing data assoication cursor..."); + DataObject link = daCursor.getLink(); + DomainObject linkObj = null; + if (link != null) { + linkObj = new LinkDomainObject(link); } - endAssociation(obj, path, prop); + walk(adapter, + DomainObjectFactory.newInstance(daCursor. + getDataObject()), + appendToPath(path, propName), + context, + linkObj); + } + endAssociation(obj, path, prop);*/ + + walkDataAssociations(adapter, + obj, + path, + context, + prop, + propName, + propValue); } } else { // Unknown property value type - do nothing @@ -390,6 +400,52 @@ public abstract class DomainObjectTraversal { endObject(obj, path); } + protected void walkDataAssociations(DomainObjectTraversalAdapter adapter, + DomainObject obj, + String path, + String context, + Property prop, + String propName, + Object propValue) { + s_log.debug(String.format("%s is a DataAssociation", prop.getName())); + + beginAssociation(obj, path, prop); + + DataAssociationCursor daCursor = + ((DataAssociation) propValue). + getDataAssociationCursor(); + + while (daCursor.next()) { + walkDataAssociation(adapter, + obj, + path, + context, + propName, + daCursor); + } + + endAssociation(obj, path, prop); + } + + protected void walkDataAssociation(DomainObjectTraversalAdapter adapter, + DomainObject obj, + String path, + String context, + String propName, + DataAssociationCursor daCursor) { + s_log.debug("Processing data assoication cursor..."); + DataObject link = daCursor.getLink(); + DomainObject linkObj = null; + if (link != null) { + linkObj = new LinkDomainObject(link); + } + walk(adapter, + DomainObjectFactory.newInstance(daCursor.getDataObject()), + appendToPath(path, propName), + context, + linkObj); + } + /** * Method called when the processing of an object * starts @@ -534,9 +590,9 @@ public abstract class DomainObjectTraversal { * this is simply a subclass since DomainObject is abstract * but we don't have any other domain object to use. */ - private class LinkDomainObject extends DomainObject { + protected class LinkDomainObject extends DomainObject { - LinkDomainObject(DataObject object) { + public LinkDomainObject(DataObject object) { super(object); } } diff --git a/ccm-core/src/com/arsdigita/domain/DomainObjectXMLRenderer.java b/ccm-core/src/com/arsdigita/domain/DomainObjectXMLRenderer.java index 7ddaef97a..71814cdbc 100755 --- a/ccm-core/src/com/arsdigita/domain/DomainObjectXMLRenderer.java +++ b/ccm-core/src/com/arsdigita/domain/DomainObjectXMLRenderer.java @@ -419,6 +419,14 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal { return m_element; } + protected void setCurrentElement(Element element) { + m_element = element; + } + + protected Stack getElementStack() { + return m_elements; + } + protected Element newElement(Element parent, String name) { return m_namespaceURI == null ? diff --git a/ccm-core/src/com/arsdigita/domain/SimpleDomainObjectTraversalAdapter.java b/ccm-core/src/com/arsdigita/domain/SimpleDomainObjectTraversalAdapter.java index c24a42db2..e157d20d9 100755 --- a/ccm-core/src/com/arsdigita/domain/SimpleDomainObjectTraversalAdapter.java +++ b/ccm-core/src/com/arsdigita/domain/SimpleDomainObjectTraversalAdapter.java @@ -33,12 +33,12 @@ import java.util.HashSet; * *

See com.arsdigita.cms.installer.DomainObjectTraversalInitializer. */ -public class SimpleDomainObjectTraversalAdapter - implements DomainObjectTraversalAdapter { - - private static final Logger s_log = - Logger.getLogger(SimpleDomainObjectTraversalAdapter.class); - +public class SimpleDomainObjectTraversalAdapter + implements DomainObjectTraversalAdapter { + + private static final Logger s_log = + Logger.getLogger( + SimpleDomainObjectTraversalAdapter.class); /** * Rule that indicates the set of properties should be treated * as an inclusion list. ie, don't allow any properties except @@ -51,15 +51,12 @@ public class SimpleDomainObjectTraversalAdapter * except those listed. This is the default for attributes. */ public final static int RULE_EXCLUDE = 1; - private HashSet m_attr = new HashSet(); private HashSet m_assoc = new HashSet(); - private int m_attrRule = RULE_EXCLUDE; private int m_assocRule = RULE_INCLUDE; - private SimpleDomainObjectTraversalAdapter m_parent; - + /** * Creates a new traversal adapter, with no parent * delegate. If no explicit rule is present it will @@ -78,11 +75,18 @@ public class SimpleDomainObjectTraversalAdapter * @param parent the parent adapter to delegate to */ public SimpleDomainObjectTraversalAdapter( - SimpleDomainObjectTraversalAdapter parent - ) { + SimpleDomainObjectTraversalAdapter parent) { m_parent = parent; } + public SimpleDomainObjectTraversalAdapter getParent() { + return m_parent; + } + + public int getAttributeRule() { + return m_attrRule; + } + /** * Set the rule for processing attributes * @@ -92,6 +96,10 @@ public class SimpleDomainObjectTraversalAdapter m_attrRule = rule; } + public int getAssociationRule() { + return m_assocRule; + } + /** * Set the rule for processing associations * @@ -100,7 +108,11 @@ public class SimpleDomainObjectTraversalAdapter public void setAssociationRule(int rule) { m_assocRule = rule; } - + + public HashSet getAttributeProperties() { + return m_attr; + } + /** * Add a property to the attribute property set. * @@ -116,9 +128,21 @@ public class SimpleDomainObjectTraversalAdapter * @param prop full path of the property to remove */ public void removeAttributeProperty(String prop) { + s_log.debug(String.format("Removing attribute property '%s'", prop)); m_attr.remove(prop); } + /** + * Clears the property set. + */ + public void clearAttributeProperties() { + m_attr.clear(); + } + + public HashSet getAssociationProperties() { + return m_assoc; + } + /** * Add a property to the association property set. * @@ -134,9 +158,17 @@ public class SimpleDomainObjectTraversalAdapter * @param prop full path of the property to remove */ public void removeAssociationProperty(String prop) { + s_log.debug(String.format("Removing association property '%s'", prop)); m_assoc.remove(prop); } - + + /** + * Clears the association properties set. + */ + public void clearAssociationProperties() { + m_assoc.clear(); + } + /** * Determines whether or not to allow processing * of a property, based on the property set and @@ -149,8 +181,8 @@ public class SimpleDomainObjectTraversalAdapter if (prop.isAttribute()) { boolean result = m_attr.contains(path); if (s_log.isDebugEnabled()) { - s_log.debug("Check attr " + path + " contains " + - result + " " + m_attrRule); + s_log.debug("Check attr " + path + " contains " + result + " " + + m_attrRule); } if (!result && m_parent != null) { if (s_log.isDebugEnabled()) { @@ -162,8 +194,8 @@ public class SimpleDomainObjectTraversalAdapter } else { boolean result = m_assoc.contains(path); if (s_log.isDebugEnabled()) { - s_log.debug("Check assoc " + path + " contains " + - result + " " + m_assocRule); + s_log.debug("Check assoc " + path + " contains " + result + " " + + m_assocRule); } if (!result && m_parent != null) { if (s_log.isDebugEnabled()) { diff --git a/ccm-core/src/log4j.properties b/ccm-core/src/log4j.properties index f3a683566..252371a4b 100755 --- a/ccm-core/src/log4j.properties +++ b/ccm-core/src/log4j.properties @@ -63,3 +63,4 @@ log4j.logger.com.arsdigita.packaging.Loader=INFO log4j.logger.com.arsdigita.cms.search.ContentPageMetadataProvider=DEBUG log4j.logger.com.arsdigita.london.importer=DEBUG +log4j.logger.com.arsdigita.london.terms.importer.TermItemBuilder=DEBUG \ No newline at end of file diff --git a/ccm-core/web/assets/xinha/XinhaConfig.js b/ccm-core/web/assets/xinha/XinhaConfig.js index d39daff3b..ff126d004 100644 --- a/ccm-core/web/assets/xinha/XinhaConfig.js +++ b/ccm-core/web/assets/xinha/XinhaConfig.js @@ -5,7 +5,8 @@ xinha_init=null; xinha_config=null; xinha_init=xinha_init?xinha_init:function(){ xinha_editors=xinha_editors?xinha_editors:["myTextArea","anotherOne"]; -xinha_plugins=xinha_plugins?xinha_plugins:["CharacterMap","ContextMenu","SmartReplace","Stylist","Linker","SuperClean","TableOperations"]; +//xinha_plugins=xinha_plugins?xinha_plugins:["CharacterMap","ContextMenu","SmartReplace","Stylist","Linker","SuperClean","TableOperations"]; +xinha_plugins=xinha_plugins?xinha_plugins:["CharacterMap","ContextMenu","SmartReplace","Stylist","SuperClean","TableOperations"]; if(!Xinha.loadPlugins(xinha_plugins,xinha_init)){ return; } diff --git a/ccm-core/web/assets/xinha/modules/CreateLink/link.html b/ccm-core/web/assets/xinha/modules/CreateLink/link.html index adad40058..aa224209a 100755 --- a/ccm-core/web/assets/xinha/modules/CreateLink/link.html +++ b/ccm-core/web/assets/xinha/modules/CreateLink/link.html @@ -98,6 +98,17 @@ function onCancel() { return false; } +function onBrowse(){ + baseURL = opener.location.pathname; + offset = baseURL.lastIndexOf("/"); + destURL = baseURL.slice(0, offset+1) + "search.jsp?useURL=true&widget=getElementById('f_href')"; + aWindow = window.open(destURL, + "search", + "toolbar=no,width=800,height=600,status=no,scrollbars=yes,resize=yes,menubar=no"); + return false; +} + + @@ -108,7 +119,10 @@ function onCancel() { - + @@ -133,4 +147,4 @@ function onCancel() { - \ No newline at end of file + diff --git a/ccm-core/web/assets/xinha/plugins/Linker/dialog.html b/ccm-core/web/assets/xinha/plugins/Linker/dialog.html index 27ce9d5cc..18cb93f6b 100755 --- a/ccm-core/web/assets/xinha/plugins/Linker/dialog.html +++ b/ccm-core/web/assets/xinha/plugins/Linker/dialog.html @@ -11,7 +11,9 @@
URL: + +
Title (tooltip):
- + @@ -104,4 +106,4 @@ - \ No newline at end of file + diff --git a/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/CustomizableGreetingItem.java b/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/CustomizableGreetingItem.java new file mode 100644 index 000000000..d585bb309 --- /dev/null +++ b/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/CustomizableGreetingItem.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2010 Jens Pelzetter, + * for the Center of Social Politics of the University of Bremen + * + * 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.london.navigation.ui; + +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.CustomizableContentItemXMLRenderer; +import com.arsdigita.cms.dispatcher.SimpleXMLGenerator; +import com.arsdigita.domain.DomainObjectTraversal; +import com.arsdigita.domain.DomainObjectTraversalAdapter; +import com.arsdigita.domain.SimpleDomainObjectTraversalAdapter; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.metadata.ObjectType; +import com.arsdigita.xml.Element; +import java.util.ArrayList; +import java.util.List; +import org.apache.log4j.Logger; + +/** + *

+ * This is a more customizable variant of the {@link GreetingItem} component. + * It uses the {@link CustomizableContentItemXMLRenderer} for rendering the + * item. + *

+ *

+ * This component provides an method to access the traversal adapter which is + * used to control which properties of the greeting item are rendered and which + * are not put into the XML output. You can create an completely new + * adapter, or copy the one which is registered for the rendered item. + *

+ *

+ * The manipulations are done in a JSP file. An example: + *

+ *
+ *  <define:component name="greetingItem"
+ *                       classname="com.arsdigita.london.navigation.ui.CustomizableGreetingItem"/>
+ *     <jsp:scriptlet>
+ *        ((com.arsdigita.london.navigation.ui.CustomizableGreetingItem) greetingItem).loadTraversalAdapter("com.arsdigita.cms.contenttypes.SciOrganization",
+ *                          SimpleXMLGenerator.ADAPTER_CONTEXT);
+ *      ((com.arsdigita.london.navigation.ui.CustomizableGreetingItem) greetingItem).getTraversalAdapter().clearAssociationProperties();
+ *      ((com.arsdigita.london.navigation.ui.CustomizableGreetingItem) greetingItem).getTraversalAdapter().addAssociationProperty("/object/persons");
+ *      ((com.arsdigita.london.navigation.ui.CustomizableGreetingItem) greetingItem).setOrder("surname asc, givenname asc");
+ *
+ *       ((com.arsdigita.london.navigation.ui.CustomizableGreetingItem) greetingItem).setPageSize(5);
+ *      </jsp:scriptlet>
+ * 
+ *

+ * As you might notice, you have to know the type of the greeting item to use + * the {@link #loadTraversalAdapter(String, String)} method if you want to + * copy the traversal adapter. + *

+ * + * @see SimpleDomainObjectTraversalAdapter + * @see CustomizableContentItemXMLRenderer + * + * @author Jens Pelzetter + */ +public class CustomizableGreetingItem extends GreetingItem { + + private static final Logger s_log = Logger.getLogger( + CustomizableGreetingItem.class); + private SimpleDomainObjectTraversalAdapter adapter; + private int m_pageSize = 20; + private String m_order; + private List m_filters; + + public CustomizableGreetingItem() { + super(); + adapter = new SimpleDomainObjectTraversalAdapter(); + m_filters = new ArrayList(); + + /*adapter.setAssociationRule( + SimpleDomainObjectTraversalAdapter.RULE_INCLUDE); + adapter.setAttributeRule(SimpleDomainObjectTraversalAdapter.RULE_INCLUDE); + adapter.addAttributeProperty("/object/title"); + adapter.addAttributeProperty("/object/name"); + adapter.addAttributeProperty("/object/addendum"); + adapter.addAttributeProperty("/object/organizationShortDescription"); + adapter.addAttributeProperty("/object/organizationDescription"); + adapter.addAssociationProperty("/object/persons");*/ + + //loadTraversalAdapter("com.arsdigita.cms.contenttypes.SciOrganization", + // SimpleXMLGenerator.ADAPTER_CONTEXT); + + //adapter.removeAssociationProperty("/object/persons"); + } + + /** + * Set the page size to use for rendering association properties. Set to 0 + * or less to deactivated the paginator. + * + * @param pageSize + */ + public void setPageSize(int pageSize) { + m_pageSize = pageSize; + } + + /** + * Set an order for the rendered data associations. + * + * @param order + */ + public void setOrder(String order) { + m_order = order; + } + + /** + * Add a filter for the rendered data associations. + * + * @param filter + */ + public void addFilter(String filter) { + m_filters.add(filter); + } + + /** + * Copies the traversal adapter for type and + * context. Caution: Do not manipulate the parent adapters! + * + * @param type + * @param context + */ + public void loadTraversalAdapter(String type, String context) { + ObjectType objType; + DomainObjectTraversalAdapter dotAdapter; + + s_log.debug(String.format("Loading traversal adapter for type '%s' " + + "and context '%s'", + type, + context)); + objType = SessionManager.getMetadataRoot().getObjectType(type); + dotAdapter = DomainObjectTraversal.findAdapter(objType, context); + + if (dotAdapter instanceof SimpleDomainObjectTraversalAdapter) { + SimpleDomainObjectTraversalAdapter sourceAdapter; + + sourceAdapter = (SimpleDomainObjectTraversalAdapter) dotAdapter; + + //adapter = (SimpleDomainObjectTraversalAdapter) dotAdapter; + + adapter = new SimpleDomainObjectTraversalAdapter(sourceAdapter. + getParent()); + adapter.setAttributeRule(sourceAdapter.getAttributeRule()); + adapter.setAssociationRule(sourceAdapter.getAssociationRule()); + for (Object prop : sourceAdapter.getAttributeProperties()) { + adapter.addAttributeProperty((String) prop); + } + + for (Object prop : sourceAdapter.getAssociationProperties()) { + adapter.addAssociationProperty((String) prop); + } + } else { + s_log.warn(String.format("Registered traversal adapter for type " + + "'%s' and context '%s' is not an instance " + + "of SimpleDomainObjectTraversalAdapter " + + "and therefore not " + + "usable with this class. ", + type, + context)); + } + + } + + public SimpleDomainObjectTraversalAdapter getTraversalAdapter() { + return adapter; + } + + /** + * Creates the XML for the GreetingItem using + * {@link CustomizableContentItemXMLRenderer}. The adapter and the other + * parameters for rendering are passed to the renderer. + * + * @param parent + * @param item + */ + @Override + protected void generateGreetingItemXml(Element parent, ContentItem item) { + CustomizableContentItemXMLRenderer renderer = + new CustomizableContentItemXMLRenderer( + parent); + renderer.setWrapAttributes(true); + renderer.setWrapRoot(false); + renderer.setWrapObjects(false); + + renderer.setPageSize(m_pageSize); + renderer.setOrder(m_order); + renderer.setFilters(m_filters); + + renderer.walk(item, SimpleXMLGenerator.ADAPTER_CONTEXT, adapter); + //renderer.walk(item, SimpleXMLGenerator.ADAPTER_CONTEXT); + + + } +} diff --git a/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/GreetingItem.java b/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/GreetingItem.java index f5d8710bb..eff4409b9 100755 --- a/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/GreetingItem.java +++ b/ccm-ldn-navigation/src/com/arsdigita/london/navigation/ui/GreetingItem.java @@ -15,7 +15,6 @@ * 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.london.navigation.ui; import javax.servlet.http.HttpServletRequest; @@ -50,20 +49,21 @@ import com.arsdigita.xml.Element; * @version $Id: GreetingItem.java 1473 2007-03-12 15:16:39Z chrisgilbert23 $ */ public class GreetingItem extends AbstractComponent { - private static final Logger s_log = Logger.getLogger( GreetingItem.class ); - + + private static final Logger s_log = Logger.getLogger(GreetingItem.class); + public Element generateXML(HttpServletRequest request, - HttpServletResponse response) { - ContentItem item = (ContentItem)getObject(); + HttpServletResponse response) { + ContentItem item = (ContentItem) getObject(); if (null == item || !item.isLive()) { return null; } - + if (!ContentItem.VERSION.equals(item.getVersion())) { item = item.getLiveVersion(); } - - + + Element content = Navigation.newElement("greetingItem"); Party currentParty = Kernel.getContext().getParty(); if (currentParty == null) { @@ -74,18 +74,20 @@ public class GreetingItem extends AbstractComponent { // // Note that the xml that is generated is only of use if you DO NOT CACHE index pages. // cg. - - PermissionDescriptor edit = new PermissionDescriptor(PrivilegeDescriptor.get(SecurityManager.CMS_EDIT_ITEM), item, currentParty); + + PermissionDescriptor edit = new PermissionDescriptor(PrivilegeDescriptor. + get(SecurityManager.CMS_EDIT_ITEM), item, currentParty); if (PermissionService.checkPermission(edit)) { content.addAttribute("canEdit", "true"); } - PermissionDescriptor publish = new PermissionDescriptor(PrivilegeDescriptor.get(SecurityManager.CMS_PUBLISH), item, currentParty); + PermissionDescriptor publish = new PermissionDescriptor(PrivilegeDescriptor. + get(SecurityManager.CMS_PUBLISH), item, currentParty); if (PermissionService.checkPermission(publish)) { content.addAttribute("canPublish", "true"); } - - ContentBundle bundle = (ContentBundle)item; - + + ContentBundle bundle = (ContentBundle) item; + /* Fix by Jens Pelzetter, 2009-08-28 * bundle.getPrimaryInstance() does not about the preferred languages * of the User Client, instead it returns the primary instance of @@ -98,23 +100,41 @@ public class GreetingItem extends AbstractComponent { //ContentItem baseItem = bundle.getPrimaryInstance(); ContentItem baseItem = bundle.negotiate(request.getLocales()); // If there is no matching language version for this content item - if(baseItem == null) { + if (baseItem == null) { // get the primary instance instead (fallback) baseItem = bundle.getPrimaryInstance(); } Element itemEl = content.newChildElement("cms:item", - CMS.CMS_XML_NS); - - ContentItemXMLRenderer renderer = - new ContentItemXMLRenderer(itemEl); - - renderer.setWrapAttributes( true ); - renderer.setWrapRoot( false ); - renderer.setWrapObjects( false ); - - renderer.walk( baseItem, SimpleXMLGenerator.ADAPTER_CONTEXT ); - + CMS.CMS_XML_NS); + + //Moved to seperate method generateGreetingItemXml to make to + //XML generation extendable (use another renderer etc.) + /*ContentItemXMLRenderer renderer = + new ContentItemXMLRenderer(itemEl); + + renderer.setWrapAttributes(true); + renderer.setWrapRoot(false); + renderer.setWrapObjects(false); + + renderer.walk(baseItem, SimpleXMLGenerator.ADAPTER_CONTEXT);*/ + + generateGreetingItemXml(itemEl, baseItem); + return content; } - + + /** + * Creates the XML for the greeting item. + * + * @param parent The parent element + * @param item The item to render + */ + protected void generateGreetingItemXml(Element parent, ContentItem item) { + ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(parent); + renderer.setWrapAttributes(true); + renderer.setWrapRoot(false); + renderer.setWrapObjects(false); + + renderer.walk(item, SimpleXMLGenerator.ADAPTER_CONTEXT); + } } diff --git a/ccm-ldn-terms/src/com/arsdigita/london/terms/importer/TermItemBuilder.java b/ccm-ldn-terms/src/com/arsdigita/london/terms/importer/TermItemBuilder.java index 76b6ecdf7..46dd3738a 100755 --- a/ccm-ldn-terms/src/com/arsdigita/london/terms/importer/TermItemBuilder.java +++ b/ccm-ldn-terms/src/com/arsdigita/london/terms/importer/TermItemBuilder.java @@ -56,6 +56,8 @@ public class TermItemBuilder { SiteNode node = null; try { + s_log.debug(String.format("Trying to get SiteNode for path '%s", + path)); node = SiteNode.getSiteNode(path); } catch (DataObjectNotFoundException ex) { s_log.error("Couldn't fetch sitenode for " + path); @@ -63,7 +65,7 @@ public class TermItemBuilder { } ContentSection section = null; - section = ContentSection.getSectionFromNode(node); + section = ContentSection.getSectionFromNode(node); String[] bits = StringUtils.split( path.substring(node.getURL().length(),
Target: