/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.utilities;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import fedora.common.Constants;
import fedora.common.rdf.RDFName;
import fedora.server.errors.ObjectIntegrityException;
import fedora.server.errors.RepositoryConfigurationException;
import fedora.server.errors.StreamIOException;
import javax.xml.XMLConstants;
/**
* Dublin Core Fields.
*
* @author Chris Wilper
* @version $Id$
*/
public class DCFields
extends DefaultHandler
implements Constants {
private final ArrayList<DCField> m_titles = new ArrayList<DCField>();
private final ArrayList<DCField> m_creators = new ArrayList<DCField>();
private final ArrayList<DCField> m_subjects = new ArrayList<DCField>();
private final ArrayList<DCField> m_descriptions = new ArrayList<DCField>();
private final ArrayList<DCField> m_publishers = new ArrayList<DCField>();
private final ArrayList<DCField> m_contributors = new ArrayList<DCField>();
private final ArrayList<DCField> m_dates = new ArrayList<DCField>();
private final ArrayList<DCField> m_types = new ArrayList<DCField>();
private final ArrayList<DCField> m_formats = new ArrayList<DCField>();
private final ArrayList<DCField> m_identifiers = new ArrayList<DCField>();
private final ArrayList<DCField> m_sources = new ArrayList<DCField>();
private final ArrayList<DCField> m_languages = new ArrayList<DCField>();
private final ArrayList<DCField> m_relations = new ArrayList<DCField>();
private final ArrayList<DCField> m_coverages = new ArrayList<DCField>();
private final ArrayList<DCField> m_rights = new ArrayList<DCField>();
private StringBuffer m_currentContent;
private String m_lang;
public DCFields() {}
public DCFields(InputStream in)
throws RepositoryConfigurationException, ObjectIntegrityException,
StreamIOException {
SAXParser parser = null;
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
parser = spf.newSAXParser();
} catch (Exception e) {
throw new RepositoryConfigurationException("Error getting SAX "
+ "parser for DC metadata: " + e.getClass().getName()
+ ": " + e.getMessage());
}
try {
parser.parse(in, this);
} catch (SAXException saxe) {
throw new ObjectIntegrityException("Parse error parsing DC XML Metadata: "
+ saxe.getMessage());
} catch (IOException ioe) {
throw new StreamIOException("Stream error parsing DC XML Metadata: "
+ ioe.getMessage());
}
}
@Override
public void startElement(String uri,
String localName,
String qName,
Attributes attrs) {
m_currentContent = new StringBuffer();
m_lang = attrs.getValue(XMLConstants.XML_NS_URI, "lang");
}
@Override
public void characters(char[] ch, int start, int length) {
m_currentContent.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) {
if (localName.equals("title")) {
titles().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("creator")) {
creators().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("subject")) {
subjects().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("description")) {
descriptions().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("publisher")) {
publishers().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("contributor")) {
contributors().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("date")) {
dates().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("type")) {
types().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("format")) {
formats().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("identifier")) {
identifiers().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("source")) {
sources().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("language")) {
languages().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("relation")) {
relations().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("coverage")) {
coverages().add(new DCField(m_currentContent.toString().trim(), m_lang));
} else if (localName.equals("rights")) {
rights().add(new DCField(m_currentContent.toString().trim(), m_lang));
}
}
/**
* Returns a Map with RDFName keys, each value containing List of String
* values for that field.
*/
public Map<RDFName, List<DCField>> getMap() {
Map<RDFName, List<DCField>> map = new HashMap<RDFName, List<DCField>>();
map.put(DC.TITLE, m_titles);
map.put(DC.CREATOR, m_creators);
map.put(DC.SUBJECT, m_subjects);
map.put(DC.DESCRIPTION, m_descriptions);
map.put(DC.PUBLISHER, m_publishers);
map.put(DC.CONTRIBUTOR, m_contributors);
map.put(DC.DATE, m_dates);
map.put(DC.TYPE, m_types);
map.put(DC.FORMAT, m_formats);
map.put(DC.IDENTIFIER, m_identifiers);
map.put(DC.SOURCE, m_sources);
map.put(DC.LANGUAGE, m_languages);
map.put(DC.RELATION, m_relations);
map.put(DC.COVERAGE, m_coverages);
map.put(DC.RIGHTS, m_rights);
return map;
}
public List<DCField> titles() {
return m_titles;
}
public List<DCField> creators() {
return m_creators;
}
public List<DCField> subjects() {
return m_subjects;
}
public List<DCField> descriptions() {
return m_descriptions;
}
public List<DCField> publishers() {
return m_publishers;
}
public List<DCField> contributors() {
return m_contributors;
}
public List<DCField> dates() {
return m_dates;
}
public List<DCField> types() {
return m_types;
}
public List<DCField> formats() {
return m_formats;
}
public List<DCField> identifiers() {
return m_identifiers;
}
public List<DCField> sources() {
return m_sources;
}
public List<DCField> languages() {
return m_languages;
}
public List<DCField> relations() {
return m_relations;
}
public List<DCField> coverages() {
return m_coverages;
}
public List<DCField> rights() {
return m_rights;
}
/**
* Get the DCFields as a String in namespace-qualified XML form, matching
* the oai_dc schema.... but without the xml declaration.
*/
public String getAsXML() {
StringBuffer out = new StringBuffer();
out.append("<" + OAI_DC.prefix + ":dc" + " xmlns:" + OAI_DC.prefix
+ "=\"" + OAI_DC.uri + "\"" + "\nxmlns:" + DC.prefix + "=\""
+ DC.uri + "\"\nxmlns:xsi=\"" + XSI.uri
+ "\"\nxsi:schemaLocation=\"" + OAI_DC.uri + " "
+ OAI_DC2_0.xsdLocation + "\">\n");
appendXML(titles(), "title", out);
appendXML(creators(), "creator", out);
appendXML(subjects(), "subject", out);
appendXML(descriptions(), "description", out);
appendXML(publishers(), "publisher", out);
appendXML(contributors(), "contributor", out);
appendXML(dates(), "date", out);
appendXML(types(), "type", out);
appendXML(formats(), "format", out);
appendXML(identifiers(), "identifier", out);
appendXML(sources(), "source", out);
appendXML(languages(), "language", out);
appendXML(relations(), "relation", out);
appendXML(coverages(), "coverage", out);
appendXML(rights(), "rights", out);
out.append("</oai_dc:dc>\n");
return out.toString();
}
private void appendXML(List<DCField> values, String name, StringBuffer out) {
for (DCField field : values) {
out.append(" <dc:" + name);
if (field.getLang() != null) {
out.append(" xml:lang=\"" + field.getLang() + "\"");
}
out.append(">");
out.append(StreamUtility.enc(field.getValue()));
out.append("</dc:" + name + ">\n");
}
}
}