/*
* 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.io.impl.internal;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.exolab.castor.xml.XMLContext;
import org.xml.sax.InputSource;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import eu.esdihumboldt.hale.common.align.extension.function.custom.CustomPropertyFunction;
import eu.esdihumboldt.hale.common.align.model.Alignment;
import eu.esdihumboldt.hale.common.align.model.BaseAlignmentCell;
import eu.esdihumboldt.hale.common.align.model.Cell;
import eu.esdihumboldt.hale.common.align.model.MutableAlignment;
import eu.esdihumboldt.hale.common.align.model.MutableCell;
import eu.esdihumboldt.hale.common.align.model.TransformationMode;
import eu.esdihumboldt.hale.common.core.io.PathUpdate;
import eu.esdihumboldt.hale.common.core.io.report.IOReporter;
import eu.esdihumboldt.hale.common.schema.model.TypeIndex;
/**
* Alignment bean serving as model for alignment I/O
*
* @author Simon Templer
*/
public class AlignmentBean extends
AbstractBaseAlignmentLoader<AlignmentBean, CellBean, ModifierBean> {
private Map<String, URI> base = new HashMap<String, URI>();
private Collection<CellBean> cells = new LinkedHashSet<CellBean>();
private Collection<ModifierBean> modifiers = new ArrayList<ModifierBean>();
/**
* Default constructor
*/
public AlignmentBean() {
super();
}
/**
* Create a bean for the given alignment
*
* @param alignment the alignment
* @param pathUpdate to update relative paths in case of a path change
*/
public AlignmentBean(Alignment alignment, final PathUpdate pathUpdate) {
super();
base = new HashMap<String, URI>(Maps.transformValues(alignment.getBaseAlignments(),
new Function<URI, URI>() {
@Override
public URI apply(URI input) {
return pathUpdate.findLocation(input, true, false, true);
}
}));
// populate bean from alignment
for (Cell cell : alignment.getCells()) {
generateModifier(cell);
if (cell instanceof BaseAlignmentCell)
continue;
CellBean cellBean = new CellBean(cell);
cells.add(cellBean);
}
}
/**
* Load an AlignmentBean from an input stream. The stream is closed at the
* end.
*
* @param in the input stream
* @param reporter the I/O reporter to report any errors to, may be
* <code>null</code>
* @return the AlignmentBean
*
* @throws MappingException if the mapping could not be loaded
* @throws MarshalException if the alignment could not be read
* @throws ValidationException if the input stream did not provide valid XML
*/
public static AlignmentBean load(InputStream in, IOReporter reporter) throws MappingException,
MarshalException, ValidationException {
Mapping mapping = new Mapping(AlignmentBean.class.getClassLoader());
mapping.loadMapping(new InputSource(AlignmentBean.class
.getResourceAsStream("AlignmentBean.xml")));
XMLContext context = new XMLContext();
context.addMapping(mapping);
Unmarshaller unmarshaller = context.createUnmarshaller();
try {
return (AlignmentBean) unmarshaller.unmarshal(new InputSource(in));
} finally {
try {
in.close();
} catch (IOException e) {
// ignore
}
}
}
/**
* Adds the given base alignment to the given alignment.
*
* @param alignment the alignment to add a base alignment to
* @param newBase URI of the new base alignment
* @param projectLocation the project location or <code>null</code>
* @param sourceTypes the source types to use for resolving definition
* references
* @param targetTypes the target types to use for resolving definition
* references
* @param reporter the I/O reporter to report any errors to, may be
* <code>null</code>
* @throws IOException if adding the base alignment fails
*/
public static void addBaseAlignment(MutableAlignment alignment, URI newBase,
URI projectLocation, TypeIndex sourceTypes, TypeIndex targetTypes, IOReporter reporter)
throws IOException {
new AlignmentBean().internalAddBaseAlignment(alignment, newBase, projectLocation,
sourceTypes, targetTypes, reporter);
}
/**
* Generates and adds a modifier for the given cell if necessary.
*
* @param cell the cell to generate a modifier for
*/
private void generateModifier(Cell cell) {
Collection<String> disabledFor;
if (cell instanceof BaseAlignmentCell)
disabledFor = ((BaseAlignmentCell) cell).getAdditionalDisabledFor();
else
disabledFor = cell.getDisabledFor();
if (!disabledFor.isEmpty()) {
ModifierBean modifier = new ModifierBean(cell.getId());
modifier.setDisableForRelation(disabledFor);
modifiers.add(modifier);
}
}
/**
* Create an alignment from the information in the bean.
*
* @param reporter the I/O reporter to report any errors to, may be
* <code>null</code>
* @param sourceTypes the source types to use for resolving definition
* references
* @param targetTypes the target types to use for resolving definition
* references
* @param updater the path updater to use for base alignments
* @return the alignment
* @throws IOException if creating the alignment fails
*/
public MutableAlignment createAlignment(IOReporter reporter, TypeIndex sourceTypes,
TypeIndex targetTypes, PathUpdate updater) throws IOException {
return super.createAlignment(this, sourceTypes, targetTypes, updater, reporter);
}
/**
* Get the defined cells
*
* @return the cells
*/
public Collection<CellBean> getCells() {
return cells;
}
/**
* Set the defined cells
*
* @param cells the cells to set
*/
public void setCells(Collection<CellBean> cells) {
this.cells = cells;
}
/**
* Get the alignment modifiers
*
* @return the modifiers
*/
public Collection<ModifierBean> getModifiers() {
return modifiers;
}
/**
* Set the alignment modifiers
*
* @param modifiers the modifiers to set
*/
public void setModifiers(Collection<ModifierBean> modifiers) {
this.modifiers = modifiers;
}
/**
* @return the base
*/
public Map<String, URI> getBase() {
return base;
}
/**
* @param base the base to set
*/
public void setBase(Map<String, URI> base) {
this.base = base;
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#loadAlignment(java.io.InputStream,
* eu.esdihumboldt.hale.common.core.io.report.IOReporter)
*/
@Override
protected AlignmentBean loadAlignment(InputStream in, IOReporter reporter) throws IOException {
try {
return load(in, reporter);
} catch (MarshalException e) {
throw new IOException(e);
} catch (ValidationException e) {
throw new IOException(e);
} catch (MappingException e) {
throw new IOException(e);
}
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#getBases(java.lang.Object)
*/
@Override
protected Map<String, URI> getBases(AlignmentBean alignment) {
return alignment.base;
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#getCells(java.lang.Object)
*/
@Override
protected Collection<CellBean> getCells(AlignmentBean alignment) {
return alignment.cells;
}
@Override
protected Collection<CustomPropertyFunction> getPropertyFunctions(AlignmentBean alignment,
TypeIndex sourceTypes, TypeIndex targetTypes) {
// not supported
return Collections.emptyList();
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#createCell(java.lang.Object,
* eu.esdihumboldt.hale.common.schema.model.TypeIndex,
* eu.esdihumboldt.hale.common.schema.model.TypeIndex,
* eu.esdihumboldt.hale.common.core.io.report.IOReporter)
*/
@Override
protected MutableCell createCell(CellBean cell, TypeIndex sourceTypes, TypeIndex targetTypes,
IOReporter reporter) {
return cell.createCell(reporter, sourceTypes, targetTypes);
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#getModifiers(java.lang.Object)
*/
@Override
protected Collection<ModifierBean> getModifiers(AlignmentBean alignment) {
return alignment.modifiers;
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#getModifiedCell(java.lang.Object)
*/
@Override
protected String getModifiedCell(ModifierBean modifier) {
return modifier.getCell();
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#getDisabledForList(java.lang.Object)
*/
@Override
protected Collection<String> getDisabledForList(ModifierBean modifier) {
return modifier.getDisableForRelation();
}
@Override
protected TransformationMode getTransformationMode(ModifierBean modifier) {
// not supported
return null;
}
/**
* @see eu.esdihumboldt.hale.common.align.io.impl.internal.AbstractBaseAlignmentLoader#getCellId(java.lang.Object)
*/
@Override
protected String getCellId(CellBean cell) {
return cell.getId();
}
}