/*
* eXist Open Source Native XML Database
* Copyright (C) 2013 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.indexing.range;
import org.exist.storage.NodePath;
import org.exist.util.DatabaseConfigurationException;
import org.exist.util.XMLString;
import org.exist.xquery.XPathException;
import org.exist.xquery.value.Type;
import org.w3c.dom.Element;
import java.util.Map;
/**
* Handles configuration of a field within an index definition:
*
* <pre>
* <create match="//parent">
* <field name="field-name" match="@xml:id" type="xs:string"/>
* </pre>
*/
public class RangeIndexConfigField {
private String name;
private NodePath path = null;
private NodePath relPath = null;
private int type = Type.STRING;
private org.exist.indexing.range.conversion.TypeConverter typeConverter = null;
protected boolean includeNested = false;
protected int wsTreatment = XMLString.SUPPRESS_NONE;
protected boolean caseSensitive = true;
public RangeIndexConfigField(NodePath parentPath, Element elem, Map<String, String> namespaces) throws DatabaseConfigurationException {
name = elem.getAttribute("name");
path = parentPath;
if (name == null || name.length() == 0) {
throw new DatabaseConfigurationException("Range index module: field element requires a name attribute");
}
String match = elem.getAttribute("match");
if (match != null && match.length() > 0) {
try {
relPath = new NodePath(namespaces, match);
if (relPath.length() == 0)
throw new DatabaseConfigurationException("Range index module: Invalid match path in collection config: " + match);
path = new NodePath(parentPath);
path.append(relPath);
} catch (IllegalArgumentException e) {
throw new DatabaseConfigurationException("Range index module: invalid qname in configuration: " + e.getMessage());
}
} else {
path = parentPath;
}
String typeStr = elem.getAttribute("type");
if (typeStr != null && typeStr.length() > 0) {
try {
this.type = Type.getType(typeStr);
} catch (XPathException e) {
throw new DatabaseConfigurationException("Invalid type declared for range index on " + match + ": " + typeStr);
}
}
String custom = elem.getAttribute("converter");
if (custom != null && custom.length() > 0) {
try {
Class customClass = Class.forName(custom);
typeConverter = (org.exist.indexing.range.conversion.TypeConverter) customClass.newInstance();
} catch (ClassNotFoundException e) {
RangeIndex.LOG.warn("Class for custom-type not found: " + custom);
} catch (InstantiationException e) {
RangeIndex.LOG.warn("Failed to initialize custom-type: " + custom, e);
} catch (IllegalAccessException e) {
RangeIndex.LOG.warn("Failed to initialize custom-type: " + custom, e);
}
}
String nested = elem.getAttribute("nested");
includeNested = (nested == null || nested.equalsIgnoreCase("yes"));
path.setIncludeDescendants(includeNested);
// normalize whitespace if whitespace="normalize"
String whitespace = elem.getAttribute("whitespace");
if (whitespace != null) {
if ("trim".equalsIgnoreCase(whitespace)) {
wsTreatment = XMLString.SUPPRESS_BOTH;
} else if ("normalize".equalsIgnoreCase(whitespace)) {
wsTreatment = XMLString.NORMALIZE;
}
}
String caseStr = elem.getAttribute("case");
if (caseStr != null && caseStr.length() > 0) {
caseSensitive = caseStr.equalsIgnoreCase("yes");
}
}
public String getName() {
return name;
}
public NodePath getPath() {
return path;
}
public int getType() {
return type;
}
public org.exist.indexing.range.conversion.TypeConverter getTypeConverter() {
return typeConverter;
}
public boolean match(NodePath other) {
return path.match(other);
}
public boolean match(NodePath parentPath, NodePath other) {
if (relPath == null) {
return parentPath.match(other);
} else {
NodePath absPath = new NodePath(parentPath);
absPath.append(relPath);
return absPath.match(other);
}
}
public int whitespaceTreatment() {
return wsTreatment;
}
public boolean isCaseSensitive() {
return caseSensitive;
}
public boolean includeNested() {
return includeNested;
}
}