001package ball.util.ant.taskdefs;
002/*-
003 * ##########################################################################
004 * Utilities
005 * $Id: XPathEvaluateTask.java 6201 2020-06-16 13:43:29Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/util/ant/taskdefs/XPathEvaluateTask.java $
007 * %%
008 * Copyright (C) 2008 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import ball.xml.XalanConstants;
024import java.io.ByteArrayOutputStream;
025import java.io.File;
026import javax.xml.namespace.QName;
027import javax.xml.parsers.DocumentBuilderFactory;
028import javax.xml.transform.Transformer;
029import javax.xml.transform.TransformerFactory;
030import javax.xml.transform.dom.DOMSource;
031import javax.xml.transform.stream.StreamResult;
032import javax.xml.xpath.XPathConstants;
033import javax.xml.xpath.XPathExpression;
034import javax.xml.xpath.XPathFactory;
035import lombok.Getter;
036import lombok.NoArgsConstructor;
037import lombok.Setter;
038import lombok.ToString;
039import lombok.experimental.Accessors;
040import org.apache.tools.ant.BuildException;
041import org.apache.tools.ant.Task;
042import org.apache.tools.ant.util.ClasspathUtils;
043import org.w3c.dom.Document;
044import org.w3c.dom.NodeList;
045
046import static javax.xml.transform.OutputKeys.INDENT;
047import static javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION;
048
049/**
050 * {@link.uri http://ant.apache.org/ Ant} {@link Task} to test
051 * {@link javax.xml.xpath.XPath} expressions.
052 *
053 * {@ant.task}
054 *
055 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
056 * @version $Revision: 6201 $
057 */
058@AntTask("xpath-evaluate")
059@NoArgsConstructor @ToString
060public class XPathEvaluateTask extends Task
061                               implements AnnotatedAntTask,
062                                          ClasspathDelegateAntTask,
063                                          ConfigurableAntTask, XalanConstants {
064    @Getter @Setter @Accessors(chain = true, fluent = true)
065    private ClasspathUtils.Delegate delegate = null;
066    @NotNull @Getter @Setter
067    private File file = null;
068    @NotNull @Getter @Setter
069    private String expression = null;
070    @NotNull @Getter
071    private QName qname = XPathConstants.STRING;
072    @NotNull @Getter @Setter
073    private int tab = 2;
074
075    public void setQname(String name) throws IllegalArgumentException {
076        try {
077            qname =
078                (QName)
079                XPathConstants.class.getField(name.toUpperCase())
080                .get(null);
081        } catch (Exception exception) {
082            qname = QName.valueOf(name);
083        }
084    }
085
086    @Override
087    public void init() throws BuildException {
088        super.init();
089        ClasspathDelegateAntTask.super.init();
090        ConfigurableAntTask.super.init();
091    }
092
093    @Override
094    public void execute() throws BuildException {
095        super.execute();
096        AnnotatedAntTask.super.execute();
097
098        try {
099            log(String.valueOf(getFile()));
100
101            Document document =
102                DocumentBuilderFactory.newInstance()
103                .newDocumentBuilder()
104                .parse(getFile());
105
106            log(getExpression());
107
108            XPathExpression expression =
109                XPathFactory.newInstance().newXPath()
110                .compile(getExpression());
111            QName qname = getQname();
112            Object value = expression.evaluate(document, qname);
113
114            if (XPathConstants.NODESET.equals(qname)) {
115                Transformer transformer =
116                    TransformerFactory.newInstance().newTransformer();
117
118                transformer.setOutputProperty(OMIT_XML_DECLARATION, YES);
119                transformer.setOutputProperty(INDENT, (tab > 0) ? YES : NO);
120                transformer.setOutputProperty(XALAN_INDENT_AMOUNT.toString(),
121                                              String.valueOf(tab));
122
123                NodeList nodeset = (NodeList) value;
124
125                for (int i = 0; i < nodeset.getLength(); i += 1) {
126                    ByteArrayOutputStream out = new ByteArrayOutputStream();
127
128                    transformer.transform(new DOMSource(nodeset.item(i)),
129                                          new StreamResult(out));
130                    log(out.toString("UTF-8"));
131                }
132            } else {
133                log(String.valueOf(value));
134            }
135        } catch (BuildException exception) {
136            throw exception;
137        } catch (RuntimeException exception) {
138            throw exception;
139        } catch (Exception exception) {
140            throw new BuildException(exception);
141        }
142    }
143}