package org.uncertweb.ps.handler.soap; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.jdom.Content; import org.jdom.Element; import org.uncertweb.ps.data.DataDescription; import org.uncertweb.ps.data.DataReference; import org.uncertweb.ps.data.Output; import org.uncertweb.ps.data.ProcessOutputs; import org.uncertweb.ps.data.RequestedOutput; import org.uncertweb.ps.data.Response; import org.uncertweb.ps.encoding.EncodeException; import org.uncertweb.ps.encoding.Encoding; import org.uncertweb.ps.encoding.EncodingRepository; import org.uncertweb.ps.encoding.xml.AbstractXMLEncoding; import org.uncertweb.ps.handler.ResponseGenerateException; import org.uncertweb.ps.handler.data.DataReferenceGenerator; import org.uncertweb.ps.process.AbstractProcess; import org.uncertweb.ps.process.ProcessRepository; import org.uncertweb.ps.storage.StorageException; import org.uncertweb.xml.Namespaces; public class XMLResponseGenerator { private static final Logger logger = Logger.getLogger(XMLResponseGenerator.class); public static Element generate(Response response) throws ResponseGenerateException { return generate(response, null); } public static Element generate(Response response, List<RequestedOutput> requestedOutputs) throws ResponseGenerateException { // get identifier, process, outputs String processIdentifier = response.getProcessIdentifier(); AbstractProcess process = ProcessRepository.getInstance().getProcess(processIdentifier); ProcessOutputs outputs = response.getOutputs(); // generate response Element responseElement = new Element(processIdentifier + "Response", Namespaces.PS); // add outputs for (String outputIdentifier : process.getOutputIdentifiers()) { // get output from process Output output = outputs.get(outputIdentifier); // check if output was requested and as reference boolean requested = false; boolean reference = false; if (requestedOutputs == null) { requested = true; } else { for (RequestedOutput reqOutput : requestedOutputs) { if (reqOutput.getName().equals(output.getIdentifier())) { requested = true; reference = reqOutput.isReference(); } } } // add output if (requested) { // get objects related to output List<Object> objects; if (output.isSingleOutput()) { objects = new ArrayList<Object>(); objects.add(output.getAsSingleOutput().getObject()); } else { objects = output.getAsMultipleOutput().getObjects(); } // encode each object DataDescription dataDescription = process.getOutputDataDescription(outputIdentifier); for (Object o : objects) { try { // base element Element outputElement = new Element(outputIdentifier, Namespaces.PS); responseElement.addContent(outputElement); // generate Content dataContent = generateData(o, dataDescription.getType(), reference); outputElement.addContent(dataContent); } catch (EncodeException e) { String message = "Couldn't encode data for " + output.getIdentifier() + "."; logger.error(message); throw new ResponseGenerateException(message, e); } } } } return responseElement; } private static Content generateData(Object object, Class<?> type, boolean reference) throws EncodeException, ResponseGenerateException { // get encoding EncodingRepository encodingRepo = EncodingRepository.getInstance(); Encoding xmlEncoding = encodingRepo.getXMLEncoding(type); Encoding binaryEncoding = encodingRepo.getBinaryEncoding(type); if (xmlEncoding == null && binaryEncoding == null) { // FIXME: not a client problem throw new ResponseGenerateException("No encoding found for type " + type.getName() + "."); } else { Content content; if (reference || xmlEncoding == null) { try { content = generateReferenceData(object, type); } catch (StorageException e) { throw new ResponseGenerateException("Couldn't store data for reference.", e); } } else { content = generateInlineData(object, type); } return content; } } private static Content generateReferenceData(Object object, Class<?> type) throws EncodeException, StorageException { // generate data DataReference ref = new DataReferenceGenerator().generate(object, AbstractXMLEncoding.class); // add reference url to response Element referenceElement = new Element("DataReference", Namespaces.PS); referenceElement.setAttribute("href", ref.getURL().toString()); referenceElement.setAttribute("mimeType", ref.getMimeType()); return referenceElement; } private static Content generateInlineData(Object object, Class<?> dataClass) throws EncodeException { AbstractXMLEncoding encoding = EncodingRepository.getInstance().getXMLEncoding(dataClass); return encoding.encode(object).detach(); } }