
org.javarosa.xpath.expr.XPathStep Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opendatakit-javarosa Show documentation
Show all versions of opendatakit-javarosa Show documentation
A Java library for rendering forms that are compliant with ODK XForms spec
The newest version!
/*
* Copyright (C) 2009 JavaRosa
*
* 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.javarosa.xpath.expr;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.javarosa.core.util.CacheTable;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapListPoly;
import org.javarosa.core.util.externalizable.ExtWrapNullable;
import org.javarosa.core.util.externalizable.Externalizable;
import org.javarosa.core.util.externalizable.PrototypeFactory;
public class XPathStep implements Externalizable {
public static final int AXIS_CHILD = 0;
public static final int AXIS_DESCENDANT = 1;
public static final int AXIS_PARENT = 2;
public static final int AXIS_ANCESTOR = 3;
public static final int AXIS_FOLLOWING_SIBLING = 4;
public static final int AXIS_PRECEDING_SIBLING = 5;
public static final int AXIS_FOLLOWING = 6;
public static final int AXIS_PRECEDING = 7;
public static final int AXIS_ATTRIBUTE = 8;
public static final int AXIS_NAMESPACE = 9;
public static final int AXIS_SELF = 10;
public static final int AXIS_DESCENDANT_OR_SELF = 11;
public static final int AXIS_ANCESTOR_OR_SELF = 12;
public static final int TEST_NAME = 0;
public static final int TEST_NAME_WILDCARD = 1;
public static final int TEST_NAMESPACE_WILDCARD = 2;
public static final int TEST_TYPE_NODE = 3;
public static final int TEST_TYPE_TEXT = 4;
public static final int TEST_TYPE_COMMENT = 5;
public static final int TEST_TYPE_PROCESSING_INSTRUCTION = 6;
private static CacheTable refs;
public static void attachCacheTable(CacheTable refs) {
XPathStep.refs = refs;
}
public static XPathStep ABBR_SELF () {
return new XPathStep(AXIS_SELF, TEST_TYPE_NODE);
}
public static XPathStep ABBR_PARENT () {
return new XPathStep(AXIS_PARENT, TEST_TYPE_NODE);
}
public static XPathStep ABBR_DESCENDANTS () {
return new XPathStep(AXIS_DESCENDANT_OR_SELF, TEST_TYPE_NODE);
}
public int axis;
public int test;
public XPathExpression[] predicates;
//test-dependent variables
public XPathQName name; //TEST_NAME only
public String namespace; //TEST_NAMESPACE_WILDCARD only
public String literal; //TEST_TYPE_PROCESSING_INSTRUCTION only
public XPathStep () { } //for deserialization
public XPathStep (int axis, int test) {
this.axis = axis;
this.test = test;
this.predicates = new XPathExpression[0];
}
public XPathStep (int axis, XPathQName name) {
this(axis, TEST_NAME);
this.name = name;
}
public XPathStep (int axis, String namespace) {
this(axis, TEST_NAMESPACE_WILDCARD);
this.namespace = namespace;
}
public String toString () {
StringBuilder sb = new StringBuilder();
sb.append("{step:");
sb.append(axisStr(axis));
sb.append(",");
sb.append(testStr());
if (predicates.length > 0) {
sb.append(",{");
for (int i = 0; i < predicates.length; i++) {
sb.append(predicates[i].toString());
if (i < predicates.length - 1)
sb.append(",");
}
sb.append("}");
}
sb.append("}");
return sb.toString();
}
public static String axisStr (int axis) {
switch (axis) {
case AXIS_CHILD: return "child";
case AXIS_DESCENDANT: return "descendant";
case AXIS_PARENT: return "parent";
case AXIS_ANCESTOR: return "ancestor";
case AXIS_FOLLOWING_SIBLING: return "following-sibling";
case AXIS_PRECEDING_SIBLING: return "preceding-sibling";
case AXIS_FOLLOWING: return "following";
case AXIS_PRECEDING: return "preceding";
case AXIS_ATTRIBUTE: return "attribute";
case AXIS_NAMESPACE: return "namespace";
case AXIS_SELF: return "self";
case AXIS_DESCENDANT_OR_SELF: return "descendant-or-self";
case AXIS_ANCESTOR_OR_SELF: return "ancestor-or-self";
default: return null;
}
}
public String testStr () {
switch(test) {
case TEST_NAME: return name.toString();
case TEST_NAME_WILDCARD: return "*";
case TEST_NAMESPACE_WILDCARD: return namespace + ":*";
case TEST_TYPE_NODE: return "node()";
case TEST_TYPE_TEXT: return "text()";
case TEST_TYPE_COMMENT: return "comment()";
case TEST_TYPE_PROCESSING_INSTRUCTION: return "proc-instr(" + (literal == null ? "" : "\'" + literal + "\'") + ")";
default: return null;
}
}
public boolean equals (Object o) {
if (o instanceof XPathStep) {
XPathStep x = (XPathStep)o;
//shortcuts for faster evaluation
if(axis != x.axis || test != x.test || predicates.length != x.predicates.length) {
return false;
}
switch (test) {
case TEST_NAME: if(!name.equals(x.name)) {return false;} break;
case TEST_NAMESPACE_WILDCARD: if(!namespace.equals(x.namespace)) {return false;} break;
case TEST_TYPE_PROCESSING_INSTRUCTION: if(!ExtUtil.equals(literal, x.literal)) {return false;} break;
default: break;
}
return ExtUtil.arrayEquals(predicates, x.predicates);
} else {
return false;
}
}
/**
* "matches" follows roughly the same process as equals(), in that it for a step it will
* check whether two steps share the same properties (multiplicity, test, axis, etc).
* The only difference is that match() will allow for a named step to match a step who's name
* is a wildcard.
*
* So
* \/path\/
* will "match"
* \/*\/
*
* even though they are not equal.
*
* Matching is reflexive, consistent, and symmetric, but _not_ transitive.
* @param xPathStep
* @return
*/
protected boolean matches(XPathStep o) {
if (o instanceof XPathStep) {
XPathStep x = (XPathStep)o;
//shortcuts for faster evaluation
if(axis != x.axis || (test != x.test && !((x.test == TEST_NAME && this.test == TEST_NAME_WILDCARD)||(this.test==TEST_NAME && x.test == TEST_NAME_WILDCARD))) || predicates.length != x.predicates.length) {
return false;
}
switch (test) {
case TEST_NAME: if(x.test != TEST_NAME_WILDCARD && !name.equals(x.name)) {return false;} break;
case TEST_NAMESPACE_WILDCARD: if(!namespace.equals(x.namespace)) {return false;} break;
case TEST_TYPE_PROCESSING_INSTRUCTION: if(!ExtUtil.equals(literal, x.literal)) {return false;} break;
default: break;
}
return ExtUtil.arrayEquals(predicates, x.predicates);
} else {
return false;
}
}
public int hashCode() {
int code = this.axis ^ this.test ^ (this.name == null ? 0 : this.name.hashCode()) ^ (this.literal == null ? 0 : this.literal.hashCode()) ^ (this.namespace == null ? 0 : this.namespace.hashCode());
for(XPathExpression xpe : predicates) {
code ^= xpe.hashCode();
}
return code;
}
public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
axis = ExtUtil.readInt(in);
test = ExtUtil.readInt(in);
switch (test) {
case TEST_NAME: name = (XPathQName)ExtUtil.read(in, XPathQName.class); break;
case TEST_NAMESPACE_WILDCARD: namespace = ExtUtil.readString(in); break;
case TEST_TYPE_PROCESSING_INSTRUCTION: literal = (String)ExtUtil.read(in, new ExtWrapNullable(String.class)); break;
}
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy