use of eu.esdihumboldt.hale.common.align.model.Condition in project hale by halestudio.
the class AppSchemaMappingTest method createTargetProperty.
private ListMultimap<String, Property> createTargetProperty(TypeDefinition targetType, List<ChildDefinition<?>> childDefs, List<Integer> contextNames, List<Condition> conditions) {
if (contextNames == null) {
contextNames = Collections.emptyList();
}
if (conditions == null) {
conditions = Collections.emptyList();
}
List<ChildContext> childContext = new ArrayList<ChildContext>();
for (int i = 0; i < childDefs.size(); i++) {
ChildDefinition<?> childDef = childDefs.get(i);
Integer contextName = (contextNames.size() > i) ? contextNames.get(i) : null;
Condition condition = (conditions.size() > 1) ? conditions.get(i) : null;
childContext.add(new ChildContext(contextName, null, condition, childDef));
}
ListMultimap<String, Property> target = ArrayListMultimap.create();
target.put(null, new DefaultProperty(new PropertyEntityDefinition(targetType, childContext, SchemaSpaceID.TARGET, null)));
return target;
}
use of eu.esdihumboldt.hale.common.align.model.Condition in project hale by halestudio.
the class InstanceVisitor method visit.
/**
* @see AbstractSourceToTargetVisitor#visit(SourceNode)
*/
@Override
public boolean visit(SourceNode source) {
if (source.getDefinition() instanceof TypeDefinition) {
if (instance == null)
return false;
// source root
if (source.getDefinition().equals(instance.getDefinition())) {
// check type filter (if any)
Filter filter = source.getEntityDefinition().getFilter();
if (filter != null && !filter.match(instance)) {
// instance does not match filter, don't descend further
return false;
/*
* XXX What about merged instances? Will this be OK for
* those? A type filter should only apply to the original
* instance if it is merged - but most filters should
* evaluate the same
*/
} else {
// also sets the node to defined
source.setValue(instance);
for (FamilyInstance child : instance.getChildren()) {
// Find fitting SourceNodes.
Collection<SourceNode> candidateNodes = tree.getRootSourceNodes(child.getDefinition());
if (candidateNodes.isEmpty()) {
/*
* No node found - but this may be because no
* property of the type is mapped, but there still
* might be child instances (in a Join) that have
* types with associated relations. To prevent those
* being skipped we add an artificial node
* representing the instance.
*/
candidateNodes = new ArrayList<>();
EntityDefinition entityDef = new TypeEntityDefinition(child.getDefinition(), SchemaSpaceID.SOURCE, null);
candidateNodes.add(new SourceNodeImpl(entityDef, null, false));
}
for (SourceNode candidateNode : candidateNodes) {
filter = candidateNode.getEntityDefinition().getFilter();
if (filter == null || filter.match(child)) {
// XXX add to all candidates!?
if (candidateNode.getValue() == null) {
candidateNode.setAnnotatedParent(source);
source.addAnnotatedChild(candidateNode);
} else {
// Duplicate here, because there is no
// guarantee, that the Duplication
// Visitor will visit candidateNode after
// this node.
SourceNodeImpl duplicateNode = new SourceNodeImpl(candidateNode.getEntityDefinition(), candidateNode.getParent(), false);
duplicateNode.setAnnotatedParent(source);
source.addAnnotatedChild(duplicateNode);
TransformationContext context = candidateNode.getContext();
duplicateNode.setContext(context);
if (context != null) {
context.duplicateContext(candidateNode, duplicateNode, Collections.<Cell>emptySet(), log);
} else {
/*
* Not sure what this really means if we
* get here.
*
* Best guess: Probably that we weren't
* able to determine how the duplication
* of this source can be propagted to
* the target. Thus the duplicated node
* will probably not have any
* connection.
*/
log.warn(log.createMessage("No transformation context for duplicated node of source " + candidateNode.getDefinition().getDisplayName(), null));
}
candidateNode = duplicateNode;
}
// run instance visitor on that annotated child
InstanceVisitor visitor = new InstanceVisitor(child, tree, log);
candidateNode.accept(visitor);
}
}
}
return true;
}
} else
return false;
} else {
Object parentValue = source.getParent().getValue();
if (parentValue == null || !(parentValue instanceof Group)) {
source.setDefined(false);
return false;
} else {
Group parentGroup = (Group) parentValue;
Definition<?> currentDef = source.getDefinition();
Object[] values = parentGroup.getProperty(currentDef.getName());
if (values == null) {
source.setDefined(false);
return false;
}
// check for contexts
EntityDefinition entityDef = source.getEntityDefinition();
// index context
Integer index = AlignmentUtil.getContextIndex(entityDef);
if (index != null) {
// only use the value at the given index, if present
if (index < values.length) {
// annotate with the value at the index
Object value = values[index];
source.setValue(value);
return true;
} else {
source.setDefined(false);
return false;
}
}
// condition context
Condition condition = AlignmentUtil.getContextCondition(entityDef);
if (condition != null) {
if (condition.getFilter() == null) {
// assume exclusion
source.setDefined(false);
return false;
}
// apply condition as filter on values and continue with
// those values
Collection<Object> matchedValues = new ArrayList<Object>();
for (Object value : values) {
// determine parent
Object parent = null;
SourceNode parentNode = source.getParent();
if (parentNode != null && parentNode.isDefined()) {
parent = parentNode.getValue();
}
// test the condition
if (AlignmentUtil.matchCondition(condition, value, parent)) {
matchedValues.add(value);
}
}
values = matchedValues.toArray();
}
// default behavior (default context)
if (values.length >= 1) {
// annotate with the first value
Object value = values[0];
source.setValue(value);
source.setAllValues(values);
} else {
source.setDefined(false);
return false;
}
if (values.length > 1) {
// handle additional values
Object[] leftovers = new Object[values.length - 1];
System.arraycopy(values, 1, leftovers, 0, leftovers.length);
source.setLeftovers(new LeftoversImpl(source, leftovers));
}
return true;
}
}
}
use of eu.esdihumboldt.hale.common.align.model.Condition in project hale by halestudio.
the class EntityDefinitionServiceImpl method getChildren.
/**
* @see EntityDefinitionService#getChildren(EntityDefinition)
*/
@Override
public Collection<? extends EntityDefinition> getChildren(EntityDefinition entity) {
List<ChildContext> path = entity.getPropertyPath();
Collection<? extends ChildDefinition<?>> children;
if (path == null || path.isEmpty()) {
// entity is a type, children are the type children
children = entity.getType().getChildren();
} else {
// get parent context
ChildContext parentContext = path.get(path.size() - 1);
if (parentContext.getChild().asGroup() != null) {
children = parentContext.getChild().asGroup().getDeclaredChildren();
} else if (parentContext.getChild().asProperty() != null) {
children = parentContext.getChild().asProperty().getPropertyType().getChildren();
} else {
throw new IllegalStateException("Illegal child definition type encountered");
}
}
if (children == null || children.isEmpty()) {
return Collections.emptyList();
}
Collection<EntityDefinition> result = new ArrayList<EntityDefinition>(children.size());
for (ChildDefinition<?> child : children) {
// add default child entity definition to result
ChildContext context = new ChildContext(child);
EntityDefinition defaultEntity = createEntity(entity.getType(), createPath(entity.getPropertyPath(), context), entity.getSchemaSpace(), entity.getFilter());
result.add(defaultEntity);
// look up additional instance contexts and add them
synchronized (namedContexts) {
for (Integer contextName : namedContexts.get(defaultEntity)) {
ChildContext namedContext = new ChildContext(contextName, null, null, child);
EntityDefinition namedChild = createEntity(entity.getType(), createPath(entity.getPropertyPath(), namedContext), entity.getSchemaSpace(), entity.getFilter());
result.add(namedChild);
}
}
synchronized (indexContexts) {
for (Integer index : indexContexts.get(defaultEntity)) {
ChildContext indexContext = new ChildContext(null, index, null, child);
EntityDefinition indexChild = createEntity(entity.getType(), createPath(entity.getPropertyPath(), indexContext), entity.getSchemaSpace(), entity.getFilter());
result.add(indexChild);
}
}
synchronized (conditionContexts) {
for (Condition condition : conditionContexts.get(defaultEntity)) {
ChildContext conditionContext = new ChildContext(null, null, condition, child);
EntityDefinition conditionChild = createEntity(entity.getType(), createPath(entity.getPropertyPath(), conditionContext), entity.getSchemaSpace(), entity.getFilter());
result.add(conditionChild);
}
}
}
return result;
}
use of eu.esdihumboldt.hale.common.align.model.Condition in project hale by halestudio.
the class EntityDefinitionServiceImpl method addContexts.
/**
* Add the missing contexts for the given entity definition.
*
* @param entityDef the entity definition to add contexts for
* @param addedContexts a collection where newly created contexts must be
* added
*/
private void addContexts(EntityDefinition entityDef, Collection<EntityDefinition> addedContexts) {
// collect the entity definition and all of its parents
LinkedList<EntityDefinition> hierarchy = new LinkedList<EntityDefinition>();
EntityDefinition parent = entityDef;
while (parent != null) {
hierarchy.addFirst(parent);
parent = getParent(parent);
}
// topmost parent
for (EntityDefinition candidate : hierarchy) {
Integer contextName = AlignmentUtil.getContextName(candidate);
Integer contextIndex = AlignmentUtil.getContextIndex(candidate);
Condition contextCondition = AlignmentUtil.getContextCondition(candidate);
if (contextName != null || contextIndex != null || contextCondition != null) {
if (contextName != null && contextIndex == null && contextCondition == null) {
// add named context
boolean added = namedContexts.put(AlignmentUtil.getDefaultEntity(candidate), contextName);
if (added) {
addedContexts.add(candidate);
}
} else if (contextIndex != null && contextName == null && contextCondition == null) {
// add index context
boolean added = indexContexts.put(AlignmentUtil.getDefaultEntity(candidate), contextIndex);
if (added) {
addedContexts.add(candidate);
}
} else if (contextCondition != null && contextName == null && contextIndex == null) {
// add condition context
boolean added = conditionContexts.put(AlignmentUtil.getDefaultEntity(candidate), contextCondition);
if (added) {
addedContexts.add(candidate);
}
} else {
throw new IllegalArgumentException("Illegal combination of instance contexts");
}
}
}
}
use of eu.esdihumboldt.hale.common.align.model.Condition in project hale by halestudio.
the class EntityDefinitionServiceImpl method addConditionContext.
/**
* @see EntityDefinitionService#addConditionContext(EntityDefinition,
* Filter)
*/
@Override
public EntityDefinition addConditionContext(EntityDefinition sibling, Filter filter) {
if (filter == null) {
throw new NullPointerException("Filter must not be null");
}
List<ChildContext> path = sibling.getPropertyPath();
if (sibling.getSchemaSpace() == SchemaSpaceID.TARGET && path.isEmpty()) {
// XXX throw exception instead?
return null;
}
Condition condition = new Condition(filter);
EntityDefinition def = AlignmentUtil.getDefaultEntity(sibling);
boolean doAdd = true;
synchronized (conditionContexts) {
// get registered context indexes
Set<Condition> existingConditions = conditionContexts.get(def);
if (existingConditions.contains(condition)) {
// this condition context is not new, but already there
doAdd = false;
}
if (doAdd) {
conditionContexts.put(def, condition);
}
}
EntityDefinition result = createWithCondition(sibling, condition);
if (doAdd) {
notifyContextAdded(result);
}
return result;
}
Aggregations