eu.planets_project.tb.impl.properties.ManuallyMeasuredPropertyHandlerImpl.java Source code

Java tutorial

Introduction

Here is the source code for eu.planets_project.tb.impl.properties.ManuallyMeasuredPropertyHandlerImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2010 The Planets Project Partners.
 *
 * All rights reserved. This program and the accompanying 
 * materials are made available under the terms of the 
 * Apache License, Version 2.0 which accompanies 
 * this distribution, and is available at 
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *******************************************************************************/
/**
 * 
 */
package eu.planets_project.tb.impl.properties;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import eu.planets_project.ifr.core.storage.api.DataRegistry;
import eu.planets_project.ifr.core.storage.api.DataRegistryFactory;
import eu.planets_project.services.datatypes.Content;
import eu.planets_project.services.datatypes.DigitalObject;
import eu.planets_project.tb.api.properties.ManuallyMeasuredProperty;

/**
 * This class is responsible mainly for two items:
 * a) adding/removing manual measurement property definitions specific for a given user
 * b) storing and loading a specific set of properties that have been applied to a given experiment
 * 
 *  - importing manual properties which the user defined from the user's space
 *  - adding manual property definitions to the user's space
 *  - creating a new set of manual properties derived from the TB3ontology for a user
 * @author <a href="mailto:andrew.lindley@ait.ac.at">Andrew Lindley</a>
 * @since 23.04.2010
 *
 */
public class ManuallyMeasuredPropertyHandlerImpl {

    //import the data manager where to store user specific information

    private static ManuallyMeasuredPropertyHandlerImpl instance;
    //contains all properties pulled in from the extracted TB3Ontology.xml
    private List<ManuallyMeasuredProperty> TB3ontologyProperties;
    private Log log = LogFactory.getLog(ManuallyMeasuredPropertyHandlerImpl.class);
    private DataRegistry dataRegistry;

    public static synchronized ManuallyMeasuredPropertyHandlerImpl getInstance() {
        if (instance == null) {
            instance = new ManuallyMeasuredPropertyHandlerImpl();
        }
        return instance;
    }

    private ManuallyMeasuredPropertyHandlerImpl() {
        //init the dataRegistry object
        dataRegistry = DataRegistryFactory.getDataRegistry();
        //parse the extractedTB3OntologyProperties.xml
        readManualUserPropertiesFromTB3Ontology();
    }

    private void readManualUserPropertiesFromTB3Ontology() {
        try {
            log.info(
                    "start readingManualUserPropertiesFromTB3Ontology from eu/planets_project/tb/impl/extractedTB3OntologyProperties.xml");
            DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dbfactory.newDocumentBuilder();
            java.io.InputStream TB3OntologyXML = getClass().getClassLoader()
                    .getResourceAsStream("eu/planets_project/tb/impl/extractedTB3OntologyProperties.xml");
            Document doc = builder.parse(TB3OntologyXML);
            Element root = doc.getDocumentElement();

            //read the properties from the xml-file
            TB3ontologyProperties = parseManualPropertiesXML(root, false);

            TB3OntologyXML.close();
            log.info("finished readingManualUserPropertiesFromTB3Ontology. imported: "
                    + TB3ontologyProperties.size() + " elements");

        } catch (Exception e) {
            log.debug("start readingManualUserPropertiesFromTB3Ontology failed " + e);
        }
    }

    private List<ManuallyMeasuredProperty> parseManualPropertiesXML(Element root, boolean bUserCreated) {
        List<ManuallyMeasuredProperty> ret = new ArrayList<ManuallyMeasuredProperty>();
        NodeList nProperties = root.getChildNodes();
        for (int i = 0; i < nProperties.getLength(); i++) {
            Node nProperty = nProperties.item(i);
            if (nProperty.getNodeName().equals("property")) {

                //now iterate over its children to extract name and description
                NodeList nPropChilds = nProperty.getChildNodes();
                String name = null, description = null, tburi = null;
                for (int j = 0; j < nPropChilds.getLength(); j++) {
                    Node nPropChild = nPropChilds.item(j);
                    if (nPropChild.getNodeName().equals("name")) {
                        name = nPropChild.getTextContent();
                    }
                    if (nPropChild.getNodeName().equals("description")) {
                        description = nPropChild.getTextContent();

                    }
                }
                NamedNodeMap attributes = nProperty.getAttributes();
                if (attributes.getNamedItem("tburi") != null) {
                    tburi = attributes.getNamedItem("tburi").getNodeValue();
                }

                //check if name and description were properly extracted
                if ((name != null) && (description != null) && (tburi != null)) {
                    //now create the ManuallyMeasuredProperty
                    ret.add(new ManuallyMeasuredPropertyImpl(name, description, tburi, bUserCreated));
                    log.debug("added propery: " + name + " " + tburi);
                } else {
                    log.debug("error creating ManuallyMeasuredProperty for property item nr: " + i);
                }
            }
        }
        return ret;
    }

    /**
     * A static utility method to create (!=store) ManuallyMeasuredProperties for a given user
     * @param userName
     * @param pName
     * @param pDescription
     * @return
     */
    public static ManuallyMeasuredProperty createUserProperty(String userName, String pName, String pDescription) {
        // FIXME This should escape problematic characters, like spaces.
        String uri = "planets://testbed/properties/" + userName + "/" + pName;
        ManuallyMeasuredProperty ret = new ManuallyMeasuredPropertyImpl(pName, pDescription, uri, true);
        return ret;
    }

    /**
     * Returns a merged list of TB3ontology + user defined manually measured properties
     */
    public List<ManuallyMeasuredProperty> loadAllManualProperties(String user) {
        List<ManuallyMeasuredProperty> ret = new ArrayList<ManuallyMeasuredProperty>();
        ret.addAll(this.loadAllOntologyDerivedManualProperties());
        ret.addAll(this.loadAllUserDefinedManualProperties(user));
        return ret;
    }

    /**
     * Loads all property definitions which are stored as XML in the user's storage area
     * @return
     */
    public List<ManuallyMeasuredProperty> loadAllUserDefinedManualProperties(String userName) {
        log.info("loading all manually defined user properties for: " + userName);
        List<ManuallyMeasuredProperty> ret = new ArrayList<ManuallyMeasuredProperty>();

        try {
            URI drManagerID = DataRegistryFactory
                    .createDataRegistryIdFromName("/experiment-files/testbed/users/" + userName).normalize();
            URI storageURI = new URI(drManagerID.getScheme(), drManagerID.getAuthority(),
                    drManagerID.getPath() + "/config/userproperties.xml", null, null).normalize();

            //retrieve the user specific properties xml file from his storage space
            DigitalObject digoUserProps = dataRegistry.getDigitalObjectManager(drManagerID).retrieve(storageURI);

            //parse the XML and extract the Properties
            DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dbfactory.newDocumentBuilder();
            java.io.InputStream userDefinedPropsXML = digoUserProps.getContent().getInputStream();
            Document doc = builder.parse(userDefinedPropsXML);
            Element root = doc.getDocumentElement();

            //read the properties from the xml-file
            ret = parseManualPropertiesXML(root, true);

            userDefinedPropsXML.close();

            log.info("successfully extracted " + ret.size() + " manual property definitions for user: " + userName);
            return ret;

        } catch (Exception e) {
            log.debug("unable to retrieve user specific manual properties definitions for: " + userName + " " + e);
            return ret;
        }
    }

    /**
     * Returns only the list of properties - i.e. excludes the user created ones.
     */
    public List<ManuallyMeasuredProperty> loadAllOntologyDerivedManualProperties() {
        return this.TB3ontologyProperties;
    }

    /**
     * Creates and adds a ManuallyMeasuredProperty to the user's list of ManuallyMeasuredProperties.
     * @param userName
     * @param pName
     * @param pDescription
     */
    public void addManualUserProperty(String userName, String pName, String pDescription) {
        ManuallyMeasuredProperty mp = createUserProperty(userName, pName, pDescription);
        this.addManualUserProperty(userName, mp);
    }

    /**
     * Adds a ManuallyMeasuredProperty to the user's list of ManuallyMeasuredProperties.
     * @param userName
     * @param p
     */
    public void addManualUserProperty(String userName, ManuallyMeasuredProperty p) {

        try {
            //0. check if the xml digital object containing this information is in place already
            if (!isUserPropConfigDigoExisting(userName)) {
                createAndStoreEmptyUserConfigDigo(userName);
            }
            //1. parse the xml containing the user defined property definitions
            List<ManuallyMeasuredProperty> userProps = this.loadAllUserDefinedManualProperties(userName);

            //2. add new property and write back to disk
            if (userProps.contains(p)) {
                log.info("user property already contained - updating definition");
                //in this case we're updating
                userProps.remove(p);
                userProps.add(p);

            } else {
                userProps.add(p);
                log.info("added user property: " + p.toString() + "overall user created properties: "
                        + userProps.size());
            }

            //3. call update on the file to persist the user's configuration
            updateUserConfigProps(userName, userProps);

        } catch (Exception e) {
            log.debug("was not able to add manual user property for user: " + userName + " " + e);
        }
    }

    /**
     * removes a specific property from the user's config space for manual properties
     * @param userName
     * @param p
     */
    public void removeManualUserProperty(String userName, ManuallyMeasuredProperty p) {
        try {
            //0. check if the xml digital object containing this information is in place already
            if (!isUserPropConfigDigoExisting(userName)) {
                createAndStoreEmptyUserConfigDigo(userName);
            }
            //1. parse the xml containing the user defined property definitions
            List<ManuallyMeasuredProperty> userProps = this.loadAllUserDefinedManualProperties(userName);

            //2. add new property and write back to disk
            if (userProps.contains(p)) {
                userProps.remove(p);
                log.info("removed user property " + p.toString() + "overall user available user properties: "
                        + userProps.size());
            } else {
                log.info("requested property for removal did not exist in user space");
            }

            //3. call update on the file to persist the user's configuration
            updateUserConfigProps(userName, userProps);

        } catch (Exception e) {
            log.debug("was not able to remove manual user property for user: " + userName + " " + e);
        }
    }

    /**
     * removes a specific property from the user's config space for manual properties
     * @param userName
     * @param name property name or URI
     */
    public void removeManualUserProperty(String userName, String name) {
        //check if name or uri, when uri extract the proeprty's name from it
        if ((name != null) && (userName != null)) {
            if (name.lastIndexOf("/") != -1) {
                name = name.substring(name.lastIndexOf("/") + 1);
            }
            ManuallyMeasuredProperty p = ManuallyMeasuredPropertyHandlerImpl.createUserProperty(userName, name,
                    null);
            this.removeManualUserProperty(userName, p);
        }
    }

    /**
     * removes all user created properties from his config space for manual properties
     * @param userName
     */
    public void removeAllManualUserProperties(String userName) {
        try {
            //0. check if the xml digital object containing this information is in place already
            if (!isUserPropConfigDigoExisting(userName)) {
                createAndStoreEmptyUserConfigDigo(userName);
            }
            //1. create a new empty list
            List<ManuallyMeasuredProperty> userProps = new ArrayList<ManuallyMeasuredProperty>();

            //3. call update on the file to persist the user's configuration
            updateUserConfigProps(userName, userProps);

        } catch (Exception e) {
            log.debug("was not able to remove all manual user properties for user: " + userName + " " + e);
        }
    }

    /**
     * Checks if we can access the digital object containing the user's manual property definitions
     * @param userName
     * @return
     */
    private boolean isUserPropConfigDigoExisting(String userName) {
        try {
            URI drManagerID = DataRegistryFactory
                    .createDataRegistryIdFromName("/experiment-files/testbed/users/" + userName).normalize();
            URI storageURI = new URI(drManagerID.getScheme(), drManagerID.getAuthority(),
                    drManagerID.getPath() + "/config/userproperties.xml", null, null).normalize();
            //retrieve the user specific properties xml file from his storage space
            dataRegistry.getDigitalObjectManager(drManagerID).retrieve(storageURI);
            return true;
        } catch (Exception e) {
            //we need to create the user's digital object containing his manual properties
            return false;
        }
    }

    /**
     * Creates a digital object for storing a user's manual properties
     * in the user's config path and returns the digo's data manager URI
     * @param userName
     * @return
     */
    private URI createAndStoreEmptyUserConfigDigo(String userName) throws Exception {

        URI drManagerID = DataRegistryFactory
                .createDataRegistryIdFromName("/experiment-files/testbed/users/" + userName).normalize();
        URI storageURI = new URI(drManagerID.getScheme(), drManagerID.getAuthority(),
                drManagerID.getPath() + "/config/userproperties.xml", null, null).normalize();

        //Create temp file.
        File temp = File.createTempFile("userproperties", ".xml");
        //create and store the digital object
        DigitalObject userpropertiesXML = new DigitalObject.Builder(Content.byValue(temp)).title("userproperties")
                .build();
        URI uriStored = dataRegistry.getDigitalObjectManager(drManagerID).storeAsNew(storageURI, userpropertiesXML);
        temp.delete();
        log.info("created storage space for user defined manual properties");
        return uriStored;
    }

    /**
     * Takes a list of user defined properties and writes them back to the user config space using
     * the update operation on the digital object manager
     * @param userName
     * @param lProps
     */
    private void updateUserConfigProps(String userName, List<ManuallyMeasuredProperty> lProps) throws Exception {
        URI drManagerID = DataRegistryFactory
                .createDataRegistryIdFromName("/experiment-files/testbed/users/" + userName).normalize();
        URI storageURI = new URI(drManagerID.getScheme(), drManagerID.getAuthority(),
                drManagerID.getPath() + "/config/userproperties.xml", null, null).normalize();

        //Create temp file, build and write xml content to file
        File temp = File.createTempFile("userproperties", ".xml");
        BufferedWriter writer = new BufferedWriter(new FileWriter(temp));
        writer.write("<userDefinedProperties>\n");
        for (ManuallyMeasuredProperty p : lProps) {
            writer.write("<property tburi=\"" + p.getURI() + "\">\n");
            writer.write("<name>" + p.getName() + "</name>\n");
            writer.write("<description>" + p.getDescription() + "</description>\n");
            writer.write("</property>\n");
        }
        writer.write("</userDefinedProperties>");
        writer.close();

        //build a digital object
        DigitalObject digoManualProps = new DigitalObject.Builder(Content.byValue(temp)).title("userproperties")
                .build();
        //call update on the digital object manager
        dataRegistry.getDigitalObjectManager(drManagerID).updateExisting(storageURI, digoManualProps);
        temp.delete();
        log.info("updated storage space for user defined manual properties");
    }

}