/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.oaipmh.harvester;
import static org.apache.commons.lang3.StringUtils.trimToNull;
import static org.opencastproject.util.data.Option.option;
import static org.opencastproject.util.data.functions.Booleans.eq;
import org.opencastproject.util.data.Option;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
/**
* Base class for all OAI-PMH responses.
*/
public abstract class OaiPmhResponse {
protected final Document doc;
protected final XPath xpath;
public OaiPmhResponse(Document doc) {
this.doc = doc;
this.xpath = createXPath();
}
/**
* Create an XPath object suitable for processing OAI-PMH response documents.
*/
public static XPath createXPath() {
XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(OaiPmhNamespaceContext.getContext());
return xPath;
}
/**
* Check if response is an error response.
*/
public boolean isError() {
return xpathExists("/oai20:OAI-PMH/oai20:error");
}
protected boolean isError(String code) {
return getErrorCode().map(eq(code)).getOrElse(false);
}
/**
* Get the error code if this is an error response.
*/
public Option<String> getErrorCode() {
return option(trimToNull(xpathString("/oai20:OAI-PMH/oai20:error/@code")));
}
/** Return the request tag. */
public String getRequest() {
return xpathString("/oai20:OAI-PMH/oai20:request");
}
/**
* Evaluate the xpath expression against the contained document. The expression must return a string (text).
*/
protected String xpathString(String expr) {
try {
return ((String) xpath.evaluate(expr, doc, XPathConstants.STRING)).trim();
} catch (XPathExpressionException e) {
throw new RuntimeException("malformed xpath expression " + expr, e);
}
}
/**
* Evaluate the xpath expression against the contained document. The expression must return a node.
*/
protected Node xpathNode(String expr) {
try {
return (Node) xpath.evaluate(expr, doc, XPathConstants.NODE);
} catch (XPathExpressionException e) {
throw new RuntimeException("malformed xpath expression " + expr, e);
}
}
public static Node xpathNode(XPath xpath, Node context, String expr) {
if (expr.startsWith("/"))
throw new IllegalArgumentException("An xpath expression that evaluates relative to a given context node "
+ "must not be absolute, i.e. start with a '/'. In this case the expression is evaluated against the"
+ "whole document which might not be wanted.");
try {
return (Node) xpath.evaluate(expr, context, XPathConstants.NODE);
} catch (XPathExpressionException e) {
throw new RuntimeException("malformed xpath expression " + expr, e);
}
}
/**
* Evaluate the xpath expression against the contained document. The expression must return a node list.
*/
protected NodeList xpathNodeList(String expr) {
try {
return (NodeList) xpath.evaluate(expr, doc, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
throw new RuntimeException("malformed xpath expression " + expr, e);
}
}
protected boolean xpathExists(String expr) {
return xpathNodeList(expr).getLength() > 0;
}
}