All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dspace.content.crosswalk.XHTMLHeadDisseminationCrosswalk Maven / Gradle / Ivy

There is a newer version: 8.0
Show newest version
/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.content.crosswalk;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.content.MetadataValue;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.SelfNamedPlugin;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Verifier;

/**
 * Crosswalk for creating appropriate <meta> elements to appear in the
 * item display page for a particular item, for improving automated processing
 * of the page (e.g. by search engines). The metadata included should be as rich
 * yet standards-compliant as possible.
 * 

* The configuration file * ${dspace.dir}/config/xhtml-head-item.properties contains the * relevant mappings. Note: where there is a custom qualifier for which no * corresponding mapping exists, the crosswalk will remove the qualifier and try * again with just the element. *

* e.g. if a field exists in the database "dc.contributor.editor", and there is * no dc.contributor.editor property below, the mapping for "dc.contributor" * will be used. If an element in the item metadata record does not appear in * the configuration, it is simply ignored; the emphasis here is on exposing * standards-compliant metadata. *

* TODO: This may usefully be extended later to work with communities and * collections. * * @author Robert Tansley */ public class XHTMLHeadDisseminationCrosswalk extends SelfNamedPlugin implements DisseminationCrosswalk { /** * log4j logger */ private static final Logger log = LogManager.getLogger(XHTMLHeadDisseminationCrosswalk.class); private static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; protected final ItemService itemService = ContentServiceFactory.getInstance().getItemService(); protected final ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); /** * Location of configuration file */ private final String config = configurationService.getProperty("dspace.dir") + File.separator + "config" + File.separator + "crosswalks" + File.separator + "xhtml-head-item.properties"; /** * Maps DSpace metadata field to name to use in XHTML head element, e.g. * dc.creator or dc.description.abstract */ private Map names; /** * Maps DSpace metadata field to scheme for that field, if any */ private Map schemes; /** * Schemas to add -- maps schema.NAME to schema URL */ private Map schemaURLs; public XHTMLHeadDisseminationCrosswalk() throws IOException { names = new HashMap<>(); schemes = new HashMap<>(); schemaURLs = new HashMap<>(); // Read in configuration Properties crosswalkProps = new Properties(); FileInputStream fis = new FileInputStream(config); try { crosswalkProps.load(fis); } finally { if (fis != null) { try { fis.close(); } catch (IOException ioe) { // ignore } } } Enumeration e = crosswalkProps.keys(); while (e.hasMoreElements()) { String prop = (String) e.nextElement(); if (prop.startsWith("schema.")) { schemaURLs.put(prop, crosswalkProps.getProperty(prop)); } else { String[] s = ((String) crosswalkProps.get(prop)).split(","); if (s.length == 2) { schemes.put(prop, s[1]); } if (s.length == 1 || s.length == 2) { names.put(prop, s[0]); } else { log.warn("Malformed parameter " + prop + " in " + config); } } } } @Override public boolean canDisseminate(DSpaceObject dso) { return (dso.getType() == Constants.ITEM); } /** * This generates a <head> element around the metadata; in general * this will probably not be used * * @param context context * @throws CrosswalkException crosswalk error * @throws IOException if IO error * @throws SQLException if database error * @throws AuthorizeException if authorization error */ @Override public Element disseminateElement(Context context, DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException { Element head = new Element("head", XHTML_NAMESPACE); head.addContent(disseminateList(context, dso)); return head; } /** * Return <meta> elements that can be put in the <head> element * of an XHTML document. * * @param context context * @throws CrosswalkException crosswalk error * @throws IOException if IO error * @throws SQLException if database error * @throws AuthorizeException if authorization error */ @Override public List disseminateList(Context context, DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException { if (dso.getType() != Constants.ITEM) { String h = dso.getHandle(); throw new CrosswalkObjectNotSupported( "Can only support items; object passed in with DB ID " + dso.getID() + ", type " + Constants.typeText[dso.getType()] + ", handle " + (h == null ? "null" : h)); } Item item = (Item) dso; String handle = item.getHandle(); List metas = new ArrayList<>(); List values = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY); // Add in schema URLs e.g. Iterator schemaIterator = schemaURLs.keySet().iterator(); while (schemaIterator.hasNext()) { String s = schemaIterator.next(); Element e = new Element("link", XHTML_NAMESPACE); e.setAttribute("rel", s); e.setAttribute("href", schemaURLs.get(s)); metas.add(e); } for (int i = 0; i < values.size(); i++) { MetadataValue v = values.get(i); MetadataField metadataField = v.getMetadataField(); MetadataSchema metadataSchema = metadataField.getMetadataSchema(); // Work out the key for the Maps that will tell us which metadata // name + scheme to use String key = metadataSchema.getName() + "." + metadataField.getElement() + (metadataField.getQualifier() != null ? "." + metadataField.getQualifier() : ""); String originalKey = key; // For later error msg // Find appropriate metadata field name to put in element String name = names.get(key); // If we don't have a field, try removing qualifier if (name == null && metadataField.getQualifier() != null) { key = metadataSchema.getName() + "." + metadataField.getElement(); name = names.get(key); } // Do not include description.provenance boolean provenance = "description".equals(metadataField.getElement()) && "provenance" .equals(metadataField.getQualifier()); if (name == null) { // Most of the time, in this crosswalk, an unrecognised // element is OK, so just report at DEBUG level if (log.isDebugEnabled()) { log.debug("No field for item " + (handle == null ? String.valueOf(dso.getID()) : handle) + " field " + originalKey); } } else if (!provenance) { Element e = new Element("meta", XHTML_NAMESPACE); e.setAttribute("name", name); if (v.getValue() == null) { e.setAttribute("content", ""); } else { // Check that we can output the content String reason = Verifier.checkCharacterData(v.getValue()); if (reason == null) { // TODO: Check valid encoding? We assume UTF-8 // TODO: Check escaping "<>& e.setAttribute("content", v.getValue()); } else { // Warn that we found invalid characters log.warn("Invalid attribute characters in Metadata: " + reason); // Strip any characters that we can, and if the result is valid, output it String simpleText = v.getValue().replaceAll("\\p{Cntrl}", ""); if (Verifier.checkCharacterData(simpleText) == null) { e.setAttribute("content", simpleText); } } } if (v.getLanguage() != null && !v.getLanguage().equals("")) { e.setAttribute("lang", v.getLanguage(), Namespace.XML_NAMESPACE); } String schemeAttr = schemes.get(key); if (schemeAttr != null) { e.setAttribute("scheme", schemeAttr); } metas.add(e); } } return metas; } @Override public Namespace[] getNamespaces() { return new Namespace[] {Namespace.getNamespace(XHTML_NAMESPACE)}; } @Override public String getSchemaLocation() { return ""; } @Override public boolean preferList() { return true; } // Plugin Methods public static String[] getPluginNames() { return new String[] {"XHTML_HEAD_ITEM"}; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy