/*
* Copyright (c) 2016 wetransform GmbH
*
* 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:
* wetransform GmbH <http://www.wetransform.to>
*/
package eu.esdihumboldt.hale.common.align.model.functions.merge;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.xml.namespace.QName;
import com.google.common.collect.ListMultimap;
import eu.esdihumboldt.hale.common.align.model.AlignmentUtil;
import eu.esdihumboldt.hale.common.align.model.ChildContext;
import eu.esdihumboldt.hale.common.align.model.EntityDefinition;
import eu.esdihumboldt.hale.common.align.model.ParameterValue;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.schema.SchemaSpaceID;
import eu.esdihumboldt.hale.common.schema.model.ChildDefinition;
import eu.esdihumboldt.hale.common.schema.model.Definition;
import eu.esdihumboldt.hale.common.schema.model.DefinitionUtil;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;
/**
* Common utilities for getting and setting merge function parameters.
*
* This is meant to be a single place where functionality is defined that is
* used for the transformation (PropertiesMergeHandler), configuration in the UI
* (MergeParameterPage) and cell migration.
*
* @author Simon Templer
*/
public class MergeUtil {
/**
* Get the properties defined in a Merge function property parameter.
*
* @param parameters the parameters multimap
* @param parameterName the parameter name
* @return the list of properties identified by their property paths
*/
public static List<List<QName>> getProperties(ListMultimap<String, ParameterValue> parameters,
String parameterName) {
List<List<QName>> result = new ArrayList<List<QName>>();
if (parameters.containsKey(parameterName)) {
for (ParameterValue property : parameters.get(parameterName)) {
result.add(getPropertyPath(property));
}
}
return result;
}
/**
* Get the property path for a value representing a property configured as
* Merge function parameter.
*
* @param value the value representation of the parameter
* @return the property identified by its property path
*/
public static List<QName> getPropertyPath(Value value) {
// XXX removed because it causes problems with dots in property names
// return PropertyResolver.getQNamesFromPath(value.as(String.class));
// FIXME quick fix that only works because only first level properties
// are supported
return Collections.singletonList(QName.valueOf(value.as(String.class)));
}
/**
* Get the property path for a value representing a property configured as
* Merge function parameter and resolve it to an entity definition.
*
* @param value the value representation of the parameter
* @param parentType the parent type of the property (the type that is
* merged)
* @return the entity definition resolved from the property path
* @throws IllegalStateException if the property path cannot be resolved
*/
public static EntityDefinition resolvePropertyPath(Value value, TypeDefinition parentType) {
List<QName> propertyPath = MergeUtil.getPropertyPath(value);
List<ChildDefinition<?>> path = new ArrayList<>();
Definition<?> parent = parentType;
for (QName element : propertyPath) {
ChildDefinition<?> child = DefinitionUtil.getChild(parent, element);
if (child != null) {
path.add(child);
parent = child;
}
else {
throw new IllegalStateException(
"Could not resolve child " + element + " in parent " + parent);
}
}
if (path.isEmpty()) {
throw new IllegalStateException("No elements in property path");
}
List<ChildContext> contexts = path.stream().map(ChildContext::new)
.collect(Collectors.toList());
return AlignmentUtil.createEntity(parentType, contexts, SchemaSpaceID.SOURCE, null);
}
/**
* Convert a property path to a value to be used for a parameter.
*
* @param path the property path
* @return the representation a parameter value
*/
public static ParameterValue toPropertyParameter(List<QName> path) {
if (path == null || path.isEmpty()) {
throw new IllegalArgumentException("Property path may not be empty");
}
// FIXME only works for 1-level properties
if (path.size() > 1) {
throw new IllegalStateException("Only properties w/ one level supported currently");
}
// TODO instead representation via ValueList and QName?
QName property = path.get(0);
return new ParameterValue(property.toString());
}
}