use of org.apache.jackrabbit.spi.commons.conversion.NameException in project jackrabbit by apache.
the class LuceneQueryBuilder method getStringValues.
/**
* Returns an array of String values to be used as a term to lookup the search index
* for a String <code>literal</code> of a certain property name. This method
* will lookup the <code>propertyName</code> in the node type registry
* trying to find out the {@link javax.jcr.PropertyType}s.
* If no property type is found looking up node type information, this
* method will guess the property type.
*
* @param propertyName the name of the property in the relation.
* @param literal the String literal in the relation.
* @return the String values to use as term for the query.
*/
private String[] getStringValues(Name propertyName, String literal) {
PropertyTypeRegistry.TypeMapping[] types = propRegistry.getPropertyTypes(propertyName);
List<String> values = new ArrayList<String>();
for (PropertyTypeRegistry.TypeMapping type : types) {
switch(type.type) {
case PropertyType.NAME:
// try to translate name
try {
Name n = session.getQName(literal);
values.add(nsMappings.translateName(n));
log.debug("Coerced " + literal + " into NAME.");
} catch (NameException e) {
log.debug("Unable to coerce '" + literal + "' into a NAME: " + e.toString());
} catch (NamespaceException e) {
log.debug("Unable to coerce '" + literal + "' into a NAME: " + e.toString());
}
break;
case PropertyType.PATH:
// try to translate path
try {
Path p = session.getQPath(literal);
values.add(resolver.getJCRPath(p));
log.debug("Coerced " + literal + " into PATH.");
} catch (NameException e) {
log.debug("Unable to coerce '" + literal + "' into a PATH: " + e.toString());
} catch (NamespaceException e) {
log.debug("Unable to coerce '" + literal + "' into a PATH: " + e.toString());
}
break;
case PropertyType.DATE:
// try to parse date
Calendar c = ISO8601.parse(literal);
if (c != null) {
values.add(DateField.timeToString(c.getTimeInMillis()));
log.debug("Coerced " + literal + " into DATE.");
} else {
log.debug("Unable to coerce '" + literal + "' into a DATE.");
}
break;
case PropertyType.DOUBLE:
// try to parse double
try {
double d = Double.parseDouble(literal);
values.add(DoubleField.doubleToString(d));
log.debug("Coerced " + literal + " into DOUBLE.");
} catch (NumberFormatException e) {
log.debug("Unable to coerce '" + literal + "' into a DOUBLE: " + e.toString());
}
break;
case PropertyType.LONG:
// try to parse long
try {
long l = Long.parseLong(literal);
values.add(LongField.longToString(l));
log.debug("Coerced " + literal + " into LONG.");
} catch (NumberFormatException e) {
log.debug("Unable to coerce '" + literal + "' into a LONG: " + e.toString());
}
break;
case PropertyType.DECIMAL:
// try to parse decimal
try {
BigDecimal d = new BigDecimal(literal);
values.add(DecimalField.decimalToString(d));
log.debug("Coerced " + literal + " into DECIMAL.");
} catch (NumberFormatException e) {
log.debug("Unable to coerce '" + literal + "' into a DECIMAL: " + e.toString());
}
break;
case PropertyType.URI:
// fall through... TODO: correct?
case PropertyType.STRING:
values.add(literal);
log.debug("Using literal " + literal + " as is.");
break;
}
}
if (values.size() == 0) {
// use literal as is then try to guess other types
values.add(literal);
// try to guess property type
if (literal.indexOf('/') > -1) {
// might be a path
try {
values.add(resolver.getJCRPath(session.getQPath(literal)));
log.debug("Coerced " + literal + " into PATH.");
} catch (Exception e) {
// not a path
}
}
if (XMLChar.isValidName(literal)) {
// might be a name
try {
Name n = session.getQName(literal);
values.add(nsMappings.translateName(n));
log.debug("Coerced " + literal + " into NAME.");
} catch (Exception e) {
// not a name
}
}
if (literal.indexOf(':') > -1) {
// is it a date?
Calendar c = ISO8601.parse(literal);
if (c != null) {
values.add(DateField.timeToString(c.getTimeInMillis()));
log.debug("Coerced " + literal + " into DATE.");
}
} else {
// long or double are possible at this point
try {
values.add(LongField.longToString(Long.parseLong(literal)));
log.debug("Coerced " + literal + " into LONG.");
} catch (NumberFormatException e) {
// try double
try {
values.add(DoubleField.doubleToString(Double.parseDouble(literal)));
log.debug("Coerced " + literal + " into DOUBLE.");
} catch (NumberFormatException e1) {
// not a double
}
}
}
}
// if still no values use literal as is
if (values.size() == 0) {
values.add(literal);
log.debug("Using literal " + literal + " as is.");
}
return values.toArray(new String[values.size()]);
}
use of org.apache.jackrabbit.spi.commons.conversion.NameException in project jackrabbit by apache.
the class LuceneQueryBuilder method visit.
public Object visit(NodeTypeQueryNode node, Object data) {
List<Term> terms = new ArrayList<Term>();
try {
String mixinTypesField = resolver.getJCRName(NameConstants.JCR_MIXINTYPES);
String primaryTypeField = resolver.getJCRName(NameConstants.JCR_PRIMARYTYPE);
NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager();
NodeType base = ntMgr.getNodeType(session.getJCRName(node.getValue()));
if (base.isMixin()) {
// search for nodes where jcr:mixinTypes is set to this mixin
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(mixinTypesField, resolver.getJCRName(node.getValue())));
terms.add(t);
} else {
// search for nodes where jcr:primaryType is set to this type
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(primaryTypeField, resolver.getJCRName(node.getValue())));
terms.add(t);
}
// now search for all node types that are derived from base
NodeTypeIterator allTypes = ntMgr.getAllNodeTypes();
while (allTypes.hasNext()) {
NodeType nt = allTypes.nextNodeType();
NodeType[] superTypes = nt.getSupertypes();
if (Arrays.asList(superTypes).contains(base)) {
Name n = session.getQName(nt.getName());
String ntName = nsMappings.translateName(n);
Term t;
if (nt.isMixin()) {
// search on jcr:mixinTypes
t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(mixinTypesField, ntName));
} else {
// search on jcr:primaryType
t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(primaryTypeField, ntName));
}
terms.add(t);
}
}
} catch (NameException e) {
exceptions.add(e);
} catch (RepositoryException e) {
exceptions.add(e);
}
if (terms.size() == 0) {
// exception occured
return new BooleanQuery();
} else if (terms.size() == 1) {
return new JackrabbitTermQuery(terms.get(0));
} else {
BooleanQuery b = new BooleanQuery();
for (Term term : terms) {
b.add(new JackrabbitTermQuery(term), Occur.SHOULD);
}
return b;
}
}
use of org.apache.jackrabbit.spi.commons.conversion.NameException in project jackrabbit by apache.
the class LuceneQueryBuilder method visit.
public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
PathQueryNode relPath = node.getRelativePath();
if (relPath == null && node.getOperation() != QueryConstants.OPERATION_SIMILAR && node.getOperation() != QueryConstants.OPERATION_SPELLCHECK) {
exceptions.add(new InvalidQueryException("@* not supported in predicate"));
return data;
}
LocationStepQueryNode[] steps = relPath.getPathSteps();
Name propertyName;
if (node.getOperation() == QueryConstants.OPERATION_SIMILAR) {
// this is a bit ugly:
// use the name of a dummy property because relPath actually
// references a property. whereas the relPath of the similar
// operation references a node
propertyName = NameConstants.JCR_PRIMARYTYPE;
} else {
propertyName = steps[steps.length - 1].getNameTest();
}
Query query;
String[] stringValues = new String[1];
switch(node.getValueType()) {
case 0:
// not set: either IS NULL or IS NOT NULL
break;
case QueryConstants.TYPE_DATE:
stringValues[0] = DateField.dateToString(node.getDateValue());
break;
case QueryConstants.TYPE_DOUBLE:
stringValues[0] = DoubleField.doubleToString(node.getDoubleValue());
break;
case QueryConstants.TYPE_LONG:
stringValues[0] = LongField.longToString(node.getLongValue());
break;
case QueryConstants.TYPE_STRING:
if (node.getOperation() == QueryConstants.OPERATION_EQ_GENERAL || node.getOperation() == QueryConstants.OPERATION_EQ_VALUE || node.getOperation() == QueryConstants.OPERATION_NE_GENERAL || node.getOperation() == QueryConstants.OPERATION_NE_VALUE) {
// only use coercing on non-range operations
stringValues = getStringValues(propertyName, node.getStringValue());
} else {
stringValues[0] = node.getStringValue();
}
break;
case QueryConstants.TYPE_POSITION:
// ignore position. is handled in the location step
return null;
default:
throw new IllegalArgumentException("Unknown relation type: " + node.getValueType());
}
// get property transformation
final int[] transform = new int[] { TransformConstants.TRANSFORM_NONE };
node.acceptOperands(new DefaultQueryNodeVisitor() {
public Object visit(PropertyFunctionQueryNode node, Object data) {
if (node.getFunctionName().equals(PropertyFunctionQueryNode.LOWER_CASE)) {
transform[0] = TransformConstants.TRANSFORM_LOWER_CASE;
} else if (node.getFunctionName().equals(PropertyFunctionQueryNode.UPPER_CASE)) {
transform[0] = TransformConstants.TRANSFORM_UPPER_CASE;
}
return data;
}
}, null);
String field = "";
try {
field = resolver.getJCRName(propertyName);
} catch (NamespaceException e) {
// should never happen
exceptions.add(e);
}
// support for fn:name()
if (propertyName.equals(FN_NAME)) {
if (node.getValueType() != QueryConstants.TYPE_STRING) {
exceptions.add(new InvalidQueryException("Name function can " + "only be used in conjunction with a string literal"));
return data;
}
if (node.getOperation() == QueryConstants.OPERATION_EQ_VALUE || node.getOperation() == QueryConstants.OPERATION_EQ_GENERAL) {
// check if string literal is a valid XML Name
if (XMLChar.isValidName(node.getStringValue())) {
// parse string literal as JCR Name
try {
Name n = session.getQName(ISO9075.decode(node.getStringValue()));
query = new NameQuery(n, indexFormatVersion, nsMappings);
} catch (NameException e) {
exceptions.add(e);
return data;
} catch (NamespaceException e) {
exceptions.add(e);
return data;
}
} else {
// will never match -> create dummy query
query = new BooleanQuery();
}
} else if (node.getOperation() == QueryConstants.OPERATION_LIKE) {
// no coercing, see above
if (stringValues[0].equals("%")) {
query = new org.apache.lucene.search.MatchAllDocsQuery();
} else {
query = new WildcardNameQuery(stringValues[0], transform[0], session, nsMappings, cache);
}
} else {
exceptions.add(new InvalidQueryException("Name function can " + "only be used in conjunction with the following operators: equals, like"));
return data;
}
} else {
switch(node.getOperation()) {
// =
case QueryConstants.OPERATION_EQ_VALUE:
case QueryConstants.OPERATION_EQ_GENERAL:
BooleanQuery or = new BooleanQuery();
for (String value : stringValues) {
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Query q;
if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
q = new CaseTermQuery.Upper(t);
} else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
q = new CaseTermQuery.Lower(t);
} else {
q = new JackrabbitTermQuery(t);
}
or.add(q, Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_EQ_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
// >=
case QueryConstants.OPERATION_GE_VALUE:
case QueryConstants.OPERATION_GE_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
or.add(new RangeQuery(lower, upper, true, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_GE_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
// >
case QueryConstants.OPERATION_GT_VALUE:
case QueryConstants.OPERATION_GT_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
or.add(new RangeQuery(lower, upper, false, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_GT_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
// <=
case QueryConstants.OPERATION_LE_VALUE:
case // <=
QueryConstants.OPERATION_LE_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
or.add(new RangeQuery(lower, upper, true, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_LE_VALUE) {
query = createSingleValueConstraint(query, field);
}
break;
case // LIKE
QueryConstants.OPERATION_LIKE:
// no coercing, see above
if (stringValues[0].equals("%")) {
query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
} else {
query = new WildcardQuery(FieldNames.PROPERTIES, field, stringValues[0], transform[0], cache);
}
break;
// <
case QueryConstants.OPERATION_LT_VALUE:
case QueryConstants.OPERATION_LT_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
or.add(new RangeQuery(lower, upper, false, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_LT_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
case // !=
QueryConstants.OPERATION_NE_VALUE:
// match nodes with property 'field' that includes svp and mvp
BooleanQuery notQuery = new BooleanQuery();
notQuery.add(Util.createMatchAllQuery(field, indexFormatVersion, cache), Occur.SHOULD);
// exclude all nodes where 'field' has the term in question
for (String value : stringValues) {
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Query q;
if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
q = new CaseTermQuery.Upper(t);
} else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
q = new CaseTermQuery.Lower(t);
} else {
q = new JackrabbitTermQuery(t);
}
notQuery.add(q, Occur.MUST_NOT);
}
// and exclude all nodes where 'field' is multi valued
notQuery.add(new JackrabbitTermQuery(new Term(FieldNames.MVP, field)), Occur.MUST_NOT);
query = notQuery;
break;
case // !=
QueryConstants.OPERATION_NE_GENERAL:
// that's:
// all nodes with property 'field'
// minus the nodes that have a single property 'field' that is
// not equal to term in question
// minus the nodes that have a multi-valued property 'field' and
// all values are equal to term in question
notQuery = new BooleanQuery();
notQuery.add(Util.createMatchAllQuery(field, indexFormatVersion, cache), Occur.SHOULD);
for (String value : stringValues) {
// exclude the nodes that have the term and are single valued
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Query svp = new NotQuery(new JackrabbitTermQuery(new Term(FieldNames.MVP, field)));
BooleanQuery and = new BooleanQuery();
Query q;
if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
q = new CaseTermQuery.Upper(t);
} else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
q = new CaseTermQuery.Lower(t);
} else {
q = new JackrabbitTermQuery(t);
}
and.add(q, Occur.MUST);
and.add(svp, Occur.MUST);
notQuery.add(and, Occur.MUST_NOT);
}
// todo above also excludes multi-valued properties that contain
// multiple instances of only stringValues. e.g. text={foo, foo}
query = notQuery;
break;
case QueryConstants.OPERATION_NULL:
query = new NotQuery(Util.createMatchAllQuery(field, indexFormatVersion, cache));
break;
case QueryConstants.OPERATION_SIMILAR:
try {
NodeId id = hmgr.resolveNodePath(session.getQPath(node.getStringValue()));
if (id != null) {
query = new SimilarityQuery(id.toString(), analyzer);
} else {
query = new BooleanQuery();
}
} catch (Exception e) {
exceptions.add(e);
query = new BooleanQuery();
}
break;
case QueryConstants.OPERATION_NOT_NULL:
query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
break;
case QueryConstants.OPERATION_SPELLCHECK:
query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
break;
default:
throw new IllegalArgumentException("Unknown relation operation: " + node.getOperation());
}
}
if (steps.length > 1) {
// child axis in relation
// elements.length - 1 = property name
// elements.length - 2 = last child axis name test
boolean selectParent = true;
for (int i = steps.length - 2; i >= 0; i--) {
LocationStepQueryNode step = steps[i];
Name name = steps[i].getNameTest();
if (i == steps.length - 2) {
if (step instanceof DerefQueryNode) {
query = createPredicateDeref(query, (DerefQueryNode) step, data);
if (steps.length == 2) {
selectParent = false;
}
} else if (step != null) {
// join name test with property query if there is one
if (name != null) {
if (!name.equals(PARENT_ELEMENT_NAME)) {
Query nameTest = new NameQuery(name, indexFormatVersion, nsMappings);
BooleanQuery and = new BooleanQuery();
and.add(query, Occur.MUST);
and.add(nameTest, Occur.MUST);
query = and;
} else {
// If we're searching the parent, we want to return the child axis,
// not the parent because this is part of the predicate. For instance,
// if the query is //child[../base], this part of the code is operating
// on the "../base" portion. So we want to return all the child nodes
// of "base", which will then be matched against the non predicate part.
query = new ChildAxisQuery(sharedItemMgr, query, null, indexFormatVersion, nsMappings);
selectParent = false;
}
} else {
// otherwise the query can be used as is
}
}
} else if (name != null && name.equals(PARENT_ELEMENT_NAME)) {
// We need to select one of the properties if we haven't already.
if (selectParent) {
query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
selectParent = false;
}
// See the note above on searching parents
query = new ChildAxisQuery(sharedItemMgr, query, null, indexFormatVersion, nsMappings);
} else {
if (step != null) {
query = new ParentAxisQuery(query, name, indexFormatVersion, nsMappings);
} else {
throw new UnsupportedOperationException();
}
}
}
// finally select the parent of the selected nodes
if (selectParent) {
query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
}
}
return query;
}
use of org.apache.jackrabbit.spi.commons.conversion.NameException in project jackrabbit by apache.
the class SysViewImportHandler method endElement.
/**
* {@inheritDoc}
*/
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
Name name = NameFactoryImpl.getInstance().create(namespaceURI, localName);
// check element name
ImportState state = stack.peek();
if (name.equals(NameConstants.SV_NODE)) {
// sv:node element
if (!state.started) {
// need to start & end current node
processNode(state, true, true);
state.started = true;
} else {
// need to end current node
processNode(state, false, true);
}
// pop current state from stack
stack.pop();
} else if (name.equals(NameConstants.SV_PROPERTY)) {
// have been collected and create node as necessary
if (currentPropName.equals(NameConstants.JCR_PRIMARYTYPE)) {
BufferedStringValue val = currentPropValues.get(0);
String s = null;
try {
s = val.retrieve();
state.nodeTypeName = resolver.getQName(s);
} catch (IOException ioe) {
throw new SAXException("error while retrieving value", ioe);
} catch (NameException e) {
throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + s, e));
} catch (NamespaceException e) {
throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + s, e));
}
} else if (currentPropName.equals(NameConstants.JCR_MIXINTYPES)) {
if (state.mixinNames == null) {
state.mixinNames = new ArrayList<Name>(currentPropValues.size());
}
for (BufferedStringValue val : currentPropValues) {
String s = null;
try {
s = val.retrieve();
Name mixin = resolver.getQName(s);
state.mixinNames.add(mixin);
} catch (IOException ioe) {
throw new SAXException("error while retrieving value", ioe);
} catch (NameException e) {
throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + s, e));
} catch (NamespaceException e) {
throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + s, e));
}
}
} else if (currentPropName.equals(NameConstants.JCR_UUID)) {
BufferedStringValue val = currentPropValues.get(0);
try {
state.uuid = val.retrieve();
} catch (IOException ioe) {
throw new SAXException("error while retrieving value", ioe);
}
} else {
if (currentPropMultipleStatus == MultipleStatus.UNKNOWN && currentPropValues.size() != 1) {
currentPropMultipleStatus = MultipleStatus.MULTIPLE;
}
PropInfo prop = new PropInfo(currentPropName, currentPropType, currentPropValues.toArray(new TextValue[currentPropValues.size()]), currentPropMultipleStatus);
state.props.add(prop);
}
// reset temp fields
currentPropValues.clear();
} else if (name.equals(NameConstants.SV_VALUE)) {
// sv:value element
currentPropValues.add(currentPropValue);
// reset temp fields
currentPropValue = null;
} else {
throw new SAXException(new InvalidSerializedDataException("invalid element in system view xml document: " + localName));
}
}
use of org.apache.jackrabbit.spi.commons.conversion.NameException in project jackrabbit by apache.
the class DocViewImportHandler method parseNames.
/**
* Parses the given string as a list of JCR names. Any whitespace sequence
* is supported as a names separator instead of just a single space to
* be more liberal in what we accept. The current namespace context is
* used to convert the prefixed name strings to QNames.
*
* @param value string value
* @return the parsed names
* @throws SAXException if an invalid name was encountered
*/
private Name[] parseNames(String value) throws SAXException {
String[] names = value.split("\\p{Space}+");
Name[] qnames = new Name[names.length];
for (int i = 0; i < names.length; i++) {
try {
qnames[i] = resolver.getQName(names[i]);
} catch (NameException ne) {
throw new SAXException("Invalid name: " + names[i], ne);
} catch (NamespaceException e) {
throw new SAXException("Invalid name: " + names[i], e);
}
}
return qnames;
}
Aggregations