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

com.bigdata.bop.solutions.IVComparator Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

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; version 2 of the License.

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/* Portions Copyright Aduna (http://www.aduna-software.com/) (c) 2007.
 *
 * Licensed under the Aduna BSD-style license.
 */
/*
 * Created on Aug 8, 2011
 */

package com.bigdata.bop.solutions;

import info.aduna.lang.ObjectUtil;

import java.io.Serializable;
import java.util.Comparator;

import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.datatypes.XMLDatatypeUtil;
import org.openrdf.query.algebra.Compare.CompareOp;
import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException;
import org.openrdf.query.algebra.evaluation.util.QueryEvaluationUtil;
import org.openrdf.query.algebra.evaluation.util.ValueComparator;

import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.impl.bnode.SidIV;
import com.bigdata.rdf.internal.impl.literal.LiteralExtensionIV;
import com.bigdata.rdf.model.BigdataLiteral;

/**
 * A comparator that compares {@link IV}s according the SPARQL value ordering as
 * specified in SPARQL Query
 * Language for RDF. This implementation is based on the openrdf
 * {@link ValueComparator} but has been modified to work with {@link IV}s.
 * 

* Note: {@link SidIV} are blank nodes. However, we order SIDs after normal * blank nodes since they are modeling somewhat different information. * * @author james * @author Arjohn Kampman * @author Bryan Thompson * @author Mike Personick * @version $Id$ */ public class IVComparator implements Comparator, Serializable { /** * */ private static final long serialVersionUID = 1L; @SuppressWarnings({ "rawtypes", "unchecked" }) public int compare(final IV o1, final IV o2) { // check equality if (ObjectUtil.nullEquals(o1, o2)) { return 0; } // 1. (Lowest) no value assigned to the variable if (o1 == null) { return -1; } if (o2 == null) { return 1; } // 2. Blank nodes final boolean b1 = o1.isBNode(); final boolean b2 = o2.isBNode(); if (b1 && b2) { return compareBNodes(o1, o2); } if (b1) { return -1; } if (b2) { return 1; } // 2.5 Statement identifiers (SIDs) final boolean s1 = o1.isStatement(); final boolean s2 = o2.isStatement(); if (s1 && s2) { return compareSIDs(o1, o2); } if (s1) { return -1; } if (s2) { return 1; } // 3. IRIs final boolean u1 = o1.isURI(); final boolean u2 = o2.isURI(); if (u1 && u2) { return compareURIs((URI) o1, (URI) o2); } if (u1) { return -1; } if (u2) { return 1; } // 4. RDF literals return compareLiterals((IV) o1, (IV) o2); } /** * Use the natural ordering of the {@link IV}s when they are both blank * nodes. This causes the solutions for the same blank node to be "grouped". * * @see Order the * same Blank Nodes together in ORDER BY */ @SuppressWarnings({ "unchecked", "rawtypes" }) private int compareBNodes(final IV leftBNode, final IV rightBNode) { return leftBNode.compareTo(rightBNode); } /** * Use the natural ordering of the {@link SidIV}s when they are both SIDs * nodes. This causes the solutions for the same {@link SidIV} to be * "grouped". * * @see * Exception when using SPARQL sort & statement identifiers */ @SuppressWarnings({ "unchecked", "rawtypes" }) private int compareSIDs(final IV leftSid, final IV rightSid) { return leftSid.compareTo(rightSid); } /** * Only difference here with Sesame ValueComparator is that we use * stringValue() instead of toString(). */ private int compareURIs(final URI leftURI, final URI rightURI) { return leftURI.stringValue().compareTo(rightURI.stringValue()); } private int compareLiterals( final IV left, final IV right) { /* * Only thing we need to special case are LiteralExtensionIVs, which * are used to model xsd:dateTime. */ if (left instanceof LiteralExtensionIV && right instanceof LiteralExtensionIV) { @SuppressWarnings("rawtypes") final IV leftDatatype = ((LiteralExtensionIV) left).getExtensionIV(); @SuppressWarnings("rawtypes") final IV rightDatatype = ((LiteralExtensionIV) right).getExtensionIV(); if (leftDatatype.equals(rightDatatype)) { return left.compareTo(right); } } return compareLiterals((Literal) left, (Literal) right); } /** * Taken directly from Sesame's ValueComparator, no modification. Handles * inlines nicely since they now implement the Literal interface. */ private int compareLiterals(final Literal leftLit, final Literal rightLit) { // Additional constraint for ORDER BY: "A plain literal is lower // than an RDF literal with type xsd:string of the same lexical // form." if (!QueryEvaluationUtil.isStringLiteral(leftLit) || !QueryEvaluationUtil.isStringLiteral(rightLit)) { try { boolean isSmaller = QueryEvaluationUtil.compareLiterals(leftLit, rightLit, CompareOp.LT); if (isSmaller) { return -1; } else { return 1; } } catch (ValueExprEvaluationException e) { // literals cannot be compared using the '<' operator, continue // below } } int result = 0; // Sort by datatype first, plain literals come before datatyped literals URI leftDatatype = leftLit.getDatatype(); URI rightDatatype = rightLit.getDatatype(); if (leftDatatype != null) { if (rightDatatype != null) { // Both literals have datatypes result = compareDatatypes(leftDatatype, rightDatatype); } else { result = 1; } } else if (rightDatatype != null) { result = -1; } if (result == 0) { // datatypes are equal or both literals are untyped; sort by language // tags, simple literals come before literals with language tags String leftLanguage = leftLit.getLanguage(); String rightLanguage = rightLit.getLanguage(); if (leftLanguage != null) { if (rightLanguage != null) { result = leftLanguage.compareTo(rightLanguage); } else { result = 1; } } else if (rightLanguage != null) { result = -1; } } if (result == 0) { // Literals are equal as fas as their datatypes and language tags are // concerned, compare their labels result = leftLit.getLabel().compareTo(rightLit.getLabel()); } return result; } /** * Taken directly from Sesame's ValueComparator, no modification. */ private int compareDatatypes(final URI leftDatatype, final URI rightDatatype) { if (XMLDatatypeUtil.isNumericDatatype(leftDatatype)) { if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { // both are numeric datatypes return compareURIs(leftDatatype, rightDatatype); } else { return -1; } } else if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) { return 1; } else if (XMLDatatypeUtil.isCalendarDatatype(leftDatatype)) { if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) { // both are calendar datatypes return compareURIs(leftDatatype, rightDatatype); } else { return -1; } } else if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) { return 1; } else { // incompatible or unordered datatypes return compareURIs(leftDatatype, rightDatatype); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy