/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.common.propertyaccessor;
import java.util.Collection;
import java.util.stream.Collectors;
import org.geotools.factory.Hints;
import org.geotools.filter.expression.PropertyAccessor;
import org.geotools.filter.expression.PropertyAccessorFactory;
import eu.esdihumboldt.hale.common.instance.helper.PropertyResolver;
import eu.esdihumboldt.hale.common.instance.model.Instance;
import eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty;
/**
* Factory for property accessor using {@link PropertyResolver}.
*
* @author Sebastian Reinhardt
*/
public class InstancePropertyAccessorFactory implements PropertyAccessorFactory {
/**
* @see PropertyAccessorFactory#createPropertyAccessor(Class, String, Class,
* Hints)
*/
@Override
public PropertyAccessor createPropertyAccessor(@SuppressWarnings("rawtypes") Class type,
String xpath, @SuppressWarnings("rawtypes") Class target, Hints hints) {
if (xpath == null)
return null;
if (!Instance.class.isAssignableFrom(type)) {
return null; // we only work with instances
}
return new InstancePropertyAccessor();
}
static class InstancePropertyAccessor implements PropertyAccessor {
@Override
public boolean canHandle(Object object, String xpath,
@SuppressWarnings("rawtypes") Class target) {
if (object instanceof Instance) {
return true;
}
else {
return false;
}
}
protected Object unwrap(Object obj) {
if (obj instanceof GeometryProperty) {
/*
* Extract geometry from GeometryProperty, as a Geometry is
* usually expected in Geotools filters related to geometries.
*
* XXX A better alternative might be adding a Geotools converter
* factory that supports this conversions (also see Geotools
* Converters class).
*/
return ((GeometryProperty<?>) obj).getGeometry();
}
return obj;
}
@SuppressWarnings("unchecked")
@Override
public Object get(Object object, String xpath, @SuppressWarnings("rawtypes") Class target) {
if (object instanceof Instance) {
Collection<Object> values = PropertyResolver.getValues((Instance) object, xpath);
if (values.size() == 1) {
/*
* Always yield single value if there is only a single
* value. This is required for instance for the IS NULL
* filter. It does not work on lists.
*/
return unwrap(values.iterator().next());
}
else if (values.isEmpty()) {
/*
* No values -> return null. This is required for instance
* for the IS NULL filter. It treats a list always as not
* null.
*/
return null;
}
else {
// unwrap values
values = values.stream().map(this::unwrap).collect(Collectors.toList());
}
return values;
}
return null;
}
@Override
public void set(Object object, String xpath, Object value,
@SuppressWarnings("rawtypes") Class target) {
throw new UnsupportedOperationException();
}
}
}