use of eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl in project hale by halestudio.
the class AbstractBaseAlignmentLoader method generatePrefixMapping.
/**
* Function to fill the prefixMapping and alignmentToInfo maps.
*
* @param addBase the URI of the new base alignment to add
* @param projectLocation the project location or <code>null</code>
* @param existingBases the map of existing bases
* @param prefixMapping gets filled with a mapping from local to global
* prefixes
* @param alignmentToInfo gets filled with a mapping from base alignment
* representations to prefixes and URIs
* @param reporter the reporter
* @return whether newBase actually is a new base and the add process should
* continue
*/
private boolean generatePrefixMapping(URI addBase, URI projectLocation, Map<String, URI> existingBases, Map<A, Map<String, String>> prefixMapping, Map<A, AlignmentInfo> alignmentToInfo, IOReporter reporter) {
// Project location may be null if the project wasn't saved yet
// Then, it still is okay, if all bases are absolute.
URI currentAbsolute = projectLocation;
URI usedAddBaseURI = addBase;
URI absoluteAddBaseURI = resolve(currentAbsolute, usedAddBaseURI);
// set of already seen URIs
Set<URI> knownURIs = new HashSet<URI>();
// reverse map of base
Map<URI, String> uriToPrefix = new HashMap<URI, String>();
// create URI to prefix map and known URIs
for (Entry<String, URI> baseEntry : existingBases.entrySet()) {
// make sure to use absolute URIs here for comparison
URI absoluteBase = resolve(currentAbsolute, baseEntry.getValue());
knownURIs.add(absoluteBase);
uriToPrefix.put(absoluteBase, baseEntry.getKey());
}
if (uriToPrefix.containsKey(absoluteAddBaseURI)) {
reporter.info(new IOMessageImpl("The base alignment (" + addBase + ") is already included.", null));
return false;
}
Set<String> existingPrefixes = new HashSet<String>(existingBases.keySet());
String newPrefix = generatePrefix(existingPrefixes);
existingPrefixes.add(newPrefix);
uriToPrefix.put(absoluteAddBaseURI, newPrefix);
/*
* XXX Adding a base alignment could only use a PathUpdate for the
* movement of the base alignment which is not known in the current
* project. Maybe could try the one of the current project either way?
*/
// find all alignments to load (also missing ones) and load the beans
LinkedList<URIPair> queue = new LinkedList<URIPair>();
queue.add(new URIPair(absoluteAddBaseURI, usedAddBaseURI));
while (!queue.isEmpty()) {
URIPair baseURI = queue.pollFirst();
A baseA;
try {
baseA = loadAlignment(new DefaultInputSupplier(baseURI.absoluteURI).getInput(), reporter);
} catch (IOException e) {
reporter.error(new IOMessageImpl("Couldn't load an included base alignment (" + baseURI.absoluteURI + ").", e));
reporter.setSuccess(false);
return false;
}
// add to alignment info map
alignmentToInfo.put(baseA, new AlignmentInfo(uriToPrefix.get(baseURI.absoluteURI), baseURI));
prefixMapping.put(baseA, new HashMap<String, String>());
// load "missing" base alignments, too, add prefix mapping
for (Entry<String, URI> baseEntry : getBases(baseA).entrySet()) {
// rawURI may be relative
URI rawURI = baseEntry.getValue();
URI absoluteURI = baseURI.absoluteURI.resolve(rawURI);
URI usedURI = absoluteURI;
// and rawURI are relative, continue using a relative URI.
if (!usedAddBaseURI.isAbsolute() && !baseURI.usedURI.isAbsolute() && !rawURI.isAbsolute()) {
usedURI = IOUtils.getRelativePath(absoluteURI, currentAbsolute);
}
// check whether this base alignment is missing
if (!knownURIs.contains(absoluteURI)) {
reporter.info(new IOMessageImpl("A base alignment referenced another base alignment (" + absoluteURI + ") that was not yet known. It is now included, too.", null));
queue.add(new URIPair(absoluteURI, usedURI));
knownURIs.add(absoluteURI);
String prefix = generatePrefix(existingPrefixes);
existingPrefixes.add(prefix);
uriToPrefix.put(absoluteURI, prefix);
}
// add prefix mapping
prefixMapping.get(baseA).put(baseEntry.getKey(), uriToPrefix.get(absoluteURI));
}
}
return true;
}
use of eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl in project hale by halestudio.
the class AbstractBaseAlignmentLoader method processBaseAlignments.
/**
* Creates and adds cells and modifiers of the base alignments to the main
* alignment.
*
* @param alignment the alignment to add base alignments to
* @param sourceTypes the source types to use for resolving definition
* references
* @param targetTypes the target types to use for resolving definition
* references
* @param prefixMapping gets filled with a mapping from local to global
* prefixes
* @param alignmentToInfo gets filled with a mapping from base alignment
* representations to prefixes and URIs
* @param reporter the I/O reporter to report any errors to, may be
* <code>null</code>
* @throws IOException if one of the base alignments does not have cell ids
*/
private void processBaseAlignments(MutableAlignment alignment, TypeIndex sourceTypes, TypeIndex targetTypes, Map<A, Map<String, String>> prefixMapping, Map<A, AlignmentInfo> alignmentToInfo, IOReporter reporter) throws IOException {
for (Entry<A, AlignmentInfo> base : alignmentToInfo.entrySet()) {
Collection<C> baseCells = getCells(base.getKey());
boolean hasIds = true;
for (C baseCell : baseCells) if (Strings.isNullOrEmpty(getCellId(baseCell))) {
hasIds = false;
break;
}
if (!hasIds) {
throw new IOException("At least one base alignment (" + base.getValue().uri.absoluteURI + ") has no cell ids. Please load and save it to generate them.");
}
}
for (Entry<A, AlignmentInfo> base : alignmentToInfo.entrySet()) {
if (alignment.getBaseAlignments().containsValue(base.getValue().uri.usedURI)) {
// base alignment already present
// can currently happen with base alignments included in base
// alignments
reporter.warn(new IOMessageImpl("Base alignment at " + base.getValue().uri.usedURI + " has already been added", null));
} else {
Collection<CustomPropertyFunction> baseFunctions = getPropertyFunctions(base.getKey(), sourceTypes, targetTypes);
Collection<C> baseCells = getCells(base.getKey());
Collection<BaseAlignmentCell> createdBaseCells = new ArrayList<BaseAlignmentCell>(baseCells.size());
List<MutableCell> createdCells = new ArrayList<>(baseCells.size());
for (C baseCell : baseCells) {
// add cells of base alignments
MutableCell cell = createCell(baseCell, sourceTypes, targetTypes, reporter);
if (cell != null) {
createdCells.add(cell);
}
}
// Migrate UnmigratedCells
migrateCells(createdCells, reporter);
for (MutableCell cell : createdCells) {
createdBaseCells.add(new BaseAlignmentCell(cell, base.getValue().uri.usedURI, base.getValue().prefix));
}
alignment.addBaseAlignment(base.getValue().prefix, base.getValue().uri.usedURI, createdBaseCells, baseFunctions);
}
}
// add modifiers of base alignments
for (Entry<A, AlignmentInfo> base : alignmentToInfo.entrySet()) applyModifiers(alignment, getModifiers(base.getKey()), prefixMapping.get(base.getKey()), base.getValue().prefix, true, reporter);
}
use of eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl in project hale by halestudio.
the class MappingExporter method execute.
@Override
protected IOReport execute(ProgressIndicator progress, IOReporter reporter) throws IOProviderConfigurationException, IOException {
progress.begin("Generate mapping documentation", ProgressIndicator.UNKNOWN);
// retrieve template URL
URL templateUrl = getClass().getResource("mapping.html");
// generate Json representation
CellJsonExtension ext = new ExtendedCellRepresentation(getAlignment(), getServiceProvider());
ValueRepresentation rep = new JsonValueRepresentation();
StringWriter jsonWriter = new StringWriter();
JsonStreamBuilder json = new JsonStreamBuilder(jsonWriter, true);
Set<Locale> locales = AlignmentJson.alignmentInfoJSON(getAlignment(), json, getServiceProvider(), getProjectInfo(), ext, rep, Locale.getDefault(), getSourceSchema(), getTargetSchema());
// create language binding
String languageJson = getLanguageJson(locales);
// create template binding
Map<String, Object> binding = new HashMap<>();
binding.put("json", jsonWriter.toString());
String title = (getProjectInfo() != null && getProjectInfo().getName() != null) ? getProjectInfo().getName() : "Mapping documentation";
binding.put("title", title);
binding.put("languages", languageJson);
binding.put("halejsVersion", HALEJS_VERSION);
// initialize template engine
GStringTemplateEngine engine = new GStringTemplateEngine();
// bind and write template
try (Writer out = new OutputStreamWriter(getTarget().getOutput(), StandardCharsets.UTF_8)) {
Writable template = engine.createTemplate(templateUrl).make(binding);
template.writeTo(out);
reporter.setSuccess(true);
} catch (Exception e) {
reporter.error(new IOMessageImpl("Error creating mapping documentation", e));
reporter.setSuccess(false);
} finally {
progress.end();
}
return reporter;
}
use of eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl in project hale by halestudio.
the class JDBCInstanceReader method execute.
@Override
protected IOReport execute(ProgressIndicator progress, IOReporter reporter) throws IOProviderConfigurationException, IOException {
progress.begin("Configure database connection", ProgressIndicator.UNKNOWN);
try {
testConnection();
String user = getParameter(PARAM_USER).as(String.class);
String password = getParameter(PARAM_PASSWORD).as(String.class);
Map<TypeDefinition, InstanceCollection> collections = new HashMap<>();
// only load instances for mapping relevant types
for (TypeDefinition type : getSourceSchema().getMappingRelevantTypes()) {
// check constraint if a Database table or not
if (type.getConstraint(DatabaseTable.class).isTable()) {
collections.put(type, new JDBCTableCollection(type, getSource().getLocation(), user, password, getCrsProvider(), getServiceProvider()) {
// To provide extensibility for getting customized
// database connection for
// Instance reading.
@Override
protected Connection createConnection() throws SQLException {
return JDBCInstanceReader.this.getConnection();
}
});
} else // database?
if (type.getConstraint(SQLQuery.class).hasQuery()) {
collections.put(type, new JDBCTableCollection(type, getSource().getLocation(), user, password, getCrsProvider(), getServiceProvider()) {
// To provide extensibility for getting customized
// database connection for
// Instance reading.
@Override
protected Connection createConnection() throws SQLException {
return JDBCInstanceReader.this.getConnection();
}
});
}
}
collection = new PerTypeInstanceCollection(collections);
reporter.setSuccess(true);
} catch (Exception e) {
reporter.error(new IOMessageImpl("Error configuring database connection", e));
reporter.setSuccess(false);
} finally {
progress.end();
}
return reporter;
}
use of eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl in project hale by halestudio.
the class JDBCInstanceWriter method populateInsertStatementOrExecuteAutoIncStatement.
/**
* Populate a prepared insert statement with values from the given instance.
* Checks if the property has auto incremental constraint, if it has then it
* maps the original old id to the id that is auto incremented while
* inserting the value. This mapping is used when inserting the foreign key
* values associated with those auto incremented column ids whose value has
* been changed. Thus, insertion of the foreign key wont fail. It will
* either execute the statement directly or add it into the batches
* depending upon the auto incremented flag.
*
* @param statement the insert statement
* @param properties the properties to fill the statement with
* @param instance the instance
* @param reporter the reporter
* @param conn Connection (used for Geometry conversion for oracle)
* @throws SQLException if configuring the statement fails
*/
private void populateInsertStatementOrExecuteAutoIncStatement(PreparedStatement statement, Set<QName> properties, Instance instance, IOReporter reporter, Connection conn) throws SQLException {
TypeDefinition type = instance.getDefinition();
int index = 1;
Object oldValue = null;
boolean isAutoIncremented = false;
for (QName propertyName : properties) {
PropertyDefinition property = (PropertyDefinition) type.getChild(propertyName);
Object[] values = instance.getProperty(propertyName);
SQLType sqlType = property.getPropertyType().getConstraint(SQLType.class);
if (!sqlType.isSet()) {
reporter.error(new IOMessageImpl("SQL type not set. Please only export to schemas read from a database.", null));
statement.setObject(index, null);
continue;
}
SQLArray arrayInfo = property.getPropertyType().getConstraint(SQLArray.class);
Object value;
if (arrayInfo.isArray() && arrayInfo.getDimension() <= 1) {
// array as multiple occurrence property
value = (values == null) ? (new Object[0]) : (values);
} else {
// single value
if (values != null && values.length > 1)
reporter.warn(new IOMessageImpl("Multiple values for a property. Only exporting first.", null));
value = (values == null || values.length == 0) ? null : values[0];
}
AutoGenerated auto = property.getConstraint(AutoGenerated.class);
if (!isWriteUnordered()) {
if (auto.isEnabled()) {
isAutoIncremented = true;
if (value != null) {
oldValue = value;
}
continue;
}
}
Reference ref = property.getConstraint(Reference.class);
if (ref.getReferencedTypes() != null) {
TypeDefinition td = (TypeDefinition) ref.getReferencedTypes().toArray()[0];
Map<Object, Long> marshMallow = typAuto.get(td);
if (marshMallow != null && value != null) {
// lookup identifier for reference
value = marshMallow.get(processLookupId(value));
}
}
if (values == null || values.length == 0) {
// XXX The default value could be a function call.
// Better would be to leave the column out of the insert
// statement, or set it to the SQL keyword "DEFAULT".
DefaultValue defaultValue = property.getConstraint(DefaultValue.class);
if (defaultValue.isSet())
statement.setObject(index, defaultValue.getValue(), sqlType.getType());
else if (property.getConstraint(NillableFlag.class).isEnabled())
statement.setNull(index, sqlType.getType());
else {
// no default, not nillable, will not work...
// set it to null here and let query fail (probably)
// XXX maybe skip this insert?
statement.setNull(index, sqlType.getType());
reporter.warn(new IOMessageImpl("Property no value, not nillable, no default value, insert will probably fail.", null));
}
} else if (value == null)
statement.setNull(index, sqlType.getType());
else
setStatementParameter(statement, index, value, property, sqlType.getType(), reporter, conn);
index++;
}
if (isAutoIncremented) {
statement.execute();
ResultSet rs = statement.getGeneratedKeys();
Long newValue = null;
while (rs.next()) {
newValue = rs.getLong(1);
}
addIDMapping(type, oldValue, newValue);
} else {
statement.addBatch();
}
}
Aggregations