/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.tool.portfolio.xml;
import java.io.File;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.validation.Schema;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.util.ArgumentChecker;
/**
* Defines the schema-insensitive interface for converting a portfolio
* document. The schema version is parsed and if available used to
* parse the XML document.
*/
public abstract class PortfolioConversion {
/**
* The directory holding the schema.
*/
public static final String SCHEMA_LOCATION = "portfolio-schemas";
/**
* The directory holding the schema.
*/
public static final File SCHEMA_DIRECTORY;
static {
URL resource = PortfolioConversion.class.getClassLoader().getResource(SCHEMA_LOCATION);
if (resource == null) {
throw new OpenGammaRuntimeException("File not found in classpath: " + SCHEMA_LOCATION);
}
try {
SCHEMA_DIRECTORY = new File(resource.toURI());
} catch (URISyntaxException e) {
throw new OpenGammaRuntimeException("File not found in classpath: " + SCHEMA_LOCATION);
}
}
/**
* The XML locator for the schema.
*/
private static final FilesystemPortfolioSchemaLocator SCHEMA_LOCATOR =
new FilesystemPortfolioSchemaLocator(SCHEMA_DIRECTORY);
private final Class<?> _portfolioDocumentClass;
private final PortfolioDocumentConverter<Object> _portfolioConverter;
@SuppressWarnings("unused")
private final IdRefResolverFactory _idRefResolverFactory;
private final Schema _schema;
/**
* Creates an instance.
*
* @param schemaVersion the schema version, not null
* @param portfolioDocumentClass the portfolio class, not null
* @param converter the converter, not null
* @param idRefResolverFactory the resolver, not null
*/
@SuppressWarnings("unchecked")
public PortfolioConversion(SchemaVersion schemaVersion,
Class<?> portfolioDocumentClass,
PortfolioDocumentConverter<?> converter,
IdRefResolverFactory idRefResolverFactory) {
_portfolioDocumentClass = portfolioDocumentClass;
_portfolioConverter = (PortfolioDocumentConverter<Object>) converter;
_idRefResolverFactory = idRefResolverFactory;
_schema = SCHEMA_LOCATOR.lookupSchema(schemaVersion);
ArgumentChecker.notNull(_schema, "schema");
}
//-------------------------------------------------------------------------
/**
* Converts the portfolio.
*
* @param inputStream the inputStream to read, not null
* @return the converted file, not null
*/
public Iterable<VersionedPortfolioHandler> convertPortfolio(InputStream inputStream) {
try {
Unmarshaller unmarshaller = createUnmarshaller();
return _portfolioConverter.convert(unmarshaller.unmarshal(inputStream));
} catch (JAXBException e) {
throw new OpenGammaRuntimeException("Error parsing XML content", e);
}
}
private Unmarshaller createUnmarshaller() throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(_portfolioDocumentClass);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema(_schema);
// Output parsing info to System.out
unmarshaller.setEventHandler(new DefaultValidationEventHandler());
// The resolver allows us to differentiate between trades and positions
// that have the same id. With this a trade and position can both have
// id = 1 in the xml file, yet be resolved correctly based on context.
// TODO can this be done without using a sun.internal class?
//unmarshaller.setProperty(IDResolver.class.getName(), _idRefResolverFactory.create());
return unmarshaller;
}
}