org.openanzo.rdf.utils.StatementUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.openanzo.rdf.utils.StatementUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * File:        $Source: /cvsroot/slrp/boca/com.ibm.adtech.boca.core/src/com/ibm/adtech/boca/utils/StatementUtils.java,v $
 * Created by:  Matthew Roy ( <a href="mailto:mroy@us.ibm.com">mroy@us.ibm.com </a>)
 * Created on:  Dec 19, 2006
 * Revision:    $Id: StatementUtils.java 168 2007-07-31 14:11:14Z mroy $
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Cambridge Semantics Incorporated - Fork to Anzo
 *******************************************************************************/
package org.openanzo.rdf.utils;

import info.aduna.collections.iterators.Iterators;

import java.util.ArrayList;
import java.util.Collection;

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.collections15.MultiMap;
import org.apache.commons.collections15.multimap.MultiHashMap;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.IDataset;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.Literal;
import org.openanzo.rdf.PlainLiteral;
import org.openanzo.rdf.Resource;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.TypedLiteral;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.openanzo.rdf.query.QueryEncoder;
import org.openanzo.rdf.vocabulary.RDF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Basic utilities for Statements and Literal
 * 
 * @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
 * 
 */
public class StatementUtils {

    private static final Logger log = LoggerFactory.getLogger(StatementUtils.class);

    private static final String containerItemPrefix = RDF.NAMESPACE + "_";

    /**
     * Determine if given statement matches given subject,prop,obj,namedgraph pattern
     * 
     * @param statement
     *            Statement to compare against match parameters
     * @param subj
     *            Subject to match, or null for any
     * @param prop
     *            Predicate to match, or null for any
     * @param obj
     *            Object to match, or null for any
     * @param context
     *            NamedGraph to match, or null for any
     * @return true if statement provided matches the 4 parameters passed
     */
    public static boolean match(Statement statement, Resource subj, org.openanzo.rdf.URI prop, Value obj,
            org.openanzo.rdf.URI context) {
        if (subj == null && prop == null && obj == null && context == null) {
            return true;
        } else {
            if (subj != null && !subj.equals(Constants.ANY_URI) && !subj.equals(statement.getSubject())) {
                return false;
            }
            if (prop != null && !prop.equals(Constants.ANY_URI) && !prop.equals(statement.getPredicate())) {
                return false;
            }
            if (obj != null && !obj.equals(Constants.ANY_URI) && !obj.equals(statement.getObject())) {
                return false;
            }
            if (context != null && !context.equals(Constants.ANY_URI)
                    && !context.equals(statement.getNamedGraphUri())) {
                return false;
            }
            return true;
        }
    }

    /**
     * Try to convert Literal to native object based on datatype
     * 
     * @param literal
     *            Literal to convert
     * @return native value of object based on datatype, or a string containing the literal's label if no conversion exists.
     */
    static public Object getNativeValue(Literal literal) {
        if (literal instanceof PlainLiteral) {
            PlainLiteral pl = (PlainLiteral) literal;
            return pl.getLabel();
        } else {
            TypedLiteral pl = (TypedLiteral) literal;
            return pl.getNativeValue();
        }
    }

    /**
     * Convert an xsd:dateTime Literal to its long representation. Note that xsd:dateTime allows the time zone to be omitted. However, to convert a literal to a
     * millisecond value, requires a time zone. That's because the millisecond long value is supposed to represent an absolute time. that is, milliseconds since
     * January 1, 1970, 00:00:00 GMT. Without a time zone in the xsd:dateTime literal, that number cannot be derived.
     * 
     * Note that this may cause information loss. xsd:dateTime support arbitrary precision fractional seconds. This method reduces the precision to
     * milliseconds.
     * 
     * @param dateTime
     *            xsd:dateTime Literal to convert
     * @return long representation of literal. null if the literal couldn't be parsed into a long such as for lack of a time zone being specified in the
     *         literal.
     */
    protected static Long convertToMilliseconds(TypedLiteral dateTime) {
        Long ret = null;
        Object nativeValue = dateTime.getNativeValue();
        if (nativeValue instanceof XMLGregorianCalendar) {
            XMLGregorianCalendar xmlCal = (XMLGregorianCalendar) nativeValue;
            try {
                if (xmlCal.getXMLSchemaType().equals(DatatypeConstants.DATETIME)
                        && xmlCal.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) {
                    ret = xmlCal.toGregorianCalendar().getTimeInMillis();
                }
            } catch (IllegalStateException e) {
                // XMLGregorianCalendar#getXMLSchemaType() will throw an IllegalStateException if the XMLGregorianCalendar is invalid.
                log.debug(LogUtils.GLITTER_MARKER,
                        "Error parsing dateTime literal into millisecond representation: {}", dateTime.toString());
            }
        }
        return ret;
    }

    /**
     * Convert {@link Constants#ANY_URI} to a null
     * 
     * @param node
     *            Value to convert to null if Constants.ANY_URI
     * @return value or null if equals {@link Constants#ANY_URI}
     */
    public static Value convertUriToAny(Value node) {
        if (node != null && node.equals(Constants.ANY_URI)) {
            return null;
        }
        return node;
    }

    /**
     * Build a string representing this find operation
     * 
     * @param subject
     * @param property
     * @param object
     * @param namedGraphUri
     * @return a string representing this find operation
     */
    public static String buildQueryString(Resource subject, org.openanzo.rdf.URI property, Value object,
            URI... namedGraphUri) {
        String subjectNode = createQueryNodeString(subject, "subject");
        String predicateNode = createQueryNodeString(property, "predicate");
        String objectNode = createQueryNodeString(object, "object");
        StringBuilder query = new StringBuilder("SELECT ");
        query.append("?graph ");
        if (subjectNode.startsWith("?")) {
            query.append(subjectNode + " ");
        }
        if (predicateNode.startsWith("?")) {
            query.append(predicateNode + " ");
        }
        if (objectNode.startsWith("?")) {
            query.append(objectNode + " ");
        }
        if (namedGraphUri != null) {
            for (URI uri : namedGraphUri) {
                query.append(" FROM NAMED " + QueryEncoder.encodeForQuery(uri));
            }
        }
        query.append(" WHERE { GRAPH ");
        query.append(" ?graph ");
        query.append(" {");
        query.append(subjectNode);
        query.append(" ");
        query.append(predicateNode);
        query.append(" ");
        query.append(objectNode);
        query.append(" }}");
        return query.toString();
    }

    private static String createQueryNodeString(Value value, String name) {
        if (value == null || value.equals(Constants.ANY_URI)) {
            return "?" + name + " ";
        }
        return QueryEncoder.encodeForQuery(value);
    }

    /**
     * Get an Collection for the members of the RDFContainer construct provided
     * 
     * @param container
     *            Resource of RDFContainer object
     * @param graph
     *            Graph containing data
     * @return Collection containing data contained within RDFContainer
     * @throws AnzoException
     */
    public static Collection<Value> getContainerMembers(Resource container, INamedGraph graph)
            throws AnzoException {
        ArrayList<Value> statements = new ArrayList<Value>();
        if (graph.contains(container, RDF.TYPE, RDF.ALT) || graph.contains(container, RDF.TYPE, RDF.Bag)
                || graph.contains(container, RDF.TYPE, RDF.Seq)) {
            Collection<Statement> containedStatements = graph.find(container, null, null);
            for (Statement stmt : containedStatements) {
                String predicate = stmt.getPredicate().toString();
                if (predicate.startsWith(containerItemPrefix)) {
                    String val = predicate.substring(containerItemPrefix.length());
                    try {
                        int li = Integer.parseInt(val);
                        statements.add(li, stmt.getObject());
                    } catch (NumberFormatException e) {
                        throw new AnzoException(ExceptionConstants.IO.USER_ENCODE_ERROR, e);
                    }
                }
            }
        }
        return statements;
    }

    /**
     * Get an Collection for the members of the RDFContainer construct provided
     * 
     * @param container
     *            Resource of RDFContainer object
     * @param dataset
     *            Dataset containing data
     * @return Collection containing data contained within RDFContainer
     * @throws AnzoException
     */
    public static Collection<Statement> getContainerMembers(Resource container, IDataset dataset)
            throws AnzoException { // NO_UCD
        ArrayList<Statement> statements = new ArrayList<Statement>();
        if (dataset.contains(container, RDF.TYPE, RDF.ALT) || dataset.contains(container, RDF.TYPE, RDF.Bag)
                || dataset.contains(container, RDF.TYPE, RDF.Seq)) {
            Collection<Statement> containedStatements = dataset.find(container, null, null);
            for (Statement stmt : containedStatements) {
                String predicate = stmt.getPredicate().toString();
                if (predicate.startsWith(containerItemPrefix)) {
                    String val = predicate.substring(containerItemPrefix.length());
                    try {
                        int li = Integer.parseInt(val);
                        statements.add(li, stmt);
                    } catch (NumberFormatException e) {
                        throw new AnzoException(ExceptionConstants.IO.USER_ENCODE_ERROR, e);
                    }
                }
            }
        }
        return statements;
    }

    /**
     * Get an Collection for the members of the RDFList construct provided
     * 
     * @param list
     *            Resource of RDFList object
     * @param graph
     *            Graph containing data
     * @return Collection containing data contained within RDFContainer
     */
    public static Collection<Value> getCollectionMembers(Resource list, INamedGraph graph) {
        ArrayList<Value> statements = new ArrayList<Value>();
        if (graph.contains(list, RDF.first, null) && graph.contains(list, RDF.rest, null)) {
            Collection<Statement> firstStatements = graph.find(list, RDF.first, null);
            if (!firstStatements.isEmpty()) {
                Statement first = firstStatements.iterator().next();
                if (!statements.contains(first.getObject())) {
                    statements.add(first.getObject());
                }
            }

            Collection<Statement> restStatements = graph.find(list, RDF.rest, null);
            if (!restStatements.isEmpty()) {
                Statement rest = restStatements.iterator().next();
                if (!statements.contains(rest.getObject()) && rest.getObject() instanceof Resource) {
                    Iterators.addAll(getCollectionMembers((Resource) rest.getObject(), graph).iterator(),
                            statements);
                }
            }
        }
        return statements;
    }

    /**
     * Get an Collection for the members of the RDFList construct provided
     * 
     * @param list
     *            Resource of RDFList object
     * @param dataset
     *            Dataset containing data
     * @return Collection containing data contained within RDFContainer
     */
    public static MultiMap<URI, Value> getCollectionMembers(Resource list, IDataset dataset) { // NO_UCD
        MultiHashMap<URI, Value> statements = new MultiHashMap<URI, Value>();
        if (dataset.contains(list, RDF.first, null) && dataset.contains(list, RDF.rest, null)) {
            Collection<Statement> firstStatements = dataset.find(list, RDF.first, null);
            if (!firstStatements.isEmpty()) {
                Statement first = firstStatements.iterator().next();
                if (!statements.containsValue(first.getNamedGraphUri(), first.getObject())) {
                    statements.put(first.getNamedGraphUri(), first.getObject());
                }
            }

            Collection<Statement> restStatements = dataset.find(list, RDF.rest, null);
            if (!restStatements.isEmpty()) {
                Statement rest = restStatements.iterator().next();
                if (!statements.containsValue(rest.getNamedGraphUri(), rest.getObject())
                        && rest.getObject() instanceof Resource) {
                    statements.putAll(getCollectionMembers((Resource) rest.getObject(), dataset));
                }
            }
        }
        return statements;
    }
}