package org.multibit.mbm.api.hal; /** * <p>XML renderer to provide the following to resources:</p> * <ul> * <li>Minified XML representation</li> * </ul> * * @since 0.0.1 *   */ import com.google.common.base.Optional; import com.theoryinpractise.halbuilder.spi.Link; import com.theoryinpractise.halbuilder.spi.ReadableResource; import com.theoryinpractise.halbuilder.spi.Renderer; import com.theoryinpractise.halbuilder.spi.Resource; import org.jdom.Element; import org.jdom.Namespace; import org.jdom.Text; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import java.io.IOException; import java.io.Writer; import java.util.List; import java.util.Map; import static com.theoryinpractise.halbuilder.impl.api.Support.HREF; import static com.theoryinpractise.halbuilder.impl.api.Support.HREFLANG; import static com.theoryinpractise.halbuilder.impl.api.Support.LINK; import static com.theoryinpractise.halbuilder.impl.api.Support.NAME; import static com.theoryinpractise.halbuilder.impl.api.Support.REL; import static com.theoryinpractise.halbuilder.impl.api.Support.SELF; import static com.theoryinpractise.halbuilder.impl.api.Support.TEMPLATED; import static com.theoryinpractise.halbuilder.impl.api.Support.TITLE; import static com.theoryinpractise.halbuilder.impl.api.Support.XSI_NAMESPACE; public class MinifiedXmlRenderer implements Renderer<String> { public Optional<String> render(ReadableResource resource, Writer writer) { final Element element = renderElement(resource, false); final XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat()); try { outputter.output(element, writer); } catch (IOException e) { throw new RuntimeException(e); } return Optional.absent(); } private Element renderElement(ReadableResource resource, boolean embedded) { final Link resourceLink = resource.getResourceLink(); final String href = resourceLink.getHref(); // Create the root element final Element resourceElement = new Element("resource"); resourceElement.setAttribute("href", href); if (!resourceLink.getRel().equals("self")) { resourceElement.setAttribute("rel", resourceLink.getRel()); } // Only add namespaces to non-embedded resources if (!embedded) { for (Map.Entry<String, String> entry : resource.getNamespaces().entrySet()) { resourceElement.addNamespaceDeclaration( Namespace.getNamespace(entry.getKey(), entry.getValue())); } // Add the instance namespace if there are null properties on this // resource or on any embedded resources. if(resource.hasNullProperties()) { resourceElement.addNamespaceDeclaration(XSI_NAMESPACE); } } //add a comment // resourceElement.addContent(new Comment("Description of a resource")); // add links List<Link> links = resource.getLinks(); for (Link link : links) { Element linkElement = new Element(LINK); if (!link.getRel().contains(SELF)) { linkElement.setAttribute(REL, link.getRel()); linkElement.setAttribute(HREF, link.getHref()); if (link.getName().isPresent()) { linkElement.setAttribute(NAME, link.getName().get()); } if (link.getTitle().isPresent()) { linkElement.setAttribute(TITLE, link.getTitle().get()); } if (link.getHreflang().isPresent()) { linkElement.setAttribute(HREFLANG, link.getHreflang().get()); } if (link.hasTemplate()) { linkElement.setAttribute(TEMPLATED, "true"); } resourceElement.addContent(linkElement); } } // add properties for (Map.Entry<String, Optional<Object>> entry : resource.getProperties().entrySet()) { Element propertyElement = new Element(entry.getKey()); if(entry.getValue().isPresent()) { propertyElement.setContent(new Text(entry.getValue().get().toString())); } else { propertyElement.setAttribute("nil", "true", XSI_NAMESPACE); } resourceElement.addContent(propertyElement); } // add subresources for (Resource halResource : resource.getResources()) { Element subResourceElement = renderElement(halResource, true); resourceElement.addContent(subResourceElement); } return resourceElement; } }