/*
* 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.align.extension.function;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import com.vividsolutions.jts.geom.Geometry;
import de.fhg.igd.eclipse.util.extension.ExtensionUtil;
import de.fhg.igd.slf4jplus.ALogger;
import de.fhg.igd.slf4jplus.ALoggerFactory;
import eu.esdihumboldt.hale.common.align.model.Type;
import eu.esdihumboldt.hale.common.align.model.condition.PropertyCondition;
import eu.esdihumboldt.hale.common.align.model.condition.PropertyOrChildrenTypeCondition;
import eu.esdihumboldt.hale.common.align.model.condition.PropertyTypeCondition;
import eu.esdihumboldt.hale.common.align.model.condition.TypeCondition;
import eu.esdihumboldt.hale.common.align.model.condition.impl.BindingCondition;
import eu.esdihumboldt.hale.common.align.model.condition.impl.GeometryCondition;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;
import eu.esdihumboldt.hale.common.schema.model.constraint.type.AugmentedValueFlag;
import eu.esdihumboldt.hale.common.schema.model.constraint.type.HasValueFlag;
/**
* Represents a source or target property as parameter to a
* {@link PropertyFunction}
*
* @author Simon Templer
*/
public final class PropertyParameter extends AbstractParameter implements PropertyParameterDefinition {
private static final ALogger log = ALoggerFactory.getLogger(PropertyParameter.class);
private static final PropertyCondition VALUE_CONDITION = new PropertyTypeCondition(
new TypeCondition() {
@Override
public boolean accept(Type entity) {
TypeDefinition type = entity.getDefinition().getDefinition();
return type.getConstraint(HasValueFlag.class).isEnabled()
|| type.getConstraint(AugmentedValueFlag.class).isEnabled();
}
});
private static final PropertyCondition VALUE_CONDITION_STRICT = new PropertyTypeCondition(
new TypeCondition() {
@Override
public boolean accept(Type entity) {
TypeDefinition type = entity.getDefinition().getDefinition();
return type.getConstraint(HasValueFlag.class).isEnabled();
}
});
private final List<PropertyCondition> conditions;
private final boolean eager;
/**
* @see AbstractParameter#AbstractParameter(IConfigurationElement)
*/
public PropertyParameter(IConfigurationElement conf) {
super(conf);
String eagerFlag = conf.getAttribute("eager");
// defaults to false
eager = Boolean.parseBoolean(eagerFlag);
conditions = createConditions(conf);
}
/**
* Create a parameter definition.
*
* @param name the parameter name
* @param minOccurrence min occurrences
* @param maxOccurrence max occurrences
* @param label human readable label
* @param description human readable description
* @param conditions a list of property conditions
* @param eager {@link #isEager()}
*/
public PropertyParameter(String name, int minOccurrence, int maxOccurrence, String label,
String description, List<PropertyCondition> conditions, boolean eager) {
super(name, minOccurrence, maxOccurrence, label, description);
this.conditions = conditions;
this.eager = eager;
}
private static List<PropertyCondition> createConditions(IConfigurationElement conf) {
List<PropertyCondition> result = new ArrayList<PropertyCondition>();
IConfigurationElement[] children = conf.getChildren();
if (children != null) {
for (IConfigurationElement child : children) {
String name = child.getName();
if (name.equals("propertyCondition")) {
try {
PropertyCondition condition = (PropertyCondition) child
.createExecutableExtension("class");
result.add(condition);
} catch (CoreException e) {
log.error("Error creating property condition from extension", e);
}
}
else if (name.equals("bindingCondition")) {
BindingCondition bc = createBindingCondition(child);
if (bc != null) {
result.add(new PropertyTypeCondition(bc));
}
}
else if (name.equals("geometryCondition")) {
GeometryCondition gc = createGeometryCondition(child);
if (gc != null) {
result.add(new PropertyTypeCondition(gc));
}
}
else if (name.equals("geometryOrParentCondition")) {
GeometryCondition gc = createGeometryCondition(child);
if (gc != null) {
result.add(new PropertyOrChildrenTypeCondition(gc));
}
}
else if (name.equals("valueCondition")) {
String attr = child.getAttribute("allowAugmented");
boolean allowAugmented;
if (attr == null || attr.isEmpty()) {
allowAugmented = true; // default value
}
else {
allowAugmented = Boolean.parseBoolean(attr);
}
if (allowAugmented) {
result.add(VALUE_CONDITION);
}
else {
result.add(VALUE_CONDITION_STRICT);
}
}
else {
// ignore
log.warn("Unrecognized property condition");
}
}
}
return result;
}
private static GeometryCondition createGeometryCondition(IConfigurationElement child) {
Collection<Class<? extends Geometry>> bindings = null;
IConfigurationElement[] types = child.getChildren("geometryType");
if (types != null) {
for (IConfigurationElement type : types) {
try {
@SuppressWarnings("unchecked")
Class<? extends Geometry> geometryType = (Class<? extends Geometry>) ExtensionUtil
.loadClass(type, "type");
if (bindings == null) {
bindings = new HashSet<Class<? extends Geometry>>();
}
bindings.add(geometryType);
} catch (Throwable e) {
log.error("Could not load geometry class defined in extension", e);
}
}
}
boolean allowCollection = true; // TODO configurable?
boolean allowConversion = true; // TODO configurable?
return new GeometryCondition(bindings, allowConversion, allowCollection);
}
private static BindingCondition createBindingCondition(IConfigurationElement child) {
Class<?> bindingClass = ExtensionUtil.loadClass(child, "compatibleClass");
if (bindingClass != null) {
boolean allowConversion = Boolean.parseBoolean(child.getAttribute("allowConversion"));
// defaults to false
boolean allowCollection = Boolean.parseBoolean(child.getAttribute("allowCollection"));
// defaults to false
return new BindingCondition(bindingClass, allowConversion, allowCollection);
}
else {
log.error("Could not load class for binding condition: "
+ child.getAttribute("compatibleClass"));
}
return null;
}
/**
* @see eu.esdihumboldt.hale.common.align.extension.function.PropertyParameterDefinition#getConditions()
*/
@Override
public List<PropertyCondition> getConditions() {
return Collections.unmodifiableList(conditions);
}
/**
* @see eu.esdihumboldt.hale.common.align.extension.function.PropertyParameterDefinition#isEager()
*/
@Override
public boolean isEager() {
return eager;
}
}