/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2009-2011, Open Source Geospatial Foundation (OSGeo) * * This library 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; * version 2.1 of the License. * * This library 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. */ package org.geotools.filter.expression; import java.util.List; import org.geotools.data.complex.xml.XmlXpathFilterData; import org.geotools.factory.Hints; import org.geotools.feature.IllegalAttributeException; import org.geotools.util.XmlXpathUtilites; import org.opengis.feature.Feature; import org.xml.sax.helpers.NamespaceSupport; /** * PropertyAccessorFactory used to create property accessors which can handle xpath expressions * against instances of {@link Feature}. * * @author Russell Petty (GeoScience Victoria) * @author Rini Angreani (CSIRO Earth Science and Resource Engineering) * @source $URL$ */ public class XmlXPathPropertyAccessorFactory implements PropertyAccessorFactory { /** * Namespace support hint */ public static Hints.Key NAMESPACE_SUPPORT = new Hints.Key(NamespaceSupport.class); public PropertyAccessor createPropertyAccessor(Class type, String xpath, Class target, Hints hints) { if (XmlXpathFilterData.class.isAssignableFrom(type)) { return new XmlXPathPropertyAcessor(); } return null; } static class XmlXPathPropertyAcessor implements PropertyAccessor { public boolean canHandle(Object object, String xpath, Class target) { // TODO: some better check for a valid xpath expression return (xpath != null) && !"".equals(xpath.trim()); } public Object get(Object object, String xpath, Class target) { XmlXpathFilterData xmlResponse = (XmlXpathFilterData) object; String indexXpath = createIndexedXpath(xmlResponse, xpath); List<String> ls = XmlXpathUtilites.getXPathValues(xmlResponse.getNamespaces(), indexXpath, xmlResponse.getDoc()); if (ls != null && !ls.isEmpty()) { return ls.get(0); } return null; } public void set(Object object, String xpath, Object value, Class target) throws IllegalAttributeException { throw new UnsupportedOperationException("Do not support updating."); // context(object).setValue(xpath, value); } private String createIndexedXpath(XmlXpathFilterData xmlResponse, String xpathString) { String itemXpath = xmlResponse.getItemXpath(); // if xpathString is from mapping file, as a function expression or inputattribute // it wouldn't be indexed // however the itemXpath would be indexed as it comes from the node // so need to remove the indexes when doing a search String unindexedXpath = XmlXpathUtilites.removeIndexes(itemXpath); int position = xpathString.indexOf(unindexedXpath); if (position != 0) { throw new RuntimeException("xpath passed in does not begin with itemXpath" + "/n xpathString =" + xpathString + "/n itemXpath =" + itemXpath); } StringBuffer sb = new StringBuffer(itemXpath); int count = xmlResponse.getCount(); if (count > -1) { sb.append("[" + xmlResponse.getCount() + "]"); } sb.append(xpathString.substring(unindexedXpath.length())); return sb.toString(); } } }