/** Copyright (C) 2012 Delcyon, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.delcyon.capo.controller.elements; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.delcyon.capo.CapoApplication; import com.delcyon.capo.controller.AbstractClientSideControl; import com.delcyon.capo.controller.ControlElementProvider; import com.delcyon.capo.controller.client.ClientSideControl; import com.delcyon.capo.resourcemanager.ContentFormatType; import com.delcyon.capo.resourcemanager.ResourceDescriptor; import com.delcyon.capo.resourcemanager.ResourceParameter; import com.delcyon.capo.resourcemanager.ResourceParameterBuilder; import com.delcyon.capo.util.diff.Diff; import com.delcyon.capo.util.diff.XMLTextDiff; import com.delcyon.capo.xml.XMLDiff; import com.delcyon.capo.xml.XPath; /** * @author jeremiah * */ @ControlElementProvider(name="diff") public class DiffElement extends AbstractClientSideControl implements ClientSideControl { private enum Attributes { name,base, mod,dst; } private static final String[] supportedNamespaces = {CapoApplication.SERVER_NAMESPACE_URI,CapoApplication.CLIENT_NAMESPACE_URI}; private static final String[] functionNames = {}; @Override public Attributes[] getAttributes() { return Attributes.values(); } @Override public Attributes[] getRequiredAttributes() { return new Attributes[]{Attributes.base,Attributes.mod}; } @Override public String[] getSupportedNamespaces() { return supportedNamespaces; } @Override public Element processClientSideElement() throws Exception { // CommandExecution commandExecution = new CommandExecution(controlElementDeclaration.getAttribute(Attributes.exec.toString()), controlElementDeclaration.getAttribute(Attributes.timeout.toString())); // commandExecution.executeCommand(); // controlElementDeclaration.setAttribute(Attributes.exitCode.toString(), commandExecution.getExitCode()+""); // Element stdoutElement = controlElementDeclaration.getOwnerDocument().createElement(Children.stdout.toString()); // stdoutElement.setTextContent(commandExecution.getStdout()); // controlElementDeclaration.appendChild(stdoutElement); // Element stderrElement = controlElementDeclaration.getOwnerDocument().createElement(Children.stderr.toString()); // stderrElement.setTextContent(commandExecution.getStderr()); // controlElementDeclaration.appendChild(stderrElement); // return (Element)(controlElementDeclaration.cloneNode(true)); return null; } @Override public Object processServerSideElement() throws Exception { // if (controlElementDeclaration.getNamespaceURI().equals(GroupElement.CLIENT_NAMESPACE_URI)) // { // // Element newCommandElement = controllerClientRequestProcessor.sendServerSideClientElement((Element) parentGroup.replaceVarsInAttributeValues(controlElementDeclaration.cloneNode(true))); // //replace our original element in the document with the newly returned element // //this is a shortcut, perhaps we should just merge all of the children into the old element // controlElementDeclaration.getParentNode().replaceChild(newCommandElement, controlElementDeclaration); // //set our field with the old element to the new element, so nothing goes wonky, and so that any XPath's will have the correct reference // controlElementDeclaration = newCommandElement; // // if (controlElementDeclaration.hasAttribute(Attributes.name.toString())) // { // parentGroup.set(controlElementDeclaration.getAttribute(Attributes.name.toString()), XPath.getXPath(controlElementDeclaration)); // } // } // else // { // //TODO run server side command // } ResourceDescriptor baseResourceDescriptor = getParentGroup().openResourceDescriptor(this, getAttributeValue(Attributes.base)); ResourceDescriptor modResourceDescriptor = getParentGroup().openResourceDescriptor(this, getAttributeValue(Attributes.mod)); ResourceParameter[] resourceParameters = ResourceParameterBuilder.getResourceParameters(getControlElementDeclaration()); //we always have to search for the lowest common denominator BIN=>TEXT=>XML if (baseResourceDescriptor.getResourceMetaData(getParentGroup(),resourceParameters).getContentFormatType() == ContentFormatType.XML || modResourceDescriptor.getResourceMetaData(getParentGroup(),resourceParameters).getContentFormatType() == ContentFormatType.XML) { Document baseDocument = CapoApplication.getDocumentBuilder().parse(baseResourceDescriptor.getInputStream(getParentGroup(),resourceParameters)); Document modDocument = CapoApplication.getDocumentBuilder().parse(modResourceDescriptor.getInputStream(getParentGroup(),resourceParameters)); XMLDiff xmlDiff = new XMLDiff(); Document differenceDocument = xmlDiff.getDifferences(baseDocument,modDocument); //XPath.dumpNode(differenceDocument, System.err); getControlElementDeclaration().appendChild(getControlElementDeclaration().getOwnerDocument().adoptNode(differenceDocument.getDocumentElement())); } else if (baseResourceDescriptor.getResourceMetaData(getParentGroup(),resourceParameters).getContentFormatType() == ContentFormatType.TEXT || modResourceDescriptor.getResourceMetaData(getParentGroup(),resourceParameters).getContentFormatType() == ContentFormatType.TEXT) { Diff diff = new Diff(baseResourceDescriptor.getInputStream(getParentGroup(),resourceParameters), modResourceDescriptor.getInputStream(getParentGroup(),resourceParameters)); XMLTextDiff xmlTextDiff = new XMLTextDiff(); Element differenceElement = xmlTextDiff.getDifferenceElement(diff); getControlElementDeclaration().appendChild(getControlElementDeclaration().getOwnerDocument().adoptNode(differenceElement)); } else //assume both are BINARY at this point { //TODO deal with Binary diffs. going to need to set a token list for this Diff diff = new Diff(baseResourceDescriptor.getInputStream(getParentGroup(),resourceParameters), modResourceDescriptor.getInputStream(getParentGroup(),resourceParameters)); } baseResourceDescriptor.close(getParentGroup(),resourceParameters); modResourceDescriptor.close(getParentGroup(),resourceParameters); return null; } }