/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.api.internal;
import groovy.lang.Closure;
import groovy.util.Node;
import groovy.util.XmlNodePrinter;
import groovy.util.XmlParser;
import groovy.xml.XmlUtil;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.gradle.api.Action;
import org.gradle.api.Transformer;
import org.gradle.api.artifacts.maven.XmlProvider;
import org.gradle.util.UncheckedException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class XmlTransformer implements Transformer<String> {
private final List<Action<? super XmlProvider>> actions = new ArrayList<Action<? super XmlProvider>>();
public void addAction(Action<? super XmlProvider> provider) {
actions.add(provider);
}
public void addAction(Closure closure) {
actions.add((Action<XmlProvider>) DefaultGroovyMethods.asType(closure, Action.class));
}
public String transform(String original) {
return doTransform(original).toString();
}
public void transform(String original, Writer destination) {
doTransform(original).writeTo(destination);
}
public void transform(Node original, Writer destination) {
doTransform(original).writeTo(destination);
}
private XmlProviderImpl doTransform(String original) {
XmlProviderImpl provider = new XmlProviderImpl(original);
provider.apply(actions);
return provider;
}
private XmlProviderImpl doTransform(Node original) {
XmlProviderImpl provider = new XmlProviderImpl(original);
provider.apply(actions);
return provider;
}
private static class XmlProviderImpl implements XmlProvider {
private StringBuilder builder;
private Node node;
private String stringValue;
private Element element;
public XmlProviderImpl(String original) {
this.stringValue = original;
}
public XmlProviderImpl(Node original) {
this.node = original;
}
public void apply(Iterable<Action<? super XmlProvider>> actions) {
for (Action<? super XmlProvider> action : actions) {
action.execute(this);
}
}
@Override
public String toString() {
StringWriter writer = new StringWriter();
writeTo(writer);
return writer.toString();
}
public void writeTo(Writer writer) {
try {
if (node != null) {
PrintWriter printWriter = new PrintWriter(writer);
new XmlNodePrinter(printWriter).print(node);
printWriter.flush();
} else if (element != null) {
PrintWriter printWriter = new PrintWriter(writer);
XmlUtil.serialize(element, printWriter);
printWriter.flush();
} else if (builder != null) {
writer.append(builder);
} else {
writer.append(stringValue);
}
} catch (IOException e) {
throw UncheckedException.asUncheckedException(e);
}
}
public StringBuilder asString() {
if (builder == null) {
builder = new StringBuilder(toString());
node = null;
element = null;
}
return builder;
}
public Node asNode() {
if (node == null) {
try {
node = new XmlParser().parseText(toString());
} catch (Exception e) {
throw UncheckedException.asUncheckedException(e);
}
builder = null;
element = null;
}
return node;
}
public Element asElement() {
if (element == null) {
Document document;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(toString())));
} catch (Exception e) {
throw UncheckedException.asUncheckedException(e);
}
element = document.getDocumentElement();
builder = null;
node = null;
}
return element;
}
}
}