package org.dspace.administer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.xml.serialize.Method;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.core.Context;
import org.xml.sax.SAXException;
/**
* @author Graham Triggs
*
* This class creates an xml document as passed in the arguments and
* from the metadata schemas for the repository.
*
* The form of the XML is as follows
*
* <metadata-schemas>
* <schema>
* <name>dc</name>
* <namespace>http://dublincore.org/documents/dcmi-terms/</namespace>
* </schema>
* </metadata-schemas>
*/
public class MetadataExporter
{
/**
* @param args
* @throws ParseException
* @throws SAXException
* @throws IOException
* @throws SQLException
* @throws RegistryExportException
*/
public static void main(String[] args) throws ParseException, SQLException, IOException, SAXException, RegistryExportException
{
// create an options object and populate it
CommandLineParser parser = new PosixParser();
Options options = new Options();
options.addOption("f", "file", true, "output xml file for registry");
options.addOption("s", "schema", true, "the name of the schema to export");
CommandLine line = parser.parse(options, args);
String file = null;
String schema = null;
if (line.hasOption('f'))
{
file = line.getOptionValue('f');
}
else
{
usage();
System.exit(0);
}
if (line.hasOption('s'))
{
schema = line.getOptionValue('s');
}
saveRegistry(file, schema);
}
public static void saveRegistry(String file, String schema) throws SQLException, IOException, SAXException, RegistryExportException
{
// create a context
Context context = new Context();
context.setIgnoreAuthorization(true);
OutputFormat xmlFormat = new OutputFormat(Method.XML, "UTF-8", true);
xmlFormat.setLineWidth(120);
xmlFormat.setIndent(4);
XMLSerializer xmlSerializer = new XMLSerializer(new BufferedWriter(new FileWriter(file)), xmlFormat);
// XMLSerializer xmlSerializer = new XMLSerializer(System.out, xmlFormat);
xmlSerializer.startDocument();
xmlSerializer.startElement("dspace-dc-types", null);
// Save the schema defintion(s)
saveSchema(context, xmlSerializer, schema);
MetadataField[] mdFields = null;
// If a single schema has been specified
if (schema != null && !"".equals(schema))
{
// Get the id of that schema
MetadataSchema mdSchema = MetadataSchema.find(context, schema);
if (mdSchema == null)
{
throw new RegistryExportException("no schema to export");
}
// Get the metadata fields only for the specified schema
mdFields = MetadataField.findAllInSchema(context, mdSchema.getSchemaID());
}
else
{
// Get the metadata fields for all the schemas
mdFields = MetadataField.findAll(context);
}
// Output the metadata fields
for (MetadataField mdField : mdFields)
{
saveType(context, xmlSerializer, mdField);
}
xmlSerializer.endElement("dspace-dc-types");
xmlSerializer.endDocument();
// abort the context, as we shouldn't have changed it!!
context.abort();
}
/**
* Serialize the schema registry. If the parameter 'schema' is null or empty, save all schemas
* @param context
* @param xmlSerializer
* @param schema
* @throws SQLException
* @throws SAXException
* @throws RegistryExportException
*/
public static void saveSchema(Context context, XMLSerializer xmlSerializer, String schema) throws SQLException, SAXException, RegistryExportException
{
if (schema != null && !"".equals(schema))
{
// Find a single named schema
MetadataSchema mdSchema = MetadataSchema.find(context, schema);
saveSchema(xmlSerializer, mdSchema);
}
else
{
// Find all schemas
MetadataSchema[] mdSchemas = MetadataSchema.findAll(context);
for (MetadataSchema mdSchema : mdSchemas)
{
saveSchema(xmlSerializer, mdSchema);
}
}
}
/**
* Serialize a single schema (namespace) registry entry
*
* @param xmlSerializer
* @param mdSchema
* @throws SAXException
* @throws RegistryExportException
*/
private static void saveSchema(XMLSerializer xmlSerializer, MetadataSchema mdSchema) throws SAXException, RegistryExportException
{
// If we haven't got a schema, it's an error
if (mdSchema == null)
{
throw new RegistryExportException("no schema to export");
}
String name = mdSchema.getName();
String namespace = mdSchema.getNamespace();
if (name == null || "".equals(name))
{
System.out.println("name is null, skipping");
return;
}
if (namespace == null || "".equals(namespace))
{
System.out.println("namespace is null, skipping");
return;
}
// Output the parent tag
xmlSerializer.startElement("dc-schema", null);
// Output the schema name
xmlSerializer.startElement("name", null);
xmlSerializer.characters(name.toCharArray(), 0, name.length());
xmlSerializer.endElement("name");
// Output the schema namespace
xmlSerializer.startElement("namespace", null);
xmlSerializer.characters(namespace.toCharArray(), 0, namespace.length());
xmlSerializer.endElement("namespace");
xmlSerializer.endElement("dc-schema");
}
/**
* Serialize a single metadata field registry entry to xml
*
* @param context
* @param xmlSerializer
* @param mdField
* @throws SAXException
* @throws RegistryExportException
* @throws SQLException
* @throws IOException
*/
private static void saveType(Context context, XMLSerializer xmlSerializer, MetadataField mdField) throws SAXException, RegistryExportException, SQLException, IOException
{
// If we haven't been given a field, it's an error
if (mdField == null)
{
throw new RegistryExportException("no field to export");
}
// Get the data from the metadata field
String schemaName = getSchemaName(context, mdField);
String element = mdField.getElement();
String qualifier = mdField.getQualifier();
String scopeNote = mdField.getScopeNote();
// We must have a schema and element
if (schemaName == null || element == null)
{
throw new RegistryExportException("incomplete field information");
}
// Output the parent tag
xmlSerializer.startElement("dc-type", null);
// Output the schema name
xmlSerializer.startElement("schema", null);
xmlSerializer.characters(schemaName.toCharArray(), 0, schemaName.length());
xmlSerializer.endElement("schema");
// Output the element
xmlSerializer.startElement("element", null);
xmlSerializer.characters(element.toCharArray(), 0, element.length());
xmlSerializer.endElement("element");
// Output the qualifier, if present
if (qualifier != null)
{
xmlSerializer.startElement("qualifier", null);
xmlSerializer.characters(qualifier.toCharArray(), 0, qualifier.length());
xmlSerializer.endElement("qualifier");
}
else
{
xmlSerializer.comment("unqualified");
}
// Output the scope note, if present
if (scopeNote != null)
{
xmlSerializer.startElement("scope_note", null);
xmlSerializer.characters(scopeNote.toCharArray(), 0, scopeNote.length());
xmlSerializer.endElement("scope_note");
}
else
{
xmlSerializer.comment("no scope note");
}
xmlSerializer.endElement("dc-type");
}
/**
* Helper method to retrieve a schema name for the field.
* Caches the name after looking up the id.
*/
static Map<Integer, String> schemaMap = new HashMap<Integer, String>();
private static String getSchemaName(Context context, MetadataField mdField) throws SQLException, RegistryExportException
{
// Get name from cache
String name = schemaMap.get(new Integer(mdField.getSchemaID()));
if (name == null)
{
// Name not retrieved before, so get the schema now
MetadataSchema mdSchema = MetadataSchema.find(context, mdField.getSchemaID());
if (mdSchema != null)
{
name = mdSchema.getName();
schemaMap.put(new Integer(mdSchema.getSchemaID()), name);
}
else
{
// Can't find the schema
throw new RegistryExportException("Can't get schema name for field");
}
}
return name;
}
/**
* Print the usage message to stdout
*/
public static void usage()
{
String usage = "Use this class with the following options:\n" +
" -f <xml output file> : specify the output file for the schemas\n" +
" -s <schema> : name of the schema to export\n";
System.out.println(usage);
}
}