com.googlecode.fascinator.redbox.sru.NLAIdentity.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.fascinator.redbox.sru.NLAIdentity.java

Source

/* 
 * The Fascinator - ReDBox/Mint SRU Client - NLA Identity
 * Copyright (C) 2012 Queensland Cyber Infrastructure Foundation (http://www.qcif.edu.au/)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package com.googlecode.fascinator.redbox.sru;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Element;
import org.dom4j.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>A basic wrapper for handling EAC-CPF formatted identities that return for
 * the National Library of Australia. This is neither a complete EAC-CPF handling
 * class, nor a complete implementation of NLA identities. It is just a utility
 * for access the things ReDBox/Mint cares about in common node.</p>
 * 
 * @author Greg Pendlebury
 */
public class NLAIdentity {
    /** Logging **/
    private static Logger log = LoggerFactory.getLogger(NLAIdentity.class);

    /** DOM4J Node for this person **/
    private Node eac;

    /** Properties we extract **/
    private String nlaId;
    private String displayName;
    private String firstName;
    private String surname;
    private String institution;
    private List<Map<String, String>> knownIds;

    /**
     * <p>Default Constructor. Extract some basic information.</p>
     * 
     * @param searchResponse A parsed DOM4J Document
     * @throws SRUException If any of the XML structure does not look like expected
     */
    public NLAIdentity(Node node) throws SRUException {
        eac = node;

        // Identity
        @SuppressWarnings("unchecked")
        List<Node> otherIds = eac.selectNodes("eac:eac-cpf/eac:control/eac:otherRecordId");
        for (Node idNode : otherIds) {
            String otherId = idNode.getText();
            if (otherId.startsWith("http://nla.gov.au")) {
                nlaId = otherId;
            }
        }
        if (nlaId == null) {
            throw new SRUException("Error processing Identity; Cannot find ID");
        }

        knownIds = getSourceIdentities();

        // Cosmetically we want to use the first row (should be the longest top-level name we found)
        firstName = knownIds.get(0).get("firstName");
        surname = knownIds.get(0).get("surname");
        displayName = knownIds.get(0).get("displayName");
        // For institution we want the first one we find that isn't NLA or Libraries Australia
        for (Map<String, String> id : knownIds) {
            if (institution == null
                    // But we'll settle for those in a pinch
                    || "National Library of Australia Party Infrastructure".equals(institution)
                    || "Libraries Australia".equals(institution)) {
                institution = id.get("institution");
            }
        }
    }

    private List<Map<String, String>> getSourceIdentities() {
        List<Map<String, String>> returnList = new ArrayList<Map<String, String>>();

        // Top level institution
        Map<String, String> idMap = new HashMap<String, String>();
        Node institutionNode = eac.selectSingleNode("eac:eac-cpf/eac:control/eac:maintenanceAgency/eac:agencyName");
        String institutionString = institutionNode.getText();
        // Top level name
        Node nlaNamesNode = eac.selectSingleNode("eac:eac-cpf/eac:cpfDescription/eac:identity");
        // Get all the names this ID lists
        List<Map<String, String>> nameList = getNames(nlaNamesNode);
        for (Map<String, String> name : nameList) {
            // Only use the longest top-level name for display purposes
            String oldDisplayName = idMap.get("displayName");
            String thisDisplayName = name.get("displayName");
            if (oldDisplayName == null
                    || (thisDisplayName != null && thisDisplayName.length() > oldDisplayName.length())) {
                // Clear any old data
                idMap.clear();
                // Store this ID
                idMap.putAll(name);
                idMap.put("institution", institutionString);
            }
        }
        // And add to the list
        returnList.add(idMap);

        // All name entities from contributing insitutions
        @SuppressWarnings("unchecked")
        List<Node> sourceIdentities = eac.selectNodes("eac:eac-cpf/eac:cpfDescription//eac:eac-cpf");
        for (Node identity : sourceIdentities) {
            // Insitution for this ID
            institutionNode = identity.selectSingleNode("*//eac:maintenanceAgency/eac:agencyName");
            institutionString = institutionNode.getText();

            // Any names for this ID
            @SuppressWarnings("unchecked")
            List<Node> idNodes = identity.selectNodes("*//eac:identity");
            for (Node idNode : idNodes) {
                // A Map for each name
                idMap = new HashMap<String, String>();
                // Get all the names this ID lists
                nameList = getNames(idNode);
                for (Map<String, String> name : nameList) {
                    idMap.putAll(name);
                }
                // Indicate the insitution for each one
                idMap.put("institution", institutionString);
                // And add to the list
                returnList.add(idMap);
            }
        }

        // Debugging
        //for (Map<String, String> id : returnList) {
        //    String display = id.get("displayName") + " (" + id.get("institution") + ")";
        //    log.debug("Identity: {}", display);
        //}

        return returnList;
    }

    private List<Map<String, String>> getNames(Node node) {
        List<Map<String, String>> nameList = new ArrayList<Map<String, String>>();

        // Any names for this ID
        @SuppressWarnings("unchecked")
        List<Node> names = node.selectNodes("eac:nameEntry");
        for (Node name : names) {
            Map<String, String> nameMap = new HashMap<String, String>();

            String thisDisplay = null;
            String thisFirstName = null;
            String thisSurname = null;
            String title = null;

            // First name
            Node firstNameNode = name
                    .selectSingleNode("eac:part[(@localType=\"forename\") or (@localType=\"givenname\")]");
            if (firstNameNode != null) {
                thisFirstName = firstNameNode.getText();
            }

            // Surname
            Node surnameNode = name
                    .selectSingleNode("eac:part[(@localType=\"surname\") or (@localType=\"familyname\")]");
            if (surnameNode != null) {
                thisSurname = surnameNode.getText();
            }

            // Title
            Node titleNode = name.selectSingleNode("eac:part[@localType=\"title\"]");
            if (titleNode != null) {
                title = titleNode.getText();
            }

            // Display Name
            if (thisSurname != null) {
                thisDisplay = thisSurname;
                nameMap.put("surname", thisSurname);
                if (thisFirstName != null) {
                    thisDisplay += ", " + thisFirstName;
                    nameMap.put("firstName", thisFirstName);
                }
                if (title != null) {
                    thisDisplay += " (" + title + ")";
                }
                nameMap.put("displayName", thisDisplay);
            }

            // Last ditch effort... we couldn't find simple name information from
            //  recommended values. So just concatenate what we can see.
            if (thisDisplay == null) {
                // Find every part
                @SuppressWarnings("unchecked")
                List<Node> parts = name.selectNodes("eac:part");
                for (Node part : parts) {
                    // Grab the value and type of this value
                    Element element = (Element) part;
                    String value = element.getText();
                    String type = element.attributeValue("localType");
                    // Build a display value for this part
                    if (type != null) {
                        value += " (" + type + ")";
                    }
                    // And add to the display name
                    if (thisDisplay == null) {
                        thisDisplay = value;
                    } else {
                        thisDisplay += ", " + value;
                    }
                }
                nameMap.put("displayName", thisDisplay);
            }

            nameList.add(nameMap);
        }

        return nameList;
    }

    /**
     * <p>Getter for the NLA Identifier in use by this Identity.</p>
     * 
     * @return String The ID from the NLA for this Identity
     */
    public String getId() {
        return nlaId;
    }

    /**
     * <p>Getter for our best estimation on a display name for this Identity.</p>
     * 
     * @return String The display name for this Identity
     */
    public String getDisplayName() {
        return displayName;
    }

    /**
     * <p>Getter for the first name for this Identity.</p>
     * 
     * @return String The first name for this Identity
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * <p>Getter for the surname for this Identity.</p>
     * 
     * @return String The surname for this Identity
     */
    public String getSurame() {
        return surname;
    }

    /**
     * <p>Getter for the institution for this Identity.</p>
     * 
     * @return String The institution for this Identity
     */
    public String getInstitution() {
        return institution;
    }

    /**
     * <p>Getter for the List of Identities observed for this person. The return
     * Objects are Maps containing keys very similar to the methods found on the
     * top-level NLAIdentity Object.</p>
     * <ul>
     *   <li>'displayName'</li>
     *   <li>'firstName'</li>
     *   <li>'surname'</li>
     *   <li>'institution'</li>
     * </ul>
     * 
     * @return List<Map<String, String>> A List Object containing identities
     */
    public List<Map<String, String>> getKnownIdentities() {
        return knownIds;
    }

    /**
     * <p>Converts a List of DOM4J Nodes into a List of processed NLAIdentity(s).
     * Individual Nodes that fail to process will be skipped.</p>
     * 
     * @param nodes A List of Nodes to process
     * @return List<NLAIdentity> A List of processed Identities
     */
    public static List<NLAIdentity> convertNodesToIdentities(List<Node> nodes) {
        try {
            return convertNodesToIdentities(nodes, false);
        } catch (SRUException ex) {
            // Will never executre because 'false' is set above,
            // but trapping this here allows users to call this method
            // with greater ease, since they wan't need to trap.
            return null;
        }
    }

    /**
     * <p>Converts a List of DOM4J Nodes into a List of processed NLAIdentity(s).
     * Must indicate whether or not errors should cause processing to halt.</p>
     * 
     * @param nodes A List of Nodes to process
     * @param haltOnErrors Flag if a single Node failing to process should halt execution.
     * @return List<NLAIdentity> A List of processed Identities
     * @throws SRUException If 'haltOnErrors' is set to TRUE and a Node fails to process.
     */
    public static List<NLAIdentity> convertNodesToIdentities(List<Node> nodes, boolean haltOnErrors)
            throws SRUException {
        List<NLAIdentity> response = new ArrayList<NLAIdentity>();
        // Sanity check
        if (nodes == null || nodes.isEmpty()) {
            return response;
        }
        // Process each Node in turn
        for (Node node : nodes) {
            try {
                NLAIdentity newId = new NLAIdentity(node);
                response.add(newId);

                // Only halt if requested
            } catch (SRUException ex) {
                log.error("Unable to process identity: ", ex);
                if (haltOnErrors) {
                    throw ex;
                }
            }
        }
        return response;
    }
}