package org.cagrid.gme.service.impl.sax;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.grammars.XMLSchemaDescription;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.cagrid.gme.model.XMLSchema;
import org.cagrid.gme.model.XMLSchemaDocument;
import org.cagrid.gme.service.impl.common.XSDUtil;
import org.cagrid.gme.service.impl.common.exceptions.SchemaParsingException;
import org.cagrid.gme.service.impl.dao.XMLSchemaInformationDao;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
/**
* @author oster
*/
public class GMEEntityResolver implements XMLEntityResolver {
protected List<XMLSchema> submissionSchemas = null;
protected XMLSchemaInformationDao schemaDao = null;
protected static Log LOG = LogFactory.getLog(GMEEntityResolver.class.getName());
public GMEEntityResolver(List<XMLSchema> submissionSchemas, XMLSchemaInformationDao schemaDao) {
super();
this.submissionSchemas = submissionSchemas;
this.schemaDao = schemaDao;
if (submissionSchemas != null) {
LOG.debug("Initializing with " + submissionSchemas.size() + " submission schemas.");
} else {
LOG.debug("Initializing with no submission schemas.");
}
}
public XMLInputSource resolveEntity(XMLResourceIdentifier identifier) throws XNIException, IOException {
String idNamespace = identifier.getNamespace();
String systemId = identifier.getLiteralSystemId();
boolean isImport = true;
if (identifier instanceof XMLSchemaDescription) {
XMLSchemaDescription desc = (XMLSchemaDescription) identifier;
short contextType = desc.getContextType();
if (contextType == XMLSchemaDescription.CONTEXT_IMPORT) {
isImport = true;
} else if (contextType == XMLSchemaDescription.CONTEXT_INCLUDE) {
isImport = false;
} else if (contextType == XMLSchemaDescription.CONTEXT_REDEFINE) {
isImport = false;
} else {
SchemaParsingException e = new SchemaParsingException(
"Internal Error! Got a request to resolve an entity of unknown/unsupported type [" + contextType
+ "].");
LOG.error(e.getMessage(), e);
throw e;
}
LOG.debug("Got a request to " + (getDisplayNameForContextType(contextType)) + " namespace (" + idNamespace
+ ") and systemId (" + systemId + ").");
}
XMLInputSource result = new XMLInputSource(identifier);
result.setPublicId(idNamespace);
result.setSystemId(systemId);
result.setBaseSystemId(idNamespace + "/" + systemId);
URI namespace;
try {
namespace = new URI(idNamespace);
} catch (URISyntaxException e) {
LOG.error("Problem parsing systemID.", e);
throw new SchemaParsingException("Problem parsing systemID:" + e.getMessage());
}
// first load schema from submission if present
XMLSchema schema = getSchemaFromSchemas(namespace);
// if not in submission load from DB
if (schema == null) {
if (this.schemaDao != null) {
// try {
schema = this.schemaDao.getXMLSchemaByTargetNamespace(namespace);
} else {
LOG.debug("No SchemaPersistence found, and schema wasn't found in submission.");
}
}
// if not in DB error out
if (schema == null) {
SchemaParsingException e = new SchemaParsingException("Unable to resolve reference to Schema (" + namespace
+ " - " + systemId + "); reference not found in submission package, nor as an existing Schema.");
LOG.error(e.getMessage(), e);
throw e;
}
XMLSchemaDocument sd = null;
if (isImport) {
// if it is an import, we need to return the "root" SchemaDocument
// for the namespace
sd = schema.getRootDocument();
} else {
// else, we need to find the SchemaDocument with a matching systemid
// convert schema to InputSource
sd = XSDUtil.getSchemaDocumentFromSchema(schema, systemId);
}
// if not found in schema, error out
if (sd == null) {
SchemaParsingException e = new SchemaParsingException("Unable to resolve reference to SchemaDocument ("
+ namespace + " - " + systemId + "); Schema was located but no matching SchemaDocument was found.");
LOG.error(e.getMessage(), e);
throw e;
}
// load the text from the SchemaDocument
result.setByteStream(new ByteArrayInputStream(sd.getSchemaText().getBytes()));
return result;
}
private String getDisplayNameForContextType(short contextType) {
if (contextType == XMLSchemaDescription.CONTEXT_IMPORT) {
return "import";
} else if (contextType == XMLSchemaDescription.CONTEXT_INCLUDE) {
return "include";
} else if (contextType == XMLSchemaDescription.CONTEXT_REDEFINE) {
return "redifine";
} else {
return "?";
}
}
protected XMLSchema getSchemaFromSchemas(URI namespace) throws SchemaParsingException {
XMLSchema result = null;
if (this.submissionSchemas != null) {
for (XMLSchema schema : this.submissionSchemas) {
if (schema.getTargetNamespace() != null && namespace.equals(schema.getTargetNamespace())) {
LOG.debug("Found desired schema in submission package.");
if (result == null) {
result = schema;
} else {
SchemaParsingException e = new SchemaParsingException(
"Schema submission contains multiple schemas claiming the same namespace(" + namespace
+ ").");
LOG.error(e.getMessage(), e);
throw e;
}
}
}
} else {
LOG.debug("No schemas to search.");
}
return result;
}
}