package be.error.wsproxy.interceptors.logging; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.springframework.ws.WebServiceMessage; import org.springframework.xml.xpath.XPathExpression; import org.springframework.xml.xpath.XPathExpressionFactoryBean; /** * Contains an {@link XPathExpression} and extra data to execute the expression on a {@link WebServiceMessage}. * <ul> * <li>The type of result that is selected by the expression, either {@link XPathExpressionType#NODE} or * {@link XPathExpressionType#VALUE}.</li> * <li>The scope in which the XPath is expected to execute. Either from the start of the SOAP document * {@link XPathExpressionScope#SOAP_ENVELOPE} or from the body {@link XPathExpressionScope#SOAP_BODY}</li> * <li>{@link #setXPathExpressionResultCardinality(XPathExpressionResultCardinality)} to indicate that the value to be * retrieved is mandatory blocking, mandatory or optional. See {@link XPathExpressionResultCardinality} for more detail. * </li> * <li>A String identifier that gives an identification to this expression. This can be a description or word that * describes what this expression selects.</li> * </ul> * * @see WebServiceMessageXPathExtractor * * @author Koen Serneels */ public class WebServiceMessageXPathExpressionMetaData { /** * Indicates to what the XPath expression evaluates. This is either the value of an element or a complete node (in * that case an XML fragment is selected) */ public static enum XPathExpressionType { VALUE, NODE; } /** * Indicates where the given XPath expression starts. Is it from the top of the SOAP document then * {@link #SOAP_ENVELOPE} should be used. Is it relative to the SOAP Body, then {@link #SOAP_BODY} should be used. */ public static enum XPathExpressionScope { SOAP_ENVELOPE, SOAP_BODY; } /** * The value selected by an XPath expression can be absent. When optional it does not matter if the value is absent. * This is for optional fields that we know about that they can be absent. Use {@link #OPTIONAL} in that case. If * result values are expected to be always there, but the fact that if they are not is not severe (we would like to * know about it, but don't block processing for example) use {@link #MANDATORY}. If a mandatory value is absent and * we like to block processing because of it, use {@link #MANDATORY_BLOCKING}. * <p> * * <b>default is {@link #MANDATORY}</b> */ public static enum XPathExpressionResultCardinality { MANDATORY_BLOCKING, MANDATORY, OPTIONAL; } private final String xPathKey; private final String unparsedXPathExpression; private XPathExpression xPathExpression; private XPathExpressionType xPathExpressionType = XPathExpressionType.VALUE; private XPathExpressionScope xPathExpressionScope = XPathExpressionScope.SOAP_BODY; private XPathExpressionResultCardinality xPathExpressionResultCardinality = XPathExpressionResultCardinality.MANDATORY; public WebServiceMessageXPathExpressionMetaData(String xPathExpression, String xPathKey) { if (StringUtils.isBlank(xPathKey)) { throw new IllegalArgumentException("xPathKey cannot be absent"); } this.xPathKey = xPathKey; this.unparsedXPathExpression = xPathExpression; XPathExpressionFactoryBean xPathExpressionFactoryBean = new XPathExpressionFactoryBean(); xPathExpressionFactoryBean.setExpression(xPathExpression); xPathExpressionFactoryBean.afterPropertiesSet(); try { this.xPathExpression = xPathExpressionFactoryBean.getObject(); } catch (Exception exception) { throw new RuntimeException(exception); } } public XPathExpressionScope getXPathExpressionScope() { return xPathExpressionScope; } public XPathExpression getXPathExpression() { return xPathExpression; } public XPathExpressionType getXPathExpressionType() { return xPathExpressionType; } public String getXPathKey() { return xPathKey; } public void setXPathExpressionType(XPathExpressionType xPathExpressionType) { this.xPathExpressionType = xPathExpressionType; } public void setXPathExpressionScope(XPathExpressionScope xPathExpressionScope) { this.xPathExpressionScope = xPathExpressionScope; } public void setXPathExpressionResultCardinality(XPathExpressionResultCardinality xPathExpressionResultCardinality) { this.xPathExpressionResultCardinality = xPathExpressionResultCardinality; } public XPathExpressionResultCardinality getXPathExpressionResultCardinality() { return xPathExpressionResultCardinality; } public String getUnparsedXpathExpression() { return unparsedXPathExpression; } @Override public boolean equals(Object that) { if (this == that) { return true; } if (that == null || getClass() != that.getClass()) { return false; } return new EqualsBuilder().append(this.getXPathKey(), ((WebServiceMessageXPathExpressionMetaData) that).getXPathKey()).isEquals(); } @Override public int hashCode() { return new HashCodeBuilder().append(getXPathKey()).toHashCode(); } }