Some performance improvements for rendering Content Items.
git-svn-id: https://svn.libreccm.org/ccm/trunk@2068 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
a65452489f
commit
526c5fa1d4
|
|
@ -34,7 +34,7 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
private String m_keyName = "";
|
private String m_keyName = "";
|
||||||
private String m_relationAttribute = "";
|
private String m_relationAttribute = "";
|
||||||
|
|
||||||
public ContentItemXMLRenderer(Element root) {
|
public ContentItemXMLRenderer(final Element root) {
|
||||||
super(root);
|
super(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,8 +54,7 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
|
|
||||||
if (nObj instanceof ContentBundle) {
|
if (nObj instanceof ContentBundle) {
|
||||||
|
|
||||||
nObj = ((ContentBundle) obj).
|
nObj = ((ContentBundle) obj).getInstance(GlobalizationHelper.getNegotiatedLocale(), true);
|
||||||
getInstance(GlobalizationHelper.getNegotiatedLocale(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.walk(adapter, nObj, path, context, linkObject);
|
super.walk(adapter, nObj, path, context, linkObject);
|
||||||
|
|
@ -64,22 +63,18 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleAttribute(DomainObject obj,
|
protected void handleAttribute(final DomainObject obj, final String path, final Property property) {
|
||||||
String path,
|
final String propertyName = property.getName();
|
||||||
Property property) {
|
|
||||||
|
|
||||||
String propertyName = property.getName();
|
|
||||||
|
|
||||||
// Special handling for the isoCountryCode field in GenericAddress
|
// Special handling for the isoCountryCode field in GenericAddress
|
||||||
if (obj instanceof GenericAddress) {
|
if (obj instanceof GenericAddress && "isoCountryCode".equals(propertyName)) {
|
||||||
if (propertyName.equals("isoCountryCode")) {
|
//if (propertyName.equals("isoCountryCode")) {
|
||||||
super.handleAttribute(obj, path, property);
|
super.handleAttribute(obj, path, property);
|
||||||
|
|
||||||
|
final Element element = newElement(m_element, "country");
|
||||||
|
element.setText(GenericAddress.getCountryNameFromIsoCode(((GenericAddress) obj).getIsoCountryCode()));
|
||||||
|
return;
|
||||||
|
|
||||||
Element element = newElement(m_element, "country");
|
|
||||||
element.setText(GenericAddress.getCountryNameFromIsoCode(((GenericAddress) obj).
|
|
||||||
getIsoCountryCode()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special handling for the relation attribute keys
|
// Special handling for the relation attribute keys
|
||||||
|
|
@ -91,8 +86,7 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
&& ((RelationAttributeInterface) obj).
|
&& ((RelationAttributeInterface) obj).
|
||||||
hasRelationAttributeProperty(propertyName)) {
|
hasRelationAttributeProperty(propertyName)) {
|
||||||
|
|
||||||
RelationAttributeInterface relationAttributeObject =
|
final RelationAttributeInterface relationAttributeObject = (RelationAttributeInterface) obj;
|
||||||
(RelationAttributeInterface) obj;
|
|
||||||
key = relationAttributeObject.getRelationAttributeKey(
|
key = relationAttributeObject.getRelationAttributeKey(
|
||||||
propertyName);
|
propertyName);
|
||||||
|
|
||||||
|
|
@ -102,25 +96,23 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
if (obj instanceof LinkDomainObject
|
if (obj instanceof LinkDomainObject
|
||||||
&& propertyName.equals(m_keyName)) {
|
&& propertyName.equals(m_keyName)) {
|
||||||
key = (String) ((LinkDomainObject) obj).get(m_keyName);
|
key = (String) ((LinkDomainObject) obj).get(m_keyName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace value of the property defined in RELATION_ATTRIBUTES string
|
// Replace value of the property defined in RELATION_ATTRIBUTES string
|
||||||
// of the primary domain object with the localized String.
|
// of the primary domain object with the localized String.
|
||||||
if (!key.isEmpty()) {
|
if (!key.isEmpty()) {
|
||||||
logger.debug(String.format(
|
// logger.debug(String.format(
|
||||||
"Getting relation attribute value for key '%s' of relation attribute '%s'",
|
// "Getting relation attribute value for key '%s' of relation attribute '%s'",
|
||||||
key, m_relationAttribute));
|
// key, m_relationAttribute));
|
||||||
RelationAttributeCollection relationAttributeCollection =
|
final RelationAttributeCollection relationAttributeCollection = new RelationAttributeCollection(
|
||||||
new RelationAttributeCollection(
|
|
||||||
m_relationAttribute, key);
|
m_relationAttribute, key);
|
||||||
relationAttributeCollection.addLanguageFilter(GlobalizationHelper.
|
relationAttributeCollection.addLanguageFilter(GlobalizationHelper.
|
||||||
getNegotiatedLocale().getLanguage());
|
getNegotiatedLocale().getLanguage());
|
||||||
if (relationAttributeCollection.size() > 0) {
|
if (!relationAttributeCollection.isEmpty()) {
|
||||||
relationAttributeCollection.next();
|
relationAttributeCollection.next();
|
||||||
Element element = newElement(m_element, m_keyName);
|
final Element element = newElement(m_element, m_keyName);
|
||||||
element.setText(relationAttributeCollection.getName());
|
element.setText(relationAttributeCollection.getName());
|
||||||
Element elementId = newElement(m_element, m_keyName + "Id");
|
final Element elementId = newElement(m_element, m_keyName + "Id");
|
||||||
elementId.setText(relationAttributeCollection.getKey());
|
elementId.setText(relationAttributeCollection.getKey());
|
||||||
relationAttributeCollection.close();
|
relationAttributeCollection.close();
|
||||||
}
|
}
|
||||||
|
|
@ -132,31 +124,26 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beginAssociation(DomainObject obj, String path,
|
protected void beginAssociation(final DomainObject obj, final String path, final Property property) {
|
||||||
Property property) {
|
|
||||||
super.beginAssociation(obj, path, property);
|
super.beginAssociation(obj, path, property);
|
||||||
|
|
||||||
String propertyName = property.getName();
|
final String propertyName = property.getName();
|
||||||
|
|
||||||
if (obj instanceof RelationAttributeInterface
|
if (obj instanceof RelationAttributeInterface
|
||||||
&& ((RelationAttributeInterface) obj).hasRelationAttributeProperty(
|
&& ((RelationAttributeInterface) obj).hasRelationAttributeProperty(
|
||||||
propertyName)) {
|
propertyName)) {
|
||||||
|
|
||||||
RelationAttributeInterface relationAttributeObject =
|
final RelationAttributeInterface relationAttributeObject = (RelationAttributeInterface) obj;
|
||||||
(RelationAttributeInterface) obj;
|
|
||||||
|
|
||||||
m_propertyName = propertyName;
|
m_propertyName = propertyName;
|
||||||
m_keyName = relationAttributeObject.getRelationAttributeKeyName(
|
m_keyName = relationAttributeObject.getRelationAttributeKeyName(propertyName);
|
||||||
propertyName);
|
m_relationAttribute = relationAttributeObject.getRelationAttributeName(propertyName);
|
||||||
m_relationAttribute = relationAttributeObject.
|
|
||||||
getRelationAttributeName(propertyName);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void endAssociation(DomainObject obj, String path,
|
protected void endAssociation(final DomainObject obj, final String path, final Property property) {
|
||||||
Property property) {
|
|
||||||
|
|
||||||
m_propertyName = "";
|
m_propertyName = "";
|
||||||
m_keyName = "";
|
m_keyName = "";
|
||||||
|
|
@ -164,4 +151,5 @@ public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
||||||
|
|
||||||
super.endAssociation(obj, path, property);
|
super.endAssociation(obj, path, property);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,15 @@ public class GenericPersonExtraXmlGenerator implements ExtraXMLGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
final GenericPerson person = (GenericPerson) item;
|
final GenericPerson person = (GenericPerson) item;
|
||||||
|
//final long start = System.nanoTime();
|
||||||
final GenericPersonContactCollection contacts = person.getContacts();
|
final GenericPersonContactCollection contacts = person.getContacts();
|
||||||
|
//System.out.printf("Got contacts in %d ms\n", (System.nanoTime() - start) / 1000000);
|
||||||
|
|
||||||
final Element contactsElem = element.newChildElement("contacts");
|
final Element contactsElem = element.newChildElement("contacts");
|
||||||
while (contacts.next()) {
|
while (contacts.next()) {
|
||||||
|
//final long start2 = System.nanoTime();
|
||||||
final GenericContact contact = contacts.getContact(GlobalizationHelper.getNegotiatedLocale().getLanguage());
|
final GenericContact contact = contacts.getContact(GlobalizationHelper.getNegotiatedLocale().getLanguage());
|
||||||
|
//System.err.printf("Got contact in %d ms from collection\n", (System.nanoTime() - start2) / 1000000);
|
||||||
generateContactXml(
|
generateContactXml(
|
||||||
contactsElem,
|
contactsElem,
|
||||||
contact,
|
contact,
|
||||||
|
|
@ -43,10 +47,12 @@ public class GenericPersonExtraXmlGenerator implements ExtraXMLGenerator {
|
||||||
private void generateContactXml(final Element contactsElem,
|
private void generateContactXml(final Element contactsElem,
|
||||||
final GenericContact contact,
|
final GenericContact contact,
|
||||||
final PageState state) {
|
final PageState state) {
|
||||||
|
//final long start = System.nanoTime();
|
||||||
final XmlGenerator generator = new XmlGenerator(contact);
|
final XmlGenerator generator = new XmlGenerator(contact);
|
||||||
generator.setItemElemName("contact", "");
|
generator.setItemElemName("contact", "");
|
||||||
generator.addItemAttribute("contactType", contact.getContactType());
|
generator.addItemAttribute("contactType", contact.getContactType());
|
||||||
generator.generateXML(state, contactsElem, "");
|
generator.generateXML(state, contactsElem, "");
|
||||||
|
//System.err.printf("Generated XML for a contact in %d ms\n", (System.nanoTime() - start) / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addGlobalStateParams(final Page page) {
|
public void addGlobalStateParams(final Page page) {
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.cms.dispatcher;
|
package com.arsdigita.cms.dispatcher;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.cms.CMS;
|
import com.arsdigita.cms.CMS;
|
||||||
import com.arsdigita.cms.ContentItem;
|
import com.arsdigita.cms.ContentItem;
|
||||||
import com.arsdigita.cms.ContentItemXMLRenderer;
|
import com.arsdigita.cms.ContentItemXMLRenderer;
|
||||||
import com.arsdigita.cms.ContentSection;
|
|
||||||
import com.arsdigita.cms.ExtraXMLGenerator;
|
import com.arsdigita.cms.ExtraXMLGenerator;
|
||||||
import com.arsdigita.cms.SecurityManager;
|
import com.arsdigita.cms.SecurityManager;
|
||||||
import com.arsdigita.cms.UserDefinedContentItem;
|
import com.arsdigita.cms.UserDefinedContentItem;
|
||||||
|
|
@ -42,6 +40,7 @@ import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.persistence.metadata.Property;
|
import com.arsdigita.persistence.metadata.Property;
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
import com.arsdigita.xml.Element;
|
import com.arsdigita.xml.Element;
|
||||||
|
import java.util.HashMap;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
@ -57,10 +56,8 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class SimpleXMLGenerator implements XMLGenerator {
|
public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
|
|
||||||
private static final Logger s_log =
|
private static final Logger s_log = Logger.getLogger(SimpleXMLGenerator.class);
|
||||||
Logger.getLogger(SimpleXMLGenerator.class);
|
public static final String ADAPTER_CONTEXT = SimpleXMLGenerator.class.getName();
|
||||||
public static final String ADAPTER_CONTEXT = SimpleXMLGenerator.class.
|
|
||||||
getName();
|
|
||||||
/**
|
/**
|
||||||
* jensp 2011-10-23: Sometimes the extra XML is not needed, for example
|
* 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
|
* when embedding the XML of a content item into the XML output of another
|
||||||
|
|
@ -79,20 +76,20 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
/**
|
/**
|
||||||
* Extra attributes for the cms:item element.
|
* Extra attributes for the cms:item element.
|
||||||
*/
|
*/
|
||||||
private Map<String, String> itemAttributes =
|
private final Map<String, String> itemAttributes = new LinkedHashMap<String, String>();
|
||||||
new LinkedHashMap<String, String>();
|
|
||||||
/**
|
/**
|
||||||
* Allows to overwrite the name and the namespace of the XML element
|
* Allows to overwrite the name and the namespace of the XML element
|
||||||
* used to wrap the rendered item.
|
* used to wrap the rendered item.
|
||||||
*/
|
*/
|
||||||
private String itemElemName = "cms:item";
|
private String itemElemName = "cms:item";
|
||||||
private String itemElemNs = CMS.CMS_XML_NS;
|
private String itemElemNs = CMS.CMS_XML_NS;
|
||||||
|
private static final Map<OID, Element> cache = new HashMap<OID, Element>();
|
||||||
|
private static final boolean USE_CACHE = false;
|
||||||
|
|
||||||
// Register general purpose adaptor for all content items
|
// Register general purpose adaptor for all content items
|
||||||
static {
|
static {
|
||||||
s_log.debug("Static initializer starting...");
|
s_log.debug("Static initializer starting...");
|
||||||
SimpleDomainObjectTraversalAdapter adapter =
|
final SimpleDomainObjectTraversalAdapter adapter = new SimpleDomainObjectTraversalAdapter();
|
||||||
new SimpleDomainObjectTraversalAdapter();
|
|
||||||
adapter.addAssociationProperty("/object/type");
|
adapter.addAssociationProperty("/object/type");
|
||||||
adapter.addAssociationProperty("/object/categories");
|
adapter.addAssociationProperty("/object/categories");
|
||||||
|
|
||||||
|
|
@ -104,6 +101,7 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleXMLGenerator() {
|
public SimpleXMLGenerator() {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseExtraXml(final boolean useExtraXml) {
|
public void setUseExtraXml(final boolean useExtraXml) {
|
||||||
|
|
@ -114,13 +112,11 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
this.listMode = listMode;
|
this.listMode = listMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addItemAttribute(final String name,
|
public void addItemAttribute(final String name, final String value) {
|
||||||
final String value) {
|
|
||||||
itemAttributes.put(name, value);
|
itemAttributes.put(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItemElemName(final String itemElemName,
|
public void setItemElemName(final String itemElemName, final String itemElemNs) {
|
||||||
final String itemElemNs) {
|
|
||||||
this.itemElemName = itemElemName;
|
this.itemElemName = itemElemName;
|
||||||
this.itemElemNs = itemElemNs;
|
this.itemElemNs = itemElemNs;
|
||||||
}
|
}
|
||||||
|
|
@ -132,14 +128,12 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
* @param parent The parent DOM element
|
* @param parent The parent DOM element
|
||||||
* @param useContext The use context
|
* @param useContext The use context
|
||||||
*/
|
*/
|
||||||
public void generateXML(PageState state, Element parent, String useContext) {
|
public void generateXML(final PageState state, final Element parent, final String useContext) {
|
||||||
final long start = System.nanoTime();
|
final long start = System.nanoTime();
|
||||||
|
|
||||||
//ContentSection section = CMS.getContext().getContentSection();
|
//ContentSection section = CMS.getContext().getContentSection();
|
||||||
ContentItem item = getContentItem(state);
|
ContentItem item = getContentItem(state);
|
||||||
|
|
||||||
System.out.printf("After getting contentitem: %d ms\n", (System.nanoTime() - start) / 1000000);
|
|
||||||
|
|
||||||
s_log.info("Generate XML for item " + item.getOID());
|
s_log.info("Generate XML for item " + item.getOID());
|
||||||
|
|
||||||
Party currentParty = Kernel.getContext().getParty();
|
Party currentParty = Kernel.getContext().getParty();
|
||||||
|
|
@ -152,29 +146,24 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
// Note that the xml that is generated is only of use if you DO NOT CACHE content pages.
|
// Note that the xml that is generated is only of use if you DO NOT CACHE content pages.
|
||||||
// cg.
|
// cg.
|
||||||
|
|
||||||
PermissionDescriptor edit =
|
final PermissionDescriptor edit = new PermissionDescriptor(
|
||||||
new PermissionDescriptor(PrivilegeDescriptor.get(
|
PrivilegeDescriptor.get(SecurityManager.CMS_EDIT_ITEM), item, currentParty);
|
||||||
SecurityManager.CMS_EDIT_ITEM), item, currentParty);
|
|
||||||
if (PermissionService.checkPermission(edit)) {
|
if (PermissionService.checkPermission(edit)) {
|
||||||
parent.addAttribute("canEdit", "true");
|
parent.addAttribute("canEdit", "true");
|
||||||
}
|
}
|
||||||
PermissionDescriptor publish =
|
final PermissionDescriptor publish = new PermissionDescriptor(
|
||||||
new PermissionDescriptor(PrivilegeDescriptor.get(
|
PrivilegeDescriptor.get(SecurityManager.CMS_PUBLISH), item, currentParty);
|
||||||
SecurityManager.CMS_PUBLISH), item, currentParty);
|
|
||||||
if (PermissionService.checkPermission(publish)) {
|
if (PermissionService.checkPermission(publish)) {
|
||||||
parent.addAttribute("canPublish", "true");
|
parent.addAttribute("canPublish", "true");
|
||||||
}
|
}
|
||||||
String className = item.getDefaultDomainClass();
|
final String className = item.getDefaultDomainClass();
|
||||||
|
|
||||||
System.out.printf("After creating permission attributes: %d ms\n", (System.nanoTime() - start) / 1000000);
|
|
||||||
|
|
||||||
// Ensure correct subtype of ContentItem is instantiated
|
// Ensure correct subtype of ContentItem is instantiated
|
||||||
if (!item.getClass().getName().equals(className)) {
|
if (!item.getClass().getName().equals(className)) {
|
||||||
s_log.info("Specializing item");
|
s_log.info("Specializing item");
|
||||||
try {
|
try {
|
||||||
item =
|
item = (ContentItem) DomainObjectFactory.newInstance(
|
||||||
(ContentItem) DomainObjectFactory.newInstance(new OID(item.
|
new OID(item.getObjectType().getQualifiedName(), item.getID()));
|
||||||
getObjectType().getQualifiedName(), item.getID()));
|
|
||||||
} catch (DataObjectNotFoundException ex) {
|
} catch (DataObjectNotFoundException ex) {
|
||||||
throw new UncheckedWrapperException(
|
throw new UncheckedWrapperException(
|
||||||
(String) GlobalizationUtil.globalize(
|
(String) GlobalizationUtil.globalize(
|
||||||
|
|
@ -183,55 +172,71 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.printf("After checking type: %d ms\n", (System.nanoTime() - start) / 1000000);
|
|
||||||
|
|
||||||
// Implementing XMLGenerator directly is now deprecated
|
// Implementing XMLGenerator directly is now deprecated
|
||||||
if (item instanceof XMLGenerator) {
|
if (item instanceof XMLGenerator) {
|
||||||
s_log.info("Item implements XMLGenerator interface");
|
s_log.info("Item implements XMLGenerator interface");
|
||||||
XMLGenerator xitem = (XMLGenerator) item;
|
final XMLGenerator xitem = (XMLGenerator) item;
|
||||||
xitem.generateXML(state, parent, useContext);
|
xitem.generateXML(state, parent, useContext);
|
||||||
|
|
||||||
} else if (className.equals("com.arsdigita.cms.UserDefinedContentItem")) {
|
} else if ("com.arsdigita.cms.UserDefinedContentItem".equals(className)) {
|
||||||
s_log.info("Item is a user defined content item");
|
s_log.info("Item is a user defined content item");
|
||||||
UserDefinedContentItem UDItem = (UserDefinedContentItem) item;
|
final UserDefinedContentItem UDItem = (UserDefinedContentItem) item;
|
||||||
generateUDItemXML(UDItem, state, parent, useContext);
|
generateUDItemXML(UDItem, state, parent, useContext);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
s_log.info("Item is using DomainObjectXMLRenderer");
|
s_log.info("Item is using DomainObjectXMLRenderer");
|
||||||
|
|
||||||
// This is the preferred method
|
// This is the preferred method
|
||||||
Element content = startElement(useContext, parent);
|
//final Element content = startElement(useContext, parent);
|
||||||
|
final Element content;
|
||||||
|
if (USE_CACHE && cache.containsKey(item.getOID())) {
|
||||||
|
content = cache.get(item.getOID());
|
||||||
|
} else {
|
||||||
|
|
||||||
ContentItemXMLRenderer renderer =
|
content = startElement(useContext);
|
||||||
new ContentItemXMLRenderer(content);
|
|
||||||
|
|
||||||
renderer.setWrapAttributes(true);
|
final ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(content);
|
||||||
renderer.setWrapRoot(false);
|
|
||||||
renderer.setWrapObjects(false);
|
|
||||||
renderer.setRevisitFullObject(true);
|
|
||||||
|
|
||||||
renderer.walk(item, ADAPTER_CONTEXT);
|
renderer.setWrapAttributes(true);
|
||||||
|
renderer.setWrapRoot(false);
|
||||||
|
renderer.setWrapObjects(false);
|
||||||
|
renderer.setRevisitFullObject(true);
|
||||||
|
|
||||||
System.out.printf("After getting rendering standard item xml: %d ms\n", (System.nanoTime() - start) / 1000000);
|
System.out.printf("Prepared renderer in %d ms\n", (System.nanoTime() - start)
|
||||||
|
/ 1000000);
|
||||||
|
|
||||||
//parent.addContent(content);
|
renderer.walk(item, ADAPTER_CONTEXT);
|
||||||
|
|
||||||
/*
|
System.out.printf("Rendered standard item xml in %d ms\n", (System.nanoTime() - start)
|
||||||
* 2011-08-27 jensp: Introduced to remove the annoying special templates
|
/ 1000000);
|
||||||
* for MultiPartArticle, SiteProxy and others. The method called
|
|
||||||
* here was already definied but not used.
|
//parent.addContent(content);
|
||||||
*
|
|
||||||
* 2011-10-23 jensp: It is now possible to disable the use of
|
/*
|
||||||
* extra XML.
|
* 2011-08-27 jensp: Introduced to remove the annoying special templates
|
||||||
*/
|
* for MultiPartArticle, SiteProxy and others. The method called
|
||||||
if (useExtraXml) {
|
* here was already definied but not used.
|
||||||
for (ExtraXMLGenerator generator : item.getExtraXMLGenerators()) {
|
*
|
||||||
generator.setListMode(listMode);
|
* 2011-10-23 jensp: It is now possible to disable the use of
|
||||||
generator.generateXML(item, content, state);
|
* extra XML.
|
||||||
|
*/
|
||||||
|
final long extraXMLStart = System.nanoTime();
|
||||||
|
if (useExtraXml) {
|
||||||
|
for (ExtraXMLGenerator generator : item.getExtraXMLGenerators()) {
|
||||||
|
generator.setListMode(listMode);
|
||||||
|
generator.generateXML(item, content, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
System.out.
|
||||||
|
printf("Rendered ExtraXML in %d ms\n", (System.nanoTime() - extraXMLStart) / 1000000);
|
||||||
|
System.out.printf(" -----\n");
|
||||||
|
|
||||||
|
cache.put(item.getOID(), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.printf("After rendering extra xml: %d ms\n", (System.nanoTime() - start) / 1000000);
|
parent.addContent(content);
|
||||||
|
|
||||||
|
System.out.printf("Rendered item in %d ms\n\n", (System.nanoTime() - start) / 1000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,22 +249,22 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
* @param state The page state
|
* @param state The page state
|
||||||
* @return A content item
|
* @return A content item
|
||||||
*/
|
*/
|
||||||
protected ContentItem getContentItem(PageState state) {
|
protected ContentItem getContentItem(final PageState state) {
|
||||||
if (CMS.getContext().hasContentItem()) {
|
if (CMS.getContext().hasContentItem()) {
|
||||||
return CMS.getContext().getContentItem();
|
return CMS.getContext().getContentItem();
|
||||||
} else {
|
} else {
|
||||||
CMSPage page = (CMSPage) state.getPage();
|
final CMSPage page = (CMSPage) state.getPage();
|
||||||
return page.getContentItem(state);
|
return page.getContentItem(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateUDItemXML(UserDefinedContentItem UDItem,
|
protected void generateUDItemXML(final UserDefinedContentItem UDItem,
|
||||||
PageState state,
|
final PageState state,
|
||||||
Element parent,
|
final Element parent,
|
||||||
String useContext) {
|
final String useContext) {
|
||||||
|
|
||||||
Element element = startElement(useContext, parent);
|
final Element element = startElement(useContext, parent);
|
||||||
Element additionalAttrs = UDItemElement(useContext);
|
final Element additionalAttrs = UDItemElement(useContext);
|
||||||
|
|
||||||
element.addAttribute("type", UDItem.getContentType().getLabel());
|
element.addAttribute("type", UDItem.getContentType().getLabel());
|
||||||
element.addAttribute("id", UDItem.getID().toString());
|
element.addAttribute("id", UDItem.getID().toString());
|
||||||
|
|
@ -267,12 +272,11 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
element.addAttribute("title", UDItem.getTitle());
|
element.addAttribute("title", UDItem.getTitle());
|
||||||
element.addAttribute("javaClass", UDItem.getContentType().getClassName());
|
element.addAttribute("javaClass", UDItem.getContentType().getClassName());
|
||||||
|
|
||||||
DynamicObjectType dot = new DynamicObjectType(
|
final DynamicObjectType dot = new DynamicObjectType(UDItem.getSpecificObjectType());
|
||||||
UDItem.getSpecificObjectType());
|
final Iterator declaredProperties =
|
||||||
Iterator declaredProperties =
|
dot.getObjectType().getDeclaredProperties();
|
||||||
dot.getObjectType().getDeclaredProperties();
|
Property currentProperty;
|
||||||
Property currentProperty = null;
|
Object value;
|
||||||
Object value = null;
|
|
||||||
while (declaredProperties.hasNext()) {
|
while (declaredProperties.hasNext()) {
|
||||||
currentProperty = (Property) declaredProperties.next();
|
currentProperty = (Property) declaredProperties.next();
|
||||||
value = (Object) UDItem.get(currentProperty.getName());
|
value = (Object) UDItem.get(currentProperty.getName());
|
||||||
|
|
@ -292,11 +296,10 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element startElement(String useContext, Element parent) {
|
private Element startElement(final String useContext, final Element parent) {
|
||||||
//Element element = new Element("cms:item", CMS.CMS_XML_NS);
|
//Element element = new Element("cms:item", CMS.CMS_XML_NS);
|
||||||
//final Element element = new Element(itemElemName, itemElemNs);
|
//final Element element = new Element(itemElemName, itemElemNs);
|
||||||
final Element element = parent.newChildElement(itemElemName,
|
final Element element = parent.newChildElement(itemElemName, itemElemNs);
|
||||||
itemElemNs);
|
|
||||||
if (useContext != null) {
|
if (useContext != null) {
|
||||||
element.addAttribute("useContext", useContext);
|
element.addAttribute("useContext", useContext);
|
||||||
}
|
}
|
||||||
|
|
@ -308,20 +311,35 @@ public class SimpleXMLGenerator implements XMLGenerator {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element UDItemElement(String useContext) {
|
private Element startElement(final String useContext) {
|
||||||
Element element = new Element("cms:UDItemAttributes", CMS.CMS_XML_NS);
|
final Element element = new Element(itemElemName, itemElemNs);
|
||||||
/*
|
|
||||||
if ( useContext != null ) {
|
if (useContext != null) {
|
||||||
element.addAttribute("useContext", useContext);
|
element.addAttribute("useContext", useContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> attr : itemAttributes.entrySet()) {
|
||||||
|
element.addAttribute(attr.getKey(), attr.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Element UDItemElement(final String useContext) {
|
||||||
|
final Element element = new Element("cms:UDItemAttributes", CMS.CMS_XML_NS);
|
||||||
|
/*
|
||||||
|
if ( useContext != null ) {
|
||||||
|
element.addAttribute("useContext", useContext);
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element UDItemAttrElement(String name, String value) {
|
private Element UDItemAttrElement(final String name, final String value) {
|
||||||
Element element = new Element("cms:UDItemAttribute", CMS.CMS_XML_NS);
|
final Element element = new Element("cms:UDItemAttribute", CMS.CMS_XML_NS);
|
||||||
element.addAttribute("UDItemAttrName", name);
|
element.addAttribute("UDItemAttrName", name);
|
||||||
element.addAttribute("UDItemAttrValue", value);
|
element.addAttribute("UDItemAttrValue", value);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,25 +18,22 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.domain;
|
package com.arsdigita.domain;
|
||||||
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import com.arsdigita.persistence.metadata.ObjectType;
|
|
||||||
import com.arsdigita.persistence.metadata.Property;
|
|
||||||
import com.arsdigita.persistence.DataCollection;
|
|
||||||
import com.arsdigita.persistence.DataObject;
|
|
||||||
import com.arsdigita.persistence.DataAssociation;
|
import com.arsdigita.persistence.DataAssociation;
|
||||||
import com.arsdigita.persistence.DataAssociationCursor;
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
import com.arsdigita.persistence.DataQuery;
|
import com.arsdigita.persistence.DataQuery;
|
||||||
import com.arsdigita.persistence.DataQueryDataCollectionAdapter;
|
import com.arsdigita.persistence.DataQueryDataCollectionAdapter;
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
import com.arsdigita.persistence.metadata.ObjectType;
|
||||||
|
import com.arsdigita.persistence.metadata.Property;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -62,8 +59,7 @@ public abstract class DomainObjectTraversal {
|
||||||
|
|
||||||
private Set m_visited = new HashSet();
|
private Set m_visited = new HashSet();
|
||||||
private static Map s_adapters = new HashMap();
|
private static Map s_adapters = new HashMap();
|
||||||
private static final Logger s_log = Logger.getLogger(
|
private static final Logger s_log = Logger.getLogger(DomainObjectTraversal.class);
|
||||||
DomainObjectTraversal.class);
|
|
||||||
public final static String LINK_NAME = "link";
|
public final static String LINK_NAME = "link";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -140,10 +136,9 @@ public abstract class DomainObjectTraversal {
|
||||||
*
|
*
|
||||||
* @param type the object type to lookup
|
* @param type the object type to lookup
|
||||||
* @param context the adapter context
|
* @param context the adapter context
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
public static DomainObjectTraversalAdapter lookupAdapter(
|
public static DomainObjectTraversalAdapter lookupAdapter(final ObjectType type, final String context) {
|
||||||
final ObjectType type,
|
|
||||||
final String context) {
|
|
||||||
Assert.exists(type, ObjectType.class);
|
Assert.exists(type, ObjectType.class);
|
||||||
Assert.exists(context, String.class);
|
Assert.exists(context, String.class);
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
|
|
@ -152,8 +147,7 @@ public abstract class DomainObjectTraversal {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (DomainObjectTraversalAdapter) s_adapters.get(
|
return (DomainObjectTraversalAdapter) s_adapters.get(new AdapterKey(type, context));
|
||||||
new AdapterKey(type, context));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -163,20 +157,20 @@ public abstract class DomainObjectTraversal {
|
||||||
*
|
*
|
||||||
* @param type the object type to search for
|
* @param type the object type to search for
|
||||||
* @param context the adapter context
|
* @param context the adapter context
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
public static DomainObjectTraversalAdapter findAdapter(ObjectType type,
|
public static DomainObjectTraversalAdapter findAdapter(final ObjectType type, final String context) {
|
||||||
final String context) {
|
|
||||||
Assert.exists(type, ObjectType.class);
|
Assert.exists(type, ObjectType.class);
|
||||||
Assert.exists(context, String.class);
|
Assert.exists(context, String.class);
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("findAdapter for type " + type.getQualifiedName()
|
s_log.debug("findAdapter for type " + type.getQualifiedName()
|
||||||
+ " in context " + context);
|
+ " in context " + context);
|
||||||
|
|
||||||
StringBuilder buf = new StringBuilder();
|
final StringBuilder buf = new StringBuilder();
|
||||||
buf.append("Adapters contain:\n");
|
buf.append("Adapters contain:\n");
|
||||||
Iterator keys = s_adapters.keySet().iterator();
|
final Iterator keys = s_adapters.keySet().iterator();
|
||||||
while (keys.hasNext()) {
|
while (keys.hasNext()) {
|
||||||
Object key = keys.next();
|
final Object key = keys.next();
|
||||||
buf.append(key.toString()).append(": ");
|
buf.append(key.toString()).append(": ");
|
||||||
buf.append(s_adapters.get(key).toString()).append('\n');
|
buf.append(s_adapters.get(key).toString()).append('\n');
|
||||||
}
|
}
|
||||||
|
|
@ -201,10 +195,8 @@ public abstract class DomainObjectTraversal {
|
||||||
* @param obj the domain object to traverse
|
* @param obj the domain object to traverse
|
||||||
* @param context the context for the traversal adapter
|
* @param context the context for the traversal adapter
|
||||||
*/
|
*/
|
||||||
public void walk(final DomainObject obj,
|
public void walk(final DomainObject obj, final String context) {
|
||||||
final String context) {
|
final DomainObjectTraversalAdapter adapter = findAdapter(obj.getObjectType(), context);
|
||||||
final DomainObjectTraversalAdapter adapter = findAdapter(obj.getObjectType(),
|
|
||||||
context);
|
|
||||||
if (adapter == null) {
|
if (adapter == null) {
|
||||||
final String errorMsg = "No adapter for object " + obj.getOID()
|
final String errorMsg = "No adapter for object " + obj.getOID()
|
||||||
+ " in context " + context;
|
+ " in context " + context;
|
||||||
|
|
@ -214,9 +206,7 @@ public abstract class DomainObjectTraversal {
|
||||||
walk(obj, context, adapter);
|
walk(obj, context, adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void walk(final DomainObject obj,
|
protected void walk(final DomainObject obj, final String context, final DomainObjectTraversalAdapter adapter) {
|
||||||
final String context,
|
|
||||||
final DomainObjectTraversalAdapter adapter) {
|
|
||||||
Assert.exists(adapter, DomainObjectTraversalAdapter.class);
|
Assert.exists(adapter, DomainObjectTraversalAdapter.class);
|
||||||
walk(adapter, obj, "/object", context, null);
|
walk(adapter, obj, "/object", context, null);
|
||||||
}
|
}
|
||||||
|
|
@ -234,12 +224,13 @@ public abstract class DomainObjectTraversal {
|
||||||
final DomainObject linkObject) {
|
final DomainObject linkObject) {
|
||||||
s_log.debug(String.format("Walking with path %s and context %s...", path,
|
s_log.debug(String.format("Walking with path %s and context %s...", path,
|
||||||
context));
|
context));
|
||||||
OID oid = obj.getOID();
|
final OID oid = obj.getOID();
|
||||||
OID linkOid = null;
|
OID linkOid = null;
|
||||||
if (linkObject != null) {
|
if (linkObject != null) {
|
||||||
linkOid = linkObject.getOID();
|
linkOid = linkObject.getOID();
|
||||||
}
|
}
|
||||||
OID[] visitedKey = {oid, linkOid};
|
|
||||||
|
final OID[] visitedKey = {oid, linkOid};
|
||||||
// Prevent infinite recursion
|
// Prevent infinite recursion
|
||||||
if (m_visited.contains(visitedKey)) {
|
if (m_visited.contains(visitedKey)) {
|
||||||
revisitObject(obj, path);
|
revisitObject(obj, path);
|
||||||
|
|
@ -261,146 +252,280 @@ public abstract class DomainObjectTraversal {
|
||||||
endLink(linkObject, path);
|
endLink(linkObject, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectType type = obj.getObjectType();
|
final ObjectType type = obj.getObjectType();
|
||||||
|
|
||||||
// Test all properties against the traversal xml
|
// Test all properties against the traversal xml
|
||||||
for (Iterator i = type.getProperties(); i.hasNext();) {
|
for (Iterator i = type.getProperties(); i.hasNext();) {
|
||||||
Property prop = (Property) i.next();
|
processProperty((Property) i.next(), obj, adapter, path, context, oid);
|
||||||
String propName = prop.getName();
|
// System.err.println("Next property...");
|
||||||
|
// final long propStart = System.nanoTime();
|
||||||
if (!adapter.processProperty(obj,
|
// final Property prop = (Property) i.next();
|
||||||
appendToPath(path, prop.getName()),
|
// final String propName = prop.getName();
|
||||||
prop,
|
//
|
||||||
context)) {
|
// if (!adapter.processProperty(obj,
|
||||||
if (s_log.isDebugEnabled()) {
|
// appendToPath(path, prop.getName()),
|
||||||
s_log.debug("Not processing " + appendToPath(path, prop.getName()) + " in object " + oid
|
// prop,
|
||||||
+ " and context "
|
// context)) {
|
||||||
+ context + " with adapter " + adapter.getClass().
|
// if (s_log.isDebugEnabled()) {
|
||||||
getName());
|
// s_log.debug("Not processing " + appendToPath(path, prop.getName()) + " in object " + oid
|
||||||
}
|
// + " and context "
|
||||||
continue;
|
// + context + " with adapter " + adapter.getClass().
|
||||||
}
|
// getName());
|
||||||
Object propValue = obj.get(propName);
|
// }
|
||||||
if (propValue == null) {
|
// continue;
|
||||||
if (s_log.isDebugEnabled()) {
|
// }
|
||||||
s_log.debug("Object " + oid.toString() + " doesn't "
|
//
|
||||||
+ "contain property " + propName);
|
// final Object propValue = obj.get(propName);
|
||||||
}
|
// if (propValue == null) {
|
||||||
continue;
|
// if (s_log.isDebugEnabled()) {
|
||||||
}
|
// s_log.debug("Object " + oid.toString() + " doesn't "
|
||||||
|
// + "contain property " + propName);
|
||||||
if (prop.isAttribute()) {
|
// }
|
||||||
handleAttribute(obj, path, prop);
|
// continue;
|
||||||
|
// }
|
||||||
} else if (propValue instanceof DataObject) {
|
//
|
||||||
// Property is a DataObject, so start recursion
|
// if (prop.isAttribute()) {
|
||||||
if (s_log.isDebugEnabled()) {
|
// handleAttribute(obj, path, prop);
|
||||||
s_log.debug(prop.getName() + " is a DataObject");
|
//
|
||||||
}
|
// } else if (propValue instanceof DataObject) {
|
||||||
|
// // Property is a DataObject, so start recursion
|
||||||
beginRole(obj, path, prop);
|
// if (s_log.isDebugEnabled()) {
|
||||||
|
// s_log.debug(prop.getName() + " is a DataObject");
|
||||||
walk(adapter,
|
// }
|
||||||
DomainObjectFactory.newInstance((DataObject) propValue),
|
//
|
||||||
appendToPath(path, propName),
|
// beginRole(obj, path, prop);
|
||||||
context,
|
//
|
||||||
null);
|
// walk(adapter,
|
||||||
|
// DomainObjectFactory.newInstance((DataObject) propValue),
|
||||||
endRole(obj, path, prop);
|
// appendToPath(path, propName),
|
||||||
} else if (propValue instanceof DataAssociation) {
|
// context,
|
||||||
|
// null);
|
||||||
|
//
|
||||||
// see #25808 - this hack prevents the content field of cms_files
|
// endRole(obj, path, prop);
|
||||||
// (which is a blob) from being queried when all we need is a
|
// } else if (propValue instanceof DataAssociation) {
|
||||||
// list of the files on an item..
|
// final long assocStart = System.nanoTime();
|
||||||
if (prop.getName().equals("fileAttachments") && !Domain.getConfig().queryBlobContentForFileAttachments()) {
|
//
|
||||||
// make true a config
|
// // see #25808 - this hack prevents the content field of cms_files
|
||||||
DataQuery fileAttachmentsQuery =
|
// // (which is a blob) from being queried when all we need is a
|
||||||
SessionManager.getSession().retrieveQuery(
|
// // list of the files on an item..
|
||||||
"com.arsdigita.cms.contentassets.fileAttachmentsQuery");
|
// final long checkstart = System.nanoTime();
|
||||||
|
// final boolean result = prop.getName().equals("fileAttachments") && !Domain.getConfig().
|
||||||
fileAttachmentsQuery.setParameter("item_id",
|
// queryBlobContentForFileAttachments();
|
||||||
obj.getOID().get("id"));
|
// System.err.printf("Checked if property is file attachment in %d ms. Result is %s\n", (System.nanoTime()
|
||||||
|
// - checkstart)
|
||||||
DataCollection files = new DataQueryDataCollectionAdapter(
|
// / 1000000, Boolean.
|
||||||
fileAttachmentsQuery, "file");
|
// toString(result));
|
||||||
|
// //if (prop.getName().equals("fileAttachments") && !Domain.getConfig().queryBlobContentForFileAttachments()) {
|
||||||
while (files.next()) {
|
// if (result) {
|
||||||
DataObject file = files.getDataObject();
|
// // make true a config
|
||||||
walk(adapter,
|
// DataQuery fileAttachmentsQuery =
|
||||||
DomainObjectFactory.newInstance(file),
|
// SessionManager.getSession().retrieveQuery(
|
||||||
appendToPath(path, propName),
|
// "com.arsdigita.cms.contentassets.fileAttachmentsQuery");
|
||||||
context,
|
//
|
||||||
null);
|
// fileAttachmentsQuery.setParameter("item_id",
|
||||||
}
|
// obj.getOID().get("id"));
|
||||||
|
//
|
||||||
} else {
|
// DataCollection files = new DataQueryDataCollectionAdapter(
|
||||||
//2010-11-08: Moved to seperate Methods to allow simple
|
// fileAttachmentsQuery, "file");
|
||||||
//extending of the handling of data assocications
|
//
|
||||||
/*
|
// while (files.next()) {
|
||||||
* if (s_log.isDebugEnabled()) { s_log.debug(prop.getName() + " is a DataAssociation"); }
|
// final DataObject file = files.getDataObject();
|
||||||
* beginAssociation(obj, path, prop);
|
// walk(adapter,
|
||||||
*
|
// DomainObjectFactory.newInstance(file),
|
||||||
* DataAssociationCursor daCursor = ((DataAssociation) propValue). getDataAssociationCursor();
|
// appendToPath(path, propName),
|
||||||
*
|
// context,
|
||||||
* while (daCursor.next()) { s_log.debug("Processing data assoication cursor..."); DataObject link =
|
// null);
|
||||||
* daCursor.getLink(); DomainObject linkObj = null; if (link != null) { linkObj = new
|
// }
|
||||||
* LinkDomainObject(link); } walk(adapter, DomainObjectFactory.newInstance(daCursor.
|
//
|
||||||
* getDataObject()), appendToPath(path, propName), context, linkObj); } endAssociation(obj, path, prop);
|
// } else {
|
||||||
*/
|
// //2010-11-08: Moved to seperate Methods to allow simple
|
||||||
|
// //extending of the handling of data assocications
|
||||||
walkDataAssociations(adapter,
|
// /*
|
||||||
obj,
|
// * if (s_log.isDebugEnabled()) { s_log.debug(prop.getName() + " is a DataAssociation"); }
|
||||||
path,
|
// * beginAssociation(obj, path, prop);
|
||||||
context,
|
// *
|
||||||
prop,
|
// * DataAssociationCursor daCursor = ((DataAssociation) propValue). getDataAssociationCursor();
|
||||||
propName,
|
// *
|
||||||
propValue);
|
// * while (daCursor.next()) { s_log.debug("Processing data assoication cursor..."); DataObject link =
|
||||||
}
|
// * daCursor.getLink(); DomainObject linkObj = null; if (link != null) { linkObj = new
|
||||||
} else {
|
// * LinkDomainObject(link); } walk(adapter, DomainObjectFactory.newInstance(daCursor.
|
||||||
// Unknown property value type - do nothing
|
// * getDataObject()), appendToPath(path, propName), context, linkObj); } endAssociation(obj, path, prop);
|
||||||
}
|
// */
|
||||||
|
//
|
||||||
|
// walkDataAssociations(adapter,
|
||||||
|
// obj,
|
||||||
|
// path,
|
||||||
|
// context,
|
||||||
|
// prop,
|
||||||
|
// propName,
|
||||||
|
// propValue);
|
||||||
|
// }
|
||||||
|
// System.err.printf("Proceesed data association %s (%s) in %d ms\n", path, propName, (System.nanoTime()
|
||||||
|
// - assocStart)
|
||||||
|
// / 1000000);
|
||||||
|
// } else {
|
||||||
|
// // Unknown property value type - do nothing
|
||||||
|
// }
|
||||||
|
// System.err.printf("Processed property %s in %d ms.", propName, (System.nanoTime() - propStart) / 1000000);
|
||||||
|
// System.err.printf("Walking since %d ms\n", (System.nanoTime() - start) / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If needed, close a surrounding tag
|
// If needed, close a surrounding tag
|
||||||
endObject(obj, path);
|
endObject(obj, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void walkDataAssociations(DomainObjectTraversalAdapter adapter,
|
private void processProperty(final Property prop,
|
||||||
DomainObject obj,
|
final DomainObject obj,
|
||||||
String path,
|
final DomainObjectTraversalAdapter adapter,
|
||||||
String context,
|
final String path,
|
||||||
Property prop,
|
final String context,
|
||||||
String propName,
|
final OID oid) {
|
||||||
Object propValue) {
|
final long start = System.nanoTime();
|
||||||
s_log.debug(String.format("%s is a DataAssociation", prop.getName()));
|
final String propName = prop.getName();
|
||||||
|
//System.out.printf("Processing property %30s...\n", propName);
|
||||||
|
|
||||||
beginAssociation(obj, path, prop);
|
if (!adapter.processProperty(obj,
|
||||||
|
appendToPath(path, prop.getName()),
|
||||||
DataAssociationCursor daCursor =
|
prop,
|
||||||
((DataAssociation) propValue).getDataAssociationCursor();
|
context)) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
while (daCursor.next()) {
|
s_log.debug("Not processing " + appendToPath(path, prop.getName()) + " in object " + oid
|
||||||
walkDataAssociation(adapter,
|
+ " and context "
|
||||||
obj,
|
+ context + " with adapter " + adapter.getClass().
|
||||||
path,
|
getName());
|
||||||
context,
|
}
|
||||||
propName,
|
return;
|
||||||
daCursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
endAssociation(obj, path, prop);
|
final Object propValue = obj.get(propName);
|
||||||
|
if (propValue == null) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Object " + oid.toString() + " doesn't "
|
||||||
|
+ "contain property " + propName);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop.isAttribute()) {
|
||||||
|
handleAttribute(obj, path, prop);
|
||||||
|
|
||||||
|
} else if (propValue instanceof DataObject) {
|
||||||
|
// Property is a DataObject, so start recursion
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug(prop.getName() + " is a DataObject");
|
||||||
|
}
|
||||||
|
|
||||||
|
beginRole(obj, path, prop);
|
||||||
|
|
||||||
|
walk(adapter,
|
||||||
|
DomainObjectFactory.newInstance((DataObject) propValue),
|
||||||
|
appendToPath(path, propName),
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
|
||||||
|
endRole(obj, path, prop);
|
||||||
|
} else if (propValue instanceof DataAssociation) {
|
||||||
|
//final long assocStart = System.nanoTime();
|
||||||
|
// see #25808 - this hack prevents the content field of cms_files
|
||||||
|
// (which is a blob) from being queried when all we need is a
|
||||||
|
// list of the files on an item..
|
||||||
|
final boolean result = "fileAttachments".equals(prop.getName())
|
||||||
|
&& !Domain.getConfig().queryBlobContentForFileAttachments();
|
||||||
|
//if (prop.getName().equals("fileAttachments") && !Domain.getConfig().queryBlobContentForFileAttachments()) {
|
||||||
|
if (result) {
|
||||||
|
// make true a config
|
||||||
|
final DataQuery fileAttachmentsQuery = SessionManager.getSession().retrieveQuery(
|
||||||
|
"com.arsdigita.cms.contentassets.fileAttachmentsQuery");
|
||||||
|
fileAttachmentsQuery.setParameter("item_id", obj.getOID().get("id"));
|
||||||
|
|
||||||
|
final DataCollection files = new DataQueryDataCollectionAdapter(fileAttachmentsQuery, "file");
|
||||||
|
//2013-02-16 jensp: Don't process the loop if there are no files...
|
||||||
|
if (!files.isEmpty()) {
|
||||||
|
while (files.next()) {
|
||||||
|
final DataObject file = files.getDataObject();
|
||||||
|
walk(adapter,
|
||||||
|
DomainObjectFactory.newInstance(file),
|
||||||
|
appendToPath(path, propName),
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//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();
|
||||||
|
*
|
||||||
|
* 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); } endAssociation(obj, path, prop);
|
||||||
|
*/
|
||||||
|
//System.out.printf("\tNeeded %3d ms to get here.\n", (System.nanoTime() - assocStart) / 1000000);
|
||||||
|
walkDataAssociations(adapter,
|
||||||
|
obj,
|
||||||
|
path,
|
||||||
|
context,
|
||||||
|
prop,
|
||||||
|
propName,
|
||||||
|
propValue);
|
||||||
|
//System.out.printf("\tNeeded %3d ms to get here.\n", (System.nanoTime() - assocStart) / 1000000);
|
||||||
|
}
|
||||||
|
//System.out.printf("\tProcssed assoc in %3d ms.\n ", (System.nanoTime() - assocStart) / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Processed property %30s in %3d ms.\n", propName, (System.nanoTime() - start) / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void walkDataAssociation(DomainObjectTraversalAdapter adapter,
|
protected void walkDataAssociations(final DomainObjectTraversalAdapter adapter,
|
||||||
DomainObject obj,
|
final DomainObject obj,
|
||||||
String path,
|
final String path,
|
||||||
String context,
|
final String context,
|
||||||
String propName,
|
final Property prop,
|
||||||
DataAssociationCursor daCursor) {
|
final String propName,
|
||||||
|
final Object propValue) {
|
||||||
|
s_log.debug(String.format("%s is a DataAssociation", prop.getName()));
|
||||||
|
|
||||||
|
final DataAssociationCursor daCursor = ((DataAssociation) propValue).getDataAssociationCursor();
|
||||||
|
|
||||||
|
//jensp 2013-02-06: Wrapped the while loop with an if to avoid a call of DataAssoiciationCursor#next() on a
|
||||||
|
//empty collection. DataAssoiciationCursor#next() tooks a serious amount of time, especially on the
|
||||||
|
//fileAttachments association (about 25 ms per item). A call of DataAssociationCursor#isEmpty() needs less than
|
||||||
|
//1 ms. If you have list with specialized items, maybe with assoication to other items, this speeds up the XML
|
||||||
|
//rendering a little bit...
|
||||||
|
//Also the beginAssoication and endAssociation methods have been moved into the if block so that they only
|
||||||
|
//created if the association is not empty
|
||||||
|
if (!daCursor.isEmpty()) {
|
||||||
|
|
||||||
|
beginAssociation(obj, path, prop);
|
||||||
|
|
||||||
|
while (daCursor.next()) {
|
||||||
|
walkDataAssociation(adapter,
|
||||||
|
obj,
|
||||||
|
path,
|
||||||
|
context,
|
||||||
|
propName,
|
||||||
|
daCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
endAssociation(obj, path, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void walkDataAssociation(final DomainObjectTraversalAdapter adapter,
|
||||||
|
final DomainObject obj,
|
||||||
|
final String path,
|
||||||
|
final String context,
|
||||||
|
final String propName,
|
||||||
|
final DataAssociationCursor daCursor) {
|
||||||
s_log.debug(String.format("Processing data assoication cursor for object '%s'...",
|
s_log.debug(String.format("Processing data assoication cursor for object '%s'...",
|
||||||
obj.getOID().toString()));
|
obj.getOID().toString()));
|
||||||
DataObject link = daCursor.getLink();
|
final DataObject link = daCursor.getLink();
|
||||||
DomainObject linkObj = null;
|
DomainObject linkObj = null;
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
linkObj = new LinkDomainObject(link);
|
linkObj = new LinkDomainObject(link);
|
||||||
|
|
@ -414,84 +539,104 @@ public abstract class DomainObjectTraversal {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the processing of an object starts
|
* Method called when the processing of an object starts
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
*/
|
*/
|
||||||
protected abstract void beginObject(DomainObject obj,
|
protected abstract void beginObject(DomainObject obj, String path);
|
||||||
String path);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the procesing of an object completes
|
* Method called when the procesing of an object completes
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
*/
|
*/
|
||||||
protected abstract void endObject(DomainObject obj,
|
protected abstract void endObject(DomainObject obj, String path);
|
||||||
String path);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the processing of a Link Object starts
|
* Method called when the processing of a Link Object starts
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
*/
|
*/
|
||||||
protected void beginLink(DomainObject obj, String path) {
|
protected void beginLink(final DomainObject obj, final String path) {
|
||||||
s_log.debug(String.format("Starting link with path = %s", path));
|
s_log.debug(String.format("Starting link with path = %s", path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the procesing of a Link Object completes
|
* Method called when the procesing of a Link Object completes
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
*/
|
*/
|
||||||
protected void endLink(DomainObject obj, String path) {
|
protected void endLink(final DomainObject obj, final String path) {
|
||||||
s_log.debug(String.format("Finished link with path = %s", path));
|
s_log.debug(String.format("Finished link with path = %s", path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when a previously visited object is encountered for a second time.
|
* Method called when a previously visited object is encountered for a second time.
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
*/
|
*/
|
||||||
protected abstract void revisitObject(DomainObject obj,
|
protected abstract void revisitObject(final DomainObject obj, final String path);
|
||||||
String path);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when an attribute is encountered
|
* Method called when an attribute is encountered
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
|
* @param property
|
||||||
*/
|
*/
|
||||||
protected abstract void handleAttribute(DomainObject obj,
|
protected abstract void handleAttribute(final DomainObject obj, final String path, final Property property);
|
||||||
String path,
|
|
||||||
Property property);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the processing of a role starts
|
* Method called when the processing of a role starts
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
|
* @param property
|
||||||
*/
|
*/
|
||||||
protected abstract void beginRole(DomainObject obj,
|
protected abstract void beginRole(DomainObject obj, String path, Property property);
|
||||||
String path,
|
|
||||||
Property property);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the procesing of a role completes
|
* Method called when the procesing of a role completes
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
|
* @param property
|
||||||
*/
|
*/
|
||||||
protected abstract void endRole(DomainObject obj,
|
protected abstract void endRole(DomainObject obj, String path, Property property);
|
||||||
String path,
|
|
||||||
Property property);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the processing of an association starts
|
* Method called when the processing of an association starts
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
|
* @param property
|
||||||
*/
|
*/
|
||||||
protected abstract void beginAssociation(DomainObject obj,
|
protected abstract void beginAssociation(DomainObject obj, String path, Property property);
|
||||||
String path,
|
|
||||||
Property property);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the procesing of an association completes
|
* Method called when the procesing of an association completes
|
||||||
|
* @param obj
|
||||||
|
* @param path
|
||||||
|
* @param property
|
||||||
*/
|
*/
|
||||||
protected abstract void endAssociation(DomainObject obj,
|
protected abstract void endAssociation(DomainObject obj, String path, Property property);
|
||||||
String path,
|
|
||||||
Property property);
|
|
||||||
|
|
||||||
protected String appendToPath(String path,
|
// protected String appendToPath(String path, final String name) {
|
||||||
String name) {
|
// if (path.endsWith("/" + name)) {
|
||||||
|
// path = path + "+";
|
||||||
|
// } else if (!path.endsWith("/" + name + "+")) {
|
||||||
|
// path = path + "/" + name;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return path;
|
||||||
|
// }
|
||||||
|
protected String appendToPath(final String path, final String name) {
|
||||||
if (path.endsWith("/" + name)) {
|
if (path.endsWith("/" + name)) {
|
||||||
path = path + "+";
|
return path.concat("+");
|
||||||
} else if (!path.endsWith("/" + name + "+")) {
|
} else if (!path.endsWith("/" + name + "+")) {
|
||||||
path = path + "/" + name;
|
return path.concat("/").concat(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String nameFromPath(String path) {
|
protected String nameFromPath(final String path) {
|
||||||
int index = path.lastIndexOf("/");
|
final int index = path.lastIndexOf('/');
|
||||||
Assert.isTrue(index >= 0, "Path starts with /");
|
Assert.isTrue(index >= 0, "Path starts with /");
|
||||||
|
|
||||||
if (path.endsWith("+")) {
|
if (path.endsWith("+")) {
|
||||||
|
|
@ -501,8 +646,8 @@ public abstract class DomainObjectTraversal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parentFromPath(String path) {
|
protected String parentFromPath(final String path) {
|
||||||
int index = path.lastIndexOf("/");
|
final int index = path.lastIndexOf('/');
|
||||||
Assert.isTrue(index >= 0, "Path starts with /");
|
Assert.isTrue(index >= 0, "Path starts with /");
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
|
|
@ -517,8 +662,7 @@ public abstract class DomainObjectTraversal {
|
||||||
private final ObjectType m_type;
|
private final ObjectType m_type;
|
||||||
private final String m_context;
|
private final String m_context;
|
||||||
|
|
||||||
public AdapterKey(ObjectType type,
|
public AdapterKey(final ObjectType type, final String context) {
|
||||||
String context) {
|
|
||||||
Assert.exists(type, ObjectType.class);
|
Assert.exists(type, ObjectType.class);
|
||||||
Assert.exists(context, String.class);
|
Assert.exists(context, String.class);
|
||||||
m_type = type;
|
m_type = type;
|
||||||
|
|
@ -526,10 +670,10 @@ public abstract class DomainObjectTraversal {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(final Object object) {
|
||||||
if (o instanceof AdapterKey) {
|
if (object instanceof AdapterKey) {
|
||||||
AdapterKey k = (AdapterKey) o;
|
final AdapterKey key = (AdapterKey) object;
|
||||||
return k.m_type.equals(m_type) && k.m_context.equals(m_context);
|
return key.m_type.equals(m_type) && key.m_context.equals(m_context);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -544,6 +688,7 @@ public abstract class DomainObjectTraversal {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return m_type.getQualifiedName() + ',' + m_context;
|
return m_type.getQualifiedName() + ',' + m_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -551,13 +696,14 @@ public abstract class DomainObjectTraversal {
|
||||||
*/
|
*/
|
||||||
protected class LinkDomainObject extends DomainObject {
|
protected class LinkDomainObject extends DomainObject {
|
||||||
|
|
||||||
public LinkDomainObject(DataObject object) {
|
public LinkDomainObject(final DataObject object) {
|
||||||
super(object);
|
super(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get(String attr) {
|
public Object get(final String attr) {
|
||||||
return super.get(attr);
|
return super.get(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,9 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* @param formatter the formatter for controlling object traversal
|
* @param formatter the formatter for controlling object traversal
|
||||||
* @param context the context in which the formatter should be used
|
* @param context the context in which the formatter should be used
|
||||||
*/
|
*/
|
||||||
public static void registerFormatter(ObjectType type,
|
public static void registerFormatter(final ObjectType type,
|
||||||
DomainObjectXMLFormatter formatter,
|
final DomainObjectXMLFormatter formatter,
|
||||||
String context) {
|
final String context) {
|
||||||
s_formatters.put(new AdapterKey(type, context), formatter);
|
s_formatters.put(new AdapterKey(type, context), formatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,8 +77,7 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* @param type the object type whose items will be traversed
|
* @param type the object type whose items will be traversed
|
||||||
* @param context the context in which the formatter should be used
|
* @param context the context in which the formatter should be used
|
||||||
*/
|
*/
|
||||||
public static void unregisterFormatter(ObjectType type,
|
public static void unregisterFormatter(final ObjectType type, final String context) {
|
||||||
String context) {
|
|
||||||
s_formatters.remove(new AdapterKey(type, context));
|
s_formatters.remove(new AdapterKey(type, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,9 +88,9 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* @param formatter the formatter for controlling object traversal
|
* @param formatter the formatter for controlling object traversal
|
||||||
* @param context the context in which the formatter should be used
|
* @param context the context in which the formatter should be used
|
||||||
*/
|
*/
|
||||||
public static void registerFormatter(String type,
|
public static void registerFormatter(final String type,
|
||||||
DomainObjectXMLFormatter formatter,
|
final DomainObjectXMLFormatter formatter,
|
||||||
String context) {
|
final String context) {
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("Registering formatter "
|
s_log.debug("Registering formatter "
|
||||||
+ formatter.getClass().getName() + " for type " + type
|
+ formatter.getClass().getName() + " for type " + type
|
||||||
|
|
@ -109,8 +108,8 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* @param type the object type whose items will be traversed
|
* @param type the object type whose items will be traversed
|
||||||
* @param context the context in which the formatter should be used
|
* @param context the context in which the formatter should be used
|
||||||
*/
|
*/
|
||||||
public static void unregisterFormatter(String type,
|
public static void unregisterFormatter(final String type,
|
||||||
String context) {
|
final String context) {
|
||||||
unregisterFormatter(MetadataRoot.getMetadataRoot().getObjectType(type),
|
unregisterFormatter(MetadataRoot.getMetadataRoot().getObjectType(type),
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
@ -121,9 +120,7 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* @param type the object type to lookup
|
* @param type the object type to lookup
|
||||||
* @param context the formatter context
|
* @param context the formatter context
|
||||||
*/
|
*/
|
||||||
public static DomainObjectXMLFormatter getFormatter(
|
public static DomainObjectXMLFormatter getFormatter(final ObjectType type, final String context) {
|
||||||
ObjectType type,
|
|
||||||
String context) {
|
|
||||||
return (DomainObjectXMLFormatter) s_formatters.get(new AdapterKey(type, context));
|
return (DomainObjectXMLFormatter) s_formatters.get(new AdapterKey(type, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,16 +131,17 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
*
|
*
|
||||||
* @param type the object type to search for
|
* @param type the object type to search for
|
||||||
* @param context the formatter context
|
* @param context the formatter context
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
public static DomainObjectXMLFormatter findFormatter(ObjectType type,
|
public static DomainObjectXMLFormatter findFormatter(final ObjectType type, final String context) {
|
||||||
String context) {
|
|
||||||
DomainObjectXMLFormatter formatter = null;
|
DomainObjectXMLFormatter formatter = null;
|
||||||
while (formatter == null && type != null) {
|
ObjectType curType = type;
|
||||||
formatter = getFormatter(type, context);
|
while (formatter == null && curType != null) {
|
||||||
|
formatter = getFormatter(curType, context);
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("getFormatter(" + type + "," + context + ")=" + formatter);
|
s_log.debug("getFormatter(" + curType + "," + context + ")=" + formatter);
|
||||||
}
|
}
|
||||||
type = type.getSupertype();
|
curType = curType.getSupertype();
|
||||||
}
|
}
|
||||||
return formatter;
|
return formatter;
|
||||||
}
|
}
|
||||||
|
|
@ -153,39 +151,34 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
*
|
*
|
||||||
* @param root the XML element in which to output children
|
* @param root the XML element in which to output children
|
||||||
*/
|
*/
|
||||||
public DomainObjectXMLRenderer(Element root) {
|
public DomainObjectXMLRenderer(final Element root) {
|
||||||
m_element = root;
|
m_element = root;
|
||||||
m_objectElements = new HashMap();
|
m_objectElements = new HashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNamespace(String prefix,
|
public void setNamespace(final String prefix, final String uri) {
|
||||||
String uri) {
|
|
||||||
m_namespacePrefix = prefix;
|
m_namespacePrefix = prefix;
|
||||||
m_namespaceURI = uri;
|
m_namespaceURI = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object format(DomainObject obj,
|
protected Object format(final DomainObject obj, final String path, final Property prop, final Object value) {
|
||||||
String path,
|
|
||||||
Property prop,
|
|
||||||
Object value) {
|
|
||||||
if (m_formatter != null) {
|
if (m_formatter != null) {
|
||||||
String propertyPath = appendToPath(path, prop.getName());
|
final String propertyPath = appendToPath(path, prop.getName());
|
||||||
Object rendered = m_formatter.format(obj,
|
Object rendered = m_formatter.format(obj, propertyPath, prop, value);
|
||||||
propertyPath,
|
|
||||||
prop, value);
|
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("FORMAT " + obj + " m_formatter=" + m_formatter + " rendered=" + rendered);
|
s_log.debug("FORMAT " + obj + " m_formatter=" + m_formatter + " rendered=" + rendered);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rendered == null) {
|
if (rendered == null) {
|
||||||
// try supertype formatters
|
// try supertype formatters
|
||||||
ObjectType objectType = obj.getObjectType().getSupertype();
|
ObjectType objectType = obj.getObjectType().getSupertype();
|
||||||
DomainObjectXMLFormatter formatter = m_formatter;
|
DomainObjectXMLFormatter formatter = m_formatter;
|
||||||
while (rendered == null && formatter != null && objectType != null) {
|
while (rendered == null && formatter != null && objectType != null) {
|
||||||
formatter = findFormatter(objectType, m_context);
|
formatter = findFormatter(objectType, m_context);
|
||||||
if (formatter != null) {
|
if (formatter == null) {
|
||||||
rendered = formatter.format(obj, propertyPath, prop, value);
|
|
||||||
} else {
|
|
||||||
rendered = null;
|
rendered = null;
|
||||||
|
} else {
|
||||||
|
rendered = formatter.format(obj, propertyPath, prop, value);
|
||||||
}
|
}
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("FALLBACK supertype " + objectType + " formatter=" + formatter + " rendered="
|
s_log.debug("FALLBACK supertype " + objectType + " formatter=" + formatter + " rendered="
|
||||||
|
|
@ -203,15 +196,14 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void walk(DomainObject obj,
|
protected void walk(final DomainObject obj, final String context, final DomainObjectTraversalAdapter adapter) {
|
||||||
String context,
|
|
||||||
DomainObjectTraversalAdapter adapter) {
|
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("Traversing " + obj + " for context " + context + " "
|
s_log.debug("Traversing " + obj + " for context " + context + " "
|
||||||
+ "using adapter " + adapter);
|
+ "using adapter " + adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_formatter = findFormatter(obj.getObjectType(), context);
|
m_formatter = findFormatter(obj.getObjectType(), context);
|
||||||
|
|
||||||
m_context = context;
|
m_context = context;
|
||||||
|
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
|
|
@ -224,8 +216,9 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
/**
|
/**
|
||||||
* Determines XML output for root object. If set to true a separate element will be output for the root object, if
|
* Determines XML output for root object. If set to true a separate element will be output for the root object, if
|
||||||
* false, then the element passed into the constructor will be used.
|
* false, then the element passed into the constructor will be used.
|
||||||
|
* @param value
|
||||||
*/
|
*/
|
||||||
public void setWrapRoot(boolean value) {
|
public void setWrapRoot(final boolean value) {
|
||||||
m_wrapRoot = value;
|
m_wrapRoot = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,8 +226,9 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* Determines XML output used for objects. If set to true, then a wrapper XML element will be generated for the
|
* Determines XML output used for objects. If set to true, then a wrapper XML element will be generated for the
|
||||||
* association, and then individual elements generated for each object. If false then no wrapper XML element will be
|
* association, and then individual elements generated for each object. If false then no wrapper XML element will be
|
||||||
* produced.
|
* produced.
|
||||||
|
* @param value
|
||||||
*/
|
*/
|
||||||
public void setWrapObjects(boolean value) {
|
public void setWrapObjects(final boolean value) {
|
||||||
m_wrapObjects = value;
|
m_wrapObjects = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +236,7 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* Determines XML output used for scalar attributes. If set to true, then each attribute is output as a separate
|
* Determines XML output used for scalar attributes. If set to true, then each attribute is output as a separate
|
||||||
* element, otherwise, attributes are output as simple attributes.
|
* element, otherwise, attributes are output as simple attributes.
|
||||||
*/
|
*/
|
||||||
public void setWrapAttributes(boolean value) {
|
public void setWrapAttributes(final boolean value) {
|
||||||
m_wrapAttributes = value;
|
m_wrapAttributes = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +244,7 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
* Determines XML output used for objects. If set to true, then repeated objects will generate full xml. If false
|
* Determines XML output used for objects. If set to true, then repeated objects will generate full xml. If false
|
||||||
* then only the OID will be printed.
|
* then only the OID will be printed.
|
||||||
*/
|
*/
|
||||||
public void setRevisitFullObject(boolean value) {
|
public void setRevisitFullObject(final boolean value) {
|
||||||
m_revisitFullObject = value;
|
m_revisitFullObject = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,11 +260,18 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
return m_wrapRoot;
|
return m_wrapRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void beginObject(DomainObject obj,
|
protected void beginObject(final DomainObject obj, final String path) {
|
||||||
String path) {
|
//if (m_wrapRoot || !path.equals("/object")) {
|
||||||
if (m_wrapRoot || !path.equals("/object")) {
|
if (m_wrapRoot || !("/object".equals(path))) {
|
||||||
String name = m_wrapObjects ? "object" : nameFromPath(path);
|
|
||||||
Element element = newElement(m_element, name);
|
final String name;
|
||||||
|
if (m_wrapObjects) {
|
||||||
|
name = "object";
|
||||||
|
} else {
|
||||||
|
name = nameFromPath(path);
|
||||||
|
}
|
||||||
|
//String name = m_wrapObjects ? "object" : nameFromPath(path);
|
||||||
|
final Element element = newElement(m_element, name);
|
||||||
|
|
||||||
m_elements.push(m_element);
|
m_elements.push(m_element);
|
||||||
m_element = element;
|
m_element = element;
|
||||||
|
|
@ -281,51 +282,48 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void endObject(DomainObject obj,
|
protected void endObject(final DomainObject obj, final String path) {
|
||||||
String path) {
|
//if (m_wrapRoot || !path.equals("/object")) {
|
||||||
if (m_wrapRoot || !path.equals("/object")) {
|
if (m_wrapRoot || !("/object".equals(path))) {
|
||||||
m_element = (Element) m_elements.pop();
|
m_element = (Element) m_elements.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void revisitObject(DomainObject obj,
|
protected void revisitObject(final DomainObject obj, final String path) {
|
||||||
String path) {
|
|
||||||
Element priorElement = null;
|
Element priorElement = null;
|
||||||
if (m_revisitFullObject) {
|
if (m_revisitFullObject) {
|
||||||
priorElement = (Element) m_objectElements.get(obj.getOID());
|
priorElement = (Element) m_objectElements.get(obj.getOID());
|
||||||
}
|
}
|
||||||
if (priorElement != null && (m_elements.search(priorElement) == -1)) {
|
if (priorElement != null && (m_elements.search(priorElement) == -1)) {
|
||||||
String name = m_wrapObjects ? "object" : nameFromPath(path);
|
final String name = m_wrapObjects ? "object" : nameFromPath(path);
|
||||||
Element element = newElement(m_element, name, priorElement);
|
newElement(m_element, name, priorElement);
|
||||||
} else {
|
} else {
|
||||||
String name = m_wrapObjects ? "object" : nameFromPath(path);
|
final String name = m_wrapObjects ? "object" : nameFromPath(path);
|
||||||
Element element = newElement(m_element, name);
|
final Element element = newElement(m_element, name);
|
||||||
element.addAttribute("oid", obj.getOID().toString());
|
element.addAttribute("oid", obj.getOID().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleAttribute(DomainObject obj,
|
protected void handleAttribute(final DomainObject obj, final String path, final Property property) {
|
||||||
String path,
|
final String name = property.getName();
|
||||||
Property property) {
|
final Object value = obj.get(name);
|
||||||
String name = property.getName();
|
|
||||||
Object value = obj.get(name);
|
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
if (m_wrapAttributes) {
|
if (m_wrapAttributes) {
|
||||||
Object formattedValue = format(obj, path, property, value);
|
final Object formattedValue = format(obj, path, property, value);
|
||||||
if (formattedValue instanceof Element) {
|
if (formattedValue instanceof Element) {
|
||||||
m_element.addContent((Element) formattedValue);
|
m_element.addContent((Element) formattedValue);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Element element = newElement(m_element, name);
|
final Element element = newElement(m_element, name);
|
||||||
element.setText((String) format(obj, path, property, value));
|
element.setText((String) format(obj, path, property, value));
|
||||||
|
|
||||||
// Quasimodo:
|
// Quasimodo:
|
||||||
// Special handling of date field, should be done somewhere else
|
// Special handling of date field, should be done somewhere else
|
||||||
// but that seems to be a problem
|
// but that seems to be a problem
|
||||||
if (value instanceof Date) {
|
if (value instanceof Date) {
|
||||||
Date date = (Date) value;
|
final Date date = (Date) value;
|
||||||
Calendar calDate = Calendar.getInstance();
|
final Calendar calDate = Calendar.getInstance();
|
||||||
calDate.setTime(date);
|
calDate.setTime(date);
|
||||||
|
|
||||||
// locale-independent date output
|
// locale-independent date output
|
||||||
|
|
@ -338,10 +336,10 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
|
|
||||||
// Quasimodo: BEGIN
|
// Quasimodo: BEGIN
|
||||||
// Add attributes for date and time
|
// Add attributes for date and time
|
||||||
Locale negLocale = com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale();
|
final Locale negLocale = com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale();
|
||||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.MEDIUM, negLocale);
|
final DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.MEDIUM, negLocale);
|
||||||
DateFormat longDateFormatter = DateFormat.getDateInstance(DateFormat.LONG, negLocale);
|
final DateFormat longDateFormatter = DateFormat.getDateInstance(DateFormat.LONG, negLocale);
|
||||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, negLocale);
|
final DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, negLocale);
|
||||||
element.addAttribute("date", dateFormatter.format(date));
|
element.addAttribute("date", dateFormatter.format(date));
|
||||||
element.addAttribute("longDate", longDateFormatter.format(date));
|
element.addAttribute("longDate", longDateFormatter.format(date));
|
||||||
element.addAttribute("time", timeFormatter.format(date));
|
element.addAttribute("time", timeFormatter.format(date));
|
||||||
|
|
@ -358,37 +356,29 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void beginRole(DomainObject obj,
|
protected void beginRole(final DomainObject obj, final String path, final Property property) {
|
||||||
String path,
|
|
||||||
Property property) {
|
|
||||||
if (m_wrapObjects) {
|
if (m_wrapObjects) {
|
||||||
Element element = newElement(m_element, property.getName());
|
final Element element = newElement(m_element, property.getName());
|
||||||
m_elements.push(m_element);
|
m_elements.push(m_element);
|
||||||
m_element = element;
|
m_element = element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void endRole(DomainObject obj,
|
protected void endRole(final DomainObject obj, final String path, final Property property) {
|
||||||
String path,
|
|
||||||
Property property) {
|
|
||||||
if (m_wrapObjects) {
|
if (m_wrapObjects) {
|
||||||
m_element = (Element) m_elements.pop();
|
m_element = (Element) m_elements.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void beginAssociation(DomainObject obj,
|
protected void beginAssociation(final DomainObject obj, final String path, final Property property) {
|
||||||
String path,
|
|
||||||
Property property) {
|
|
||||||
if (m_wrapObjects) {
|
if (m_wrapObjects) {
|
||||||
Element element = newElement(m_element, property.getName());
|
final Element element = newElement(m_element, property.getName());
|
||||||
m_elements.push(m_element);
|
m_elements.push(m_element);
|
||||||
m_element = element;
|
m_element = element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void endAssociation(DomainObject obj,
|
protected void endAssociation(final DomainObject obj, final String path, final Property property) {
|
||||||
String path,
|
|
||||||
Property property) {
|
|
||||||
if (m_wrapObjects) {
|
if (m_wrapObjects) {
|
||||||
m_element = (Element) m_elements.pop();
|
m_element = (Element) m_elements.pop();
|
||||||
}
|
}
|
||||||
|
|
@ -398,7 +388,7 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
return m_element;
|
return m_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setCurrentElement(Element element) {
|
protected void setCurrentElement(final Element element) {
|
||||||
m_element = element;
|
m_element = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -406,21 +396,42 @@ public class DomainObjectXMLRenderer extends DomainObjectTraversal {
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Element newElement(Element parent,
|
protected Element newElement(final Element parent, final String name) {
|
||||||
String name) {
|
if (m_namespaceURI == null) {
|
||||||
return m_namespaceURI == null
|
return parent.newChildElement(name);
|
||||||
? parent.newChildElement(name)
|
} else {
|
||||||
: parent.newChildElement(m_namespacePrefix + ":" + name,
|
final StringBuffer nameBuffer = new StringBuffer();
|
||||||
m_namespaceURI);
|
nameBuffer.append(m_namespacePrefix);
|
||||||
|
nameBuffer.append(':');
|
||||||
|
nameBuffer.append(name);
|
||||||
|
|
||||||
|
return parent.newChildElement(name, m_namespaceURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return m_namespaceURI == null
|
||||||
|
// ? parent.newChildElement(name)
|
||||||
|
// : parent.newChildElement(m_namespacePrefix + ":" + name,
|
||||||
|
// m_namespaceURI);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Element newElement(Element parent,
|
protected Element newElement(final Element parent, final String name, final Element copy) {
|
||||||
String name,
|
if (m_namespaceURI == null) {
|
||||||
Element copy) {
|
return parent.newChildElement(name, copy);
|
||||||
return m_namespaceURI == null
|
} else {
|
||||||
? parent.newChildElement(name, copy)
|
final StringBuffer nameBuffer = new StringBuffer();
|
||||||
: parent.newChildElement(m_namespacePrefix + ":" + name,
|
nameBuffer.append(m_namespacePrefix);
|
||||||
m_namespaceURI,
|
nameBuffer.append(':');
|
||||||
copy);
|
nameBuffer.append(name);
|
||||||
|
|
||||||
|
return parent.newChildElement(name, m_namespaceURI, copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return m_namespaceURI == null
|
||||||
|
// ? parent.newChildElement(name, copy)
|
||||||
|
// : parent.newChildElement(m_namespacePrefix + ":" + name,
|
||||||
|
// m_namespaceURI,
|
||||||
|
// copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package com.arsdigita.domain;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import com.arsdigita.persistence.metadata.Property;
|
import com.arsdigita.persistence.metadata.Property;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a general purpose traversal adaptor
|
* This is a general purpose traversal adaptor
|
||||||
|
|
@ -157,7 +158,7 @@ public class SimpleDomainObjectTraversalAdapter
|
||||||
* @param prop full path of the property to remove
|
* @param prop full path of the property to remove
|
||||||
*/
|
*/
|
||||||
public void removeAssociationProperty(String prop) {
|
public void removeAssociationProperty(String prop) {
|
||||||
s_log.debug(String.format("Removing association property '%s'", prop));
|
//s_log.debug(String.format("Removing association property '%s'", prop));
|
||||||
m_assoc.remove(prop);
|
m_assoc.remove(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue