use of eu.esdihumboldt.hale.common.align.model.impl.DefaultCell in project hale by halestudio.
the class DefaultsVisitor method addAugmentationCell.
/**
* Add a simple cell using an augmentation w/o parameters.
*
* @param ped the property entity definition
* @param functionId the function identifier
* @param priority the cell priority
*/
private void addAugmentationCell(PropertyEntityDefinition ped, String functionId, Priority priority) {
// create cell template
MutableCell cell = new DefaultCell();
cell.setPriority(priority);
ListMultimap<String, Entity> target = ArrayListMultimap.create();
cell.setTarget(target);
// set transformation identifier (Function ID)
cell.setTransformationIdentifier(functionId);
// set cell target (Property)
target.put(null, new DefaultProperty(ped));
BGISAppUtil.appendNote(cell, "Generated default mapping.");
cells.add(cell);
}
use of eu.esdihumboldt.hale.common.align.model.impl.DefaultCell in project hale by halestudio.
the class DuplicateVisitor method visit.
@Override
protected boolean visit(PropertyEntityDefinition ped) {
if (ADE_NS.equals(ped.getDefinition().getName().getNamespaceURI())) {
for (Cell exampleCell : exampleCells.get(ped.getDefinition().getName().getLocalPart())) {
// handle each example cell
// copy cell
DefaultCell cell = new DefaultCell(exampleCell);
// reset ID
cell.setId(null);
// assign new target
ListMultimap<String, Entity> target = ArrayListMultimap.create();
target.put(cell.getTarget().keys().iterator().next(), new DefaultProperty(ped));
cell.setTarget(target);
BGISAppUtil.appendNote(cell, cellNote);
cells.add(cell);
}
return true;
}
return false;
}
use of eu.esdihumboldt.hale.common.align.model.impl.DefaultCell in project hale by halestudio.
the class CityGMLPropagateVisitor method propagateCell.
/**
* Propagate a given cell to the given target property and possible source
* types.
*
* @param exampleCell the example cell
* @param ped the target property
*/
private void propagateCell(Cell exampleCell, PropertyEntityDefinition ped) {
/*
* Find the type where the property actually is defined, as if possible
* a super type mapping should be used.
*/
TypeDefinition targetType = findTypeDefining(ped);
if (!targetType.equals(ped.getType())) {
ped = new PropertyEntityDefinition(targetType, ped.getPropertyPath(), ped.getSchemaSpace(), ped.getFilter());
}
// check if the cell was already handled for the type
if (handledTargets.get(exampleCell).contains(targetType)) {
// don't produce any duplicates
return;
}
handledTargets.put(exampleCell, targetType);
TypeEntityIndex<List<ChildContext>> index = new TypeEntityIndex<List<ChildContext>>();
Collection<TypeDefinition> sourceTypes = findSourceTypes(exampleCell, targetType, index);
if (sourceTypes != null) {
for (TypeDefinition sourceType : sourceTypes) {
// copy cell
DefaultCell cell = new DefaultCell(exampleCell);
// reset ID
cell.setId(null);
// assign new target
ListMultimap<String, Entity> target = ArrayListMultimap.create();
target.put(cell.getTarget().keys().iterator().next(), new DefaultProperty(ped));
cell.setTarget(target);
// assign new source(s)
ListMultimap<String, Entity> source = ArrayListMultimap.create();
for (Entry<String, ? extends Entity> entry : cell.getSource().entries()) {
// create new source entity
List<ChildContext> path = index.get(sourceType, entry.getValue());
if (path == null) {
throw new IllegalStateException("No replacement property path computed");
}
Property newSource = new DefaultProperty(new PropertyEntityDefinition(sourceType, path, SchemaSpaceID.SOURCE, null));
source.put(entry.getKey(), newSource);
}
cell.setSource(source);
BGISAppUtil.appendNote(cell, cellNote);
cells.add(cell);
}
}
}
use of eu.esdihumboldt.hale.common.align.model.impl.DefaultCell in project hale by halestudio.
the class AlignmentUtil method reparentCell.
/**
* Returns a cell like the given property cell with all source and target
* types matching those off the given type cell.<br>
* If the types already match they are unchanged. If the types are sub types
* of the types of the type cell they are changed. If no change is necessary
* the cell itself is returned.
*
* @param propertyCell the property cell to update
* @param typeCell the type cell with the target types
* @param strict If false and the target type cell has no sources or target,
* the property cell is updated to have the sources/target in
* their declaring type. If true, said properties are left
* unchanged. Does not matter for complete type cells, since they
* have sources and a target.
* @return the updated cell or <code>null</code> if an update isn't possible
*/
public static Cell reparentCell(Cell propertyCell, Cell typeCell, boolean strict) {
ListMultimap<String, Entity> sources = ArrayListMultimap.create();
ListMultimap<String, Entity> targets = ArrayListMultimap.create();
boolean updateNecessary = false;
// XXX are updates to the property path needed?
// Currently not, since ChildDefinitions are compared by their names
// only.
// TARGETS
Entity targetEntity = CellUtil.getFirstEntity(typeCell.getTarget());
if (targetEntity != null) {
TypeDefinition typeCellTargetType = ((Type) targetEntity).getDefinition().getDefinition();
for (Entry<String, ? extends Entity> target : propertyCell.getTarget().entries()) {
TypeDefinition propertyCellTargetType = target.getValue().getDefinition().getType();
if (propertyCellTargetType.equals(typeCellTargetType))
targets.put(target.getKey(), target.getValue());
else if (DefinitionUtil.isSuperType(typeCellTargetType, propertyCellTargetType)) {
PropertyEntityDefinition oldDef = (PropertyEntityDefinition) target.getValue().getDefinition();
targets.put(target.getKey(), new DefaultProperty(new PropertyEntityDefinition(typeCellTargetType, oldDef.getPropertyPath(), SchemaSpaceID.TARGET, null)));
updateNecessary = true;
} else {
// a cell with targets in more than one type
return null;
}
}
} else if (!strict)
updateNecessary |= reparentToDeclaring(propertyCell.getTarget(), targets);
else
targets.putAll(propertyCell.getTarget());
if (propertyCell.getSource() != null && !propertyCell.getSource().isEmpty()) {
if (typeCell.getSource() != null && !typeCell.getSource().isEmpty()) {
// collect source entity definitions
Collection<TypeEntityDefinition> typeCellSourceTypes = new ArrayList<TypeEntityDefinition>();
for (Entity entity : typeCell.getSource().values()) typeCellSourceTypes.add((TypeEntityDefinition) entity.getDefinition());
for (Entry<String, ? extends Entity> source : propertyCell.getSource().entries()) {
TypeEntityDefinition propertyCellSourceType = getTypeEntity(source.getValue().getDefinition());
if (typeCellSourceTypes.contains(propertyCellSourceType))
sources.put(source.getKey(), source.getValue());
else {
boolean matchFound = false;
// maybe the whole cell should be duplicated?
for (TypeEntityDefinition typeCellSourceType : typeCellSourceTypes) {
if (DefinitionUtil.isSuperType(typeCellSourceType.getDefinition(), propertyCellSourceType.getDefinition()) && (propertyCellSourceType.getFilter() == null || propertyCellSourceType.getFilter().equals(typeCellSourceType.getFilter()))) {
if (matchFound)
log.warn("Inherited property cell source matches multiple sources of type cell.");
matchFound = true;
PropertyEntityDefinition oldDef = (PropertyEntityDefinition) source.getValue().getDefinition();
sources.put(source.getKey(), new DefaultProperty(new PropertyEntityDefinition(typeCellSourceType.getDefinition(), oldDef.getPropertyPath(), SchemaSpaceID.SOURCE, typeCellSourceType.getFilter())));
updateNecessary = true;
// XXX break; if only one match should be added
}
}
if (!matchFound) {
// cell
return null;
}
}
}
} else if (!strict)
updateNecessary |= reparentToDeclaring(propertyCell.getSource(), sources);
else
targets.putAll(propertyCell.getTarget());
}
if (updateNecessary) {
MutableCell copy = new DefaultCell(propertyCell);
copy.setSource(sources);
copy.setTarget(targets);
propertyCell = copy;
}
return propertyCell;
}
use of eu.esdihumboldt.hale.common.align.model.impl.DefaultCell in project hale by halestudio.
the class AbstractMergeCellMigrator method mergeSources.
/**
* Update the cell sources.
*
* @param sources the old sources
* @param mergeIndex the merge index
* @param originalCell the original cell
* @param migration the alignment migration (may be useful for cases where
* only entity replacement needs to be done)
* @param getCellMigrator functions that yields a cell migrator for a
* function (may be useful for cases where only entity
* replacement needs to be done)
* @param log the migration process log
* @return the merged cell or cells
*/
protected Iterable<MutableCell> mergeSources(ListMultimap<String, ? extends Entity> sources, MergeIndex mergeIndex, Cell originalCell, AlignmentMigration migration, Function<String, CellMigrator> getCellMigrator, SimpleLog log) {
// XXX relevant here at all?
boolean transferBase = true;
if (sources.size() == 1) {
EntityDefinition source = sources.values().iterator().next().getDefinition();
List<Cell> matches = mergeIndex.getCellsForTarget(source);
List<String> storedMessages = new ArrayList<>();
boolean inaccurateMatch = false;
if (matches.isEmpty()) {
// try to find match via parent (in specific cases)
matches = findParentMatch(source, mergeIndex);
if (!matches.isEmpty()) {
inaccurateMatch = true;
// message may not be added in every case, because it may be
// a duplicate
// storedMessages.add(MessageFormat
// .format("Inaccurate match of {0} via parent entity", source));
}
}
if (!matches.isEmpty()) {
List<MutableCell> cells = new ArrayList<>();
for (Cell match : matches) {
// the original cell
if (isDirectMatch(match)) {
MigrationOptions replaceSource = new MigrationOptionsImpl(true, false, transferBase);
cells.add(getCellMigrator.apply(originalCell.getTransformationIdentifier()).updateCell(originalCell, migration, replaceSource, log));
} else // matching cell
if (isDirectMatch(originalCell)) {
MigrationOptions replaceTarget = new MigrationOptionsImpl(false, true, transferBase);
AlignmentMigration cellMigration = new AbstractMigration() {
@Override
protected Optional<EntityDefinition> findMatch(EntityDefinition entity) {
Entity target = CellUtil.getFirstEntity(originalCell.getTarget());
if (target != null) {
return Optional.ofNullable(target.getDefinition());
}
return Optional.empty();
}
};
MutableCell newCell = getCellMigrator.apply(match.getTransformationIdentifier()).updateCell(match, cellMigration, replaceTarget, log);
SimpleLog cellLog = SimpleLog.all(log, new CellLog(newCell, CELL_LOG_CATEGORY));
// source of original cell may have
// filters/conditions/contexts that are not applied by
// changing the target
// try to apply source contexts
Entity originalSource = CellUtil.getFirstEntity(originalCell.getSource());
applySourceContexts(newCell, originalSource, cellLog);
cells.add(newCell);
} else {
// otherwise, use custom logic to try to combine cells
MutableCell newCell = new DefaultCell(originalCell);
SimpleLog cellLog = SimpleLog.all(log, new CellLog(newCell, CELL_LOG_CATEGORY));
C context = newContext(originalCell);
// reset source
newCell.setSource(ArrayListMultimap.create());
if (inaccurateMatch) {
cellLog.warn(MessageFormat.format("Inaccurate match of {0} via parent entity", source));
}
mergeSource(newCell, sources.keys().iterator().next(), source, match, originalCell, cellLog, context, migration, mergeIndex);
finalize(newCell, migration, context, cellLog);
cells.add(newCell);
}
}
if (!cells.isEmpty() && !storedMessages.isEmpty()) {
// add stored messages
cells.forEach(cell -> {
CellLog cLog = new CellLog(cell, CELL_LOG_CATEGORY);
storedMessages.forEach(msg -> cLog.warn(msg));
});
}
return cells;
} else {
// no match -> remove?
// rather add original + documentation
MutableCell newCell = new DefaultCell(originalCell);
SimpleLog cellLog = SimpleLog.all(log, new CellLog(newCell, CELL_LOG_CATEGORY));
cellLog.warn("No match for source {0} found, unable to associate to new source schema", source);
return Collections.singleton(newCell);
}
} else {
// handle each source
// collects messages in case all matches are direct matches
List<String> directMessages = new ArrayList<>();
// determine if all matches are direct
boolean allDirect = sources.entries().stream().allMatch(source -> {
List<Cell> matches = mergeIndex.getCellsForTarget(source.getValue().getDefinition());
if (matches.isEmpty()) {
directMessages.add(MessageFormat.format("No match was found for source {0}, please check how this can be compensated.", source.getValue().getDefinition()));
// if there is no match, treat it as direct match
return true;
} else {
if (matches.size() > 1) {
directMessages.add(MessageFormat.format("Multiple matches for source {0}, only one was taken into account", source.getValue().getDefinition()));
}
return isDirectMatch(matches.get(0));
}
});
MutableCell newCell;
if (allDirect) {
// if the matching are all Retype/Rename, replace sources of
// the original cell
MigrationOptions replaceSource = new MigrationOptionsImpl(true, false, transferBase);
newCell = getCellMigrator.apply(originalCell.getTransformationIdentifier()).updateCell(originalCell, migration, replaceSource, log);
// add messages from match check
SimpleLog cellLog = SimpleLog.all(log, new CellLog(newCell, CELL_LOG_CATEGORY));
directMessages.forEach(msg -> cellLog.warn(msg));
} else {
// handle each source separately
newCell = new DefaultCell(originalCell);
SimpleLog cellLog = SimpleLog.all(log, new CellLog(newCell, CELL_LOG_CATEGORY));
C context = newContext(originalCell);
// reset source
newCell.setSource(ArrayListMultimap.create());
for (Entry<String, ? extends Entity> source : sources.entries()) {
List<Cell> matches = mergeIndex.getCellsForTarget(source.getValue().getDefinition());
if (!matches.isEmpty()) {
Cell match = matches.get(0);
mergeSource(newCell, source.getKey(), source.getValue().getDefinition(), match, originalCell, cellLog, context, migration, mergeIndex);
if (matches.size() > 1) {
// FIXME how can we deal w/ multiple matches?
cellLog.warn("Multiple matches for source {0}, only one was handled", source.getValue().getDefinition());
}
} else {
// no match, just not add source?
cellLog.warn("No match was found for source {0}, please check how this can be compensated.", source.getValue().getDefinition());
}
}
finalize(newCell, migration, context, cellLog);
}
return Collections.singleton(newCell);
}
}
Aggregations