org.theospi.portfolio.shared.model.impl.GenericXmlRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.theospi.portfolio.shared.model.impl.GenericXmlRenderer.java

Source

/**********************************************************************************
* $URL:https://source.sakaiproject.org/svn/osp/trunk/common/api-impl/src/java/org/theospi/portfolio/shared/model/impl/GenericXmlRenderer.java $
* $Id:GenericXmlRenderer.java 9134 2006-05-08 20:28:42Z chmaurer@iupui.edu $
***********************************************************************************
*
 * Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*
**********************************************************************************/
package org.theospi.portfolio.shared.model.impl;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.sakaiproject.metaobj.shared.ArtifactFinder;
import org.sakaiproject.metaobj.shared.EntityContextFinder;
import org.sakaiproject.metaobj.shared.mgt.PresentableObjectHome;
import org.sakaiproject.metaobj.shared.model.Artifact;
import org.sakaiproject.metaobj.shared.model.Id;
import org.sakaiproject.metaobj.utils.xml.SchemaInvalidException;
import org.theospi.portfolio.shared.model.OspException;

/**
 * This class renders an object into an xml object.  This implementation
 * uses bean introspection to navigate the object model and convert into
 * a jdom model. In relies on the objectStructure xml file to specify which
 * properties to traverse.  The prevents circlular references from being
 * traversed.
 *
 * Valid values for type attribute are: collection, artifact, object.
 * If not specified object is assumed.
 *
 *
 */
public class GenericXmlRenderer implements PresentableObjectHome {
    protected final Log logger = LogFactory.getLog(getClass());
    private ArtifactFinder artifactFinder;
    private String objectStructure;
    private String rootName;
    private String supportedType;
    private String artifactType;

    protected Element getObjectStructureRoot() {
        SAXBuilder builder = new SAXBuilder();
        builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // SAK-23131
        InputStream is = null;
        try {
            is = getClass().getResourceAsStream(getObjectStructure());
            Document doc = builder.build(is);
            return doc.getRootElement();
        } catch (Exception e) {
            throw new SchemaInvalidException(e);
        } finally {
            try {
                is.close();
            } catch (Exception e) {
                logger.warn("Error cleaning up resource:", e);
            }
        }
    }

    protected Element getXml(Object object, String container, String site, String context) {
        Element rootElement = new Element(getRootName());
        try {
            addObjectNodeInfo(rootElement, object, getObjectStructureRoot(), container, site, context);
        } catch (IntrospectionException e) {
            logger.error("", e);
        }

        return rootElement;
    }

    protected boolean isTraversableType(PropertyDescriptor descriptor, Element structure) {
        if (structure == null) {
            return false;
        }
        if (structure.getChild(descriptor.getName()) != null || structure.getName().equals(descriptor.getName())) {
            return true;
        }

        return false;
    }

    protected void addObjectNodeInfo(Element parentNode, Object object, Element structure, String container,
            String site, String context) throws IntrospectionException {
        if (object == null)
            return;
        // go through each property... put each one in...
        logger.debug("adding object of class " + object.getClass());

        BeanInfo info = Introspector.getBeanInfo(object.getClass());

        PropertyDescriptor[] props = info.getPropertyDescriptors();

        for (int i = 0; i < props.length; i++) {
            PropertyDescriptor property = props[i];
            logger.debug("examining property: " + property.getName());
            if (isTraversableType(property, structure)) {
                if (isCollection(property, structure)) {
                    addCollectionItems(parentNode, property, object, structure, container, site, context);
                } else if (isArtifact(property, structure)) {
                    addArtifactItem(parentNode, property, object, container, site, context);
                } else {
                    addItem(parentNode, property, object, structure, container, site, context);
                }
            } else {
                addItemToXml(parentNode, property, object);
            }

        }
    }

    protected void addItemToXml(Element parentNode, PropertyDescriptor prop, Object object) {
        String attribName = prop.getName();

        logger.debug("adding attribute: " + attribName);

        Method readMethod = prop.getReadMethod();
        if (readMethod == null || readMethod.getParameterTypes().length > 0
                || Collection.class.isAssignableFrom(readMethod.getReturnType())) {
            logger.debug("skipping attrib: " + attribName);
            return;
        }

        Element attribute = new Element(attribName);
        Object attribValue = null;

        try {
            attribValue = readMethod.invoke(object, (Object[]) null);
        } catch (IllegalAccessException e) {
            logger.error("could not get attribute", e);
        } catch (InvocationTargetException e) {
            logger.error("could not get attribute", e);
        }
        if (attribValue != null && attribValue.toString().length() > 0) {
            logger.debug("value for attrib " + attribName + " is not null.");
            attribute.addContent(attribValue.toString());
        }

        parentNode.addContent(attribute);
    }

    protected void addItem(Element parentNode, PropertyDescriptor prop, Object object, Element structure,
            String container, String site, String context) {
        logger.debug("addItem()");

        Method readMethod = prop.getReadMethod();
        Element newElement = new Element(prop.getName());
        try {
            Object newObject = readMethod.invoke(object, (Object[]) null);
            parentNode.addContent(newElement);
            addObjectNodeInfo(newElement, newObject, structure.getChild(prop.getName()), container, site, context);
        } catch (IllegalAccessException e) {
            logger.error("could not get attribute", e);
        } catch (InvocationTargetException e) {
            logger.error("could not get attribute", e);
        } catch (IntrospectionException e) {
            logger.error("could not get attribute", e);
        }
    }

    protected void addArtifactItem(Element parentNode, PropertyDescriptor prop, Object object, String container,
            String site, String context) {
        logger.debug("addArtifactItem()");

        Method readMethod = prop.getReadMethod();
        Id artifactId = null;
        try {
            artifactId = (Id) readMethod.invoke(object, (Object[]) null);

        } catch (IllegalAccessException e) {
            logger.error("could not get attribute", e);
        } catch (InvocationTargetException e) {
            logger.error("could not get attribute", e);
        }

        logger.debug("finding artifact with id=" + artifactId);

        Artifact art = getArtifactFinder().load(artifactId);

        if (art.getHome() instanceof PresentableObjectHome) {
            PresentableObjectHome home = (PresentableObjectHome) art.getHome();
            Element node = home.getArtifactAsXml(art, container, site, context);
            node.setName("artifact");
            parentNode.addContent(node);
        }
    }

    protected void addCollectionItems(Element parentNode, PropertyDescriptor prop, Object object, Element structure,
            String container, String site, String context) {
        logger.debug("addCollectionItems()");

        Method readMethod = prop.getReadMethod();
        Element newListElement = new Element(prop.getName());
        try {
            Object newObject = readMethod.invoke(object, (Object[]) null);
            parentNode.addContent(newListElement);
            Collection items = (Collection) newObject;
            int index = 0;
            for (Iterator i = items.iterator(); i.hasNext();) {
                Element newElement = new Element(getCollectionItemName(prop.getName()));
                newElement.setAttribute("index", String.valueOf(index));
                newListElement.addContent(newElement);

                Element elementStructure = structure.getChild(prop.getName());
                if (elementStructure == null && structure.getAttributeValue("isNested") != null
                        && structure.getAttributeValue("isNested").equals("true")) {
                    elementStructure = structure.getParentElement().getChild(prop.getName());
                }
                addObjectNodeInfo(newElement, i.next(), elementStructure, container, site, context);
                index++;
            }
        } catch (IllegalAccessException e) {
            logger.error("could not get attribute", e);
        } catch (InvocationTargetException e) {
            logger.error("could not get attribute", e);
        } catch (IntrospectionException e) {
            logger.error("could not get attribute", e);
        }

    }

    protected String getCollectionItemName(String listName) {
        if (listName.endsWith("s")) {
            return listName.substring(0, listName.length() - 1);
        }
        return listName;
    }

    protected boolean isArtifact(PropertyDescriptor prop, Element structure) {
        Element child = structure.getChild(prop.getName());
        String typeAttribute = child.getAttributeValue("type");
        if (typeAttribute != null && typeAttribute.equals("artifact")) {
            return true;
        }
        return false;
    }

    protected boolean isCollection(PropertyDescriptor prop, Element structure) {
        Element elementStructure = structure.getChild(prop.getName());
        if (elementStructure == null && structure.getAttributeValue("isNested") != null
                && structure.getAttributeValue("isNested").equals("true")) {
            elementStructure = structure.getParentElement().getChild(prop.getName());
        } else if (elementStructure == null) {
            return false;
        }
        String typeAttribute = elementStructure.getAttributeValue("type");
        if (typeAttribute != null && typeAttribute.equals("collection")) {
            return true;
        }
        return false;
    }

    public Element getArtifactAsXml(Artifact artifact) {
        return getArtifactAsXml(artifact, null, null, null);
    }

    public Element getArtifactAsXml(Artifact artifact, String container, String site, String context) {
        try {
            Class supportedType = Class.forName(getSupportedType());
            if (supportedType.isAssignableFrom(artifact.getClass())) {
                return getXml(artifact, container, site, context);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(getSupportedType() + " is not a valid class: " + e.getMessage(), e);
        }

        throw new OspException("Expecting object of type: " + getSupportedType() + " but found object of type "
                + artifact.getClass());
    }

    public ArtifactFinder getArtifactFinder() {
        return artifactFinder;
    }

    public void setArtifactFinder(ArtifactFinder artifactFinder) {
        this.artifactFinder = artifactFinder;
    }

    public String getObjectStructure() {
        return objectStructure;
    }

    public String getRootName() {
        return rootName;
    }

    public void setRootName(String rootName) {
        this.rootName = rootName;
    }

    public void setObjectStructure(String objectStructure) {
        this.objectStructure = objectStructure;
    }

    public String getSupportedType() {
        return supportedType;
    }

    public void setSupportedType(String supportedType) {
        this.supportedType = supportedType;
    }

    public String getArtifactType() {
        return artifactType;
    }

    public void setArtifactType(String artifactType) {
        this.artifactType = artifactType;
    }
}