/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
*/
package org.identityconnectors.patternparser;
import java.io.StringReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* Transforms may be applied to the result of a pattern match.
* <p>
* Transforms have completely arbitrary input and output; they can simply modify
* an input string, or change it into a different object, such as an array, a
* Date, or a List.
* <p>
* Transforms may be applied to the output of other Transforms, creating a chain
* of transforms.
* <p>
* Predefined transforms each have their own XML representation. If additional
* Transforms are needed, it is possible to create new subclasses of Transform.
* If you do this, you must implement the methods:
* <ul>
* <li><b>transform</b> -- perform the transform.</li>
* <li><b>getChildren</b> -- if your Transform has child Transforms, this must
* produce an XML string representing the children.</li>
* <li><b>getAttributes</b> -- if your Transform has attributes, this must
* produce a string representing the attributes.</li>
*
* </ul>
* Represented in XML by
*
* <pre>
* <Transform class='<b>class</b>' ...attributes...>
* ...children...
* </Transform>
* </pre>
*
* where
* <ul>
* <li><b>class</b> -- the fully-qualified name of the Transform subclass
* </ul>
*
* @param <T>
* Type of the transformed object.
*/
public abstract class Transform<T> {
protected static final String CLASS = "class";
protected static Element getFirstChildElement(Element element) {
NodeList nodes = element.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
if (nodes.item(i) instanceof Element) {
return (Element) nodes.item(i);
}
}
return null;
}
protected static String attributeToString(String name, String value) {
return " " + name + "='" + value.replaceAll("'", "'") + "'";
}
protected String getAttributes() {
if (getClass().getPackage().equals(Transform.class.getPackage())) {
return "";
} else {
return attributeToString(CLASS, getClass().getName());
}
}
protected String getChildren(int indent) {
return "";
}
public String toXml(int indent) {
String children = getChildren(indent);
StringBuffer pad = new StringBuffer();
String className;
if (getClass().getPackage().equals(Transform.class.getPackage())) {
className = getClass().getSimpleName();
} else {
className = "Transform";
}
for (int i = 0; i < indent; i++) {
pad.append(" ");
}
if (children.length() == 0) {
return pad + "<" + className + getAttributes() + "/>\n";
} else {
return pad + "<" + className + getAttributes() + ">\n" + children + pad + "</"
+ className + ">\n";
}
}
/**
* Transform an input object.
*
* @param input
* the object to be transformed
* @return the transformed object
* @throws Exception
*/
public abstract T transform(Object input) throws Exception;
/**
* Factory method to create a Transform from an Element representing the
* transform.
*
* @param element
* @return
* @throws IllegalArgumentException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static Transform newTransform(Element element) throws InstantiationException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException,
ClassNotFoundException {
String className = element.getAttribute(CLASS);
if (className.length() == 0) {
className = Transform.class.getPackage().getName() + "." + element.getTagName();
}
Class<? extends Transform> clazz = (Class<? extends Transform>) Class.forName(className);
Constructor<? extends Transform> constructor = clazz.getConstructor(Element.class);
return constructor.newInstance(element);
}
public static Transform newTransform(String string) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
DocumentBuilder parser = factory.newDocumentBuilder();
Document document = parser.parse(new InputSource(new StringReader(string)));
NodeList elements = document.getChildNodes();
for (int i = 0; i < elements.getLength(); i++) {
if (elements.item(i) instanceof Element) {
return Transform.newTransform((Element) elements.item(i));
}
}
return null;
}
};