001: package com.technoetic.xplanner.export;
002:
003: import com.technoetic.xplanner.domain.Iteration;
004: import com.technoetic.xplanner.domain.Person;
005: import com.technoetic.xplanner.domain.Project;
006: import com.technoetic.xplanner.domain.Role;
007: import com.technoetic.xplanner.domain.Task;
008: import com.technoetic.xplanner.domain.TimeEntry;
009: import com.technoetic.xplanner.domain.UserStory;
010: import net.sf.hibernate.Session;
011: import org.apache.commons.beanutils.PropertyUtils;
012: import org.apache.commons.betwixt.ElementDescriptor;
013: import org.apache.commons.betwixt.XMLBeanInfo;
014: import org.apache.commons.betwixt.XMLIntrospector;
015: import org.apache.commons.betwixt.expression.Context;
016: import org.apache.commons.betwixt.expression.Expression;
017: import org.apache.commons.betwixt.io.BeanWriter;
018: import org.apache.commons.betwixt.strategy.DecapitalizeNameMapper;
019: import org.apache.commons.collections.CollectionUtils;
020: import org.apache.commons.collections.Predicate;
021: import org.apache.log4j.Logger;
022:
023: import javax.servlet.http.HttpServletResponse;
024: import java.beans.IntrospectionException;
025: import java.io.StringWriter;
026: import java.util.ArrayList;
027: import java.util.List;
028:
029: public class XmlExporter implements Exporter {
030: private Logger log = Logger.getLogger(getClass());
031:
032: public void initializeHeaders(HttpServletResponse response) {
033: response.setHeader("Content-type", "text/xml");
034: response.setHeader("Content-disposition",
035: "inline; filename=export.xml");
036: }
037:
038: public byte[] export(Session session, Object object)
039: throws ExportException {
040: try {
041: StringWriter outputWriter = new StringWriter();
042: outputWriter.write("<?xml version='1.0' ?>");
043: BeanWriter beanWriter = new BeanWriter(outputWriter);
044: beanWriter.getXMLIntrospector().setAttributesForPrimitives(
045: false);
046: beanWriter.setWriteIDs(false);
047: beanWriter.enablePrettyPrint();
048:
049: beanWriter.getXMLIntrospector().setElementNameMapper(
050: new DecapitalizeNameMapper());
051: configureBindings(beanWriter);
052: installCircularRelationshipsHack(beanWriter);
053: ElementDescriptor descriptor = getElementDescriptor(
054: beanWriter.getXMLIntrospector(),
055: XPlannerData.class, "objects");
056: String collectionName = "objects";
057: if (object instanceof Project) {
058: collectionName = "projects";
059: } else if (object instanceof Iteration) {
060: collectionName = "iterations";
061: }
062: descriptor.setLocalName(collectionName);
063: List people = session.find("from person in class "
064: + Person.class.getName());
065: XPlannerData data = new XPlannerData();
066: data.setPeople(people);
067: data.setObjects(new ArrayList());
068: data.getObjects().add(object);
069:
070: beanWriter.write("xplanner", data);
071: return outputWriter.toString().getBytes();
072: } catch (Exception e) {
073: log.error("error formatting XML export", e);
074: return null;
075: }
076: }
077:
078: // todo - Find a way to eliminate this hack as Hibernate dependencies are added.
079: private void installCircularRelationshipsHack(BeanWriter beanWriter)
080: throws IntrospectionException {
081: installRelationshipMapper(beanWriter, Task.class, "story",
082: "story.id");
083: // installRelationshipMapper(beanWriter, Iteration.class, "project", "project.id");
084: }
085:
086: private void installRelationshipMapper(BeanWriter beanWriter,
087: Class aClass, String property, final String propertyPath)
088: throws IntrospectionException {
089: ElementDescriptor taskParentDescriptor = getElementDescriptor(
090: beanWriter.getXMLIntrospector(), aClass, property);
091: taskParentDescriptor.setContextExpression(new Expression() {
092: public Object evaluate(Context context) {
093: try {
094: return PropertyUtils.getProperty(context.getBean(),
095: propertyPath);
096: } catch (Exception e) {
097: throw new RuntimeException(e);
098: }
099: }
100:
101: public void update(Context context, String s) {
102: // no op
103: }
104: });
105: }
106:
107: private ElementDescriptor getElementDescriptor(
108: XMLIntrospector xmlIntrospector, Class beanClass,
109: String property) throws IntrospectionException {
110: ElementDescriptor[] descriptors = xmlIntrospector.introspect(
111: beanClass).getElementDescriptor()
112: .getElementDescriptors();
113: ElementDescriptor descriptor = null;
114: for (int i = 0; i < descriptors.length; i++) {
115: if (descriptors[i].getPropertyName().equals(property)) {
116: descriptor = descriptors[i];
117: }
118: }
119: return descriptor;
120: }
121:
122: private void configureBindings(BeanWriter beanWriter)
123: throws IntrospectionException {
124: XMLBeanInfo beanInfo;
125: beanInfo = configureBeanInfo(beanWriter, Project.class);
126: hideProperty(beanInfo, "currentIteration");
127: beanInfo = configureBeanInfo(beanWriter, Iteration.class);
128: beanInfo = configureBeanInfo(beanWriter, UserStory.class);
129: beanInfo = configureBeanInfo(beanWriter, Task.class);
130: beanInfo = configureBeanInfo(beanWriter, TimeEntry.class);
131: beanInfo = configureBeanInfo(beanWriter, Person.class);
132: hideProperty(beanInfo, "lastUpdateTime");
133: hideProperty(beanInfo, "password");
134: beanInfo = configureBeanInfo(beanWriter, Role.class);
135: hideProperty(beanInfo, "personId");
136: hideProperty(beanInfo, "id");
137: }
138:
139: private XMLBeanInfo configureBeanInfo(BeanWriter beanWriter,
140: Class beanClass) throws IntrospectionException {
141: XMLBeanInfo beanInfo;
142: beanInfo = beanWriter.getXMLIntrospector()
143: .introspect(beanClass);
144: hideProperty(beanInfo, "lastUpdateTime");
145: return beanInfo;
146: }
147:
148: // private void renderAsAttribute(XMLBeanInfo beanInfo, String property) {
149: // hideProperty(beanInfo, property);
150: // AttributeDescriptor[] originalAttributeDescriptors = beanInfo.getElementDescriptor().getAttributeDescriptors();
151: // AttributeDescriptor[] attributeDescriptors = new AttributeDescriptor[originalAttributeDescriptors.length+1];
152: // System.arraycopy(originalAttributeDescriptors, 0, attributeDescriptors, 0, originalAttributeDescriptors.length);
153: // AttributeDescriptor attributeDescriptor = new AttributeDescriptor(property);
154: // attributeDescriptor.setPropertyName(property);
155: // attributeDescriptor.setPropertyType(Object.class);
156: // BeanInfo bi = null;
157: // try {
158: // bi = Introspector.getBeanInfo(beanInfo.getBeanClass());
159: // } catch (IntrospectionException e) {
160: // e.printStackTrace(); //To change body of catch statement use Options | File Templates.
161: // }
162: // PropertyDescriptor propertyDescriptor = null;
163: // PropertyDescriptor propertyDescriptors[] = bi.getPropertyDescriptors();
164: // for (int i = 0; i < propertyDescriptors.length; i++) {
165: // if (propertyDescriptors[i].fromNameKey().equals(property)) {
166: // propertyDescriptor = propertyDescriptors[i];
167: // break;
168: // }
169: // }
170: // attributeDescriptor.setTextExpression(new MethodExpression(propertyDescriptor.getReadMethod()));
171: // attributeDescriptors[originalAttributeDescriptors.length] = attributeDescriptor;
172: // beanInfo.getElementDescriptor().setAttributeDescriptors(attributeDescriptors);
173: //
174: // }
175:
176: private static void hideProperty(XMLBeanInfo beanInfo,
177: final String property) {
178: ArrayList elementDescriptors = new ArrayList();
179: ElementDescriptor elementDescriptor = beanInfo
180: .getElementDescriptor();
181: CollectionUtils.addAll(elementDescriptors, elementDescriptor
182: .getElementDescriptors());
183: elementDescriptors.remove(CollectionUtils.find(
184: elementDescriptors, new Predicate() {
185: public boolean evaluate(Object o) {
186: return ((ElementDescriptor) o)
187: .getPropertyName().equals(property);
188: }
189: }));
190: elementDescriptor
191: .setElementDescriptors((ElementDescriptor[]) elementDescriptors
192: .toArray(new ElementDescriptor[elementDescriptors
193: .size()]));
194: }
195:
196: public static class XPlannerData {
197: private List people;
198: private List objects;
199:
200: public List getPeople() {
201: return people;
202: }
203:
204: public void setPeople(List people) {
205: this .people = people;
206: }
207:
208: public void setObjects(List objects) {
209: this .objects = objects;
210: }
211:
212: public List getObjects() {
213: return objects;
214: }
215: }
216: }
|