/**
* File: $HeadURL: https://hdt-java.googlecode.com/svn/trunk/hdt-jena/src/org/rdfhdt/hdtjena/NodeDictionary.java $
* Revision: $Rev: 197 $
* Last modified: $Date: 2013-04-12 19:39:33 +0100 (vie, 12 abr 2013) $
* Last modified by: $Author: mario.arias $
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Contacting the authors:
* Mario Arias: mario.arias@deri.org
* Javier D. Fernandez: jfergar@infor.uva.es
* Miguel A. Martinez-Prieto: migumar2@infor.uva.es
*/
package org.rdfhdt.hdtjena;
import java.util.Map;
import org.apache.jena.datatypes.RDFDatatype;
import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.datatypes.xsd.impl.RDFLangString;
import org.apache.jena.graph.JenaNodeCreator;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.Query;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.ARQConstants;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.engine.ExecutionContext;
import org.rdfhdt.hdt.dictionary.Dictionary;
import org.rdfhdt.hdt.enums.TripleComponentRole;
import org.rdfhdt.hdt.triples.TripleID;
import org.rdfhdt.hdtjena.bindings.HDTId;
import org.rdfhdt.hdtjena.cache.DictionaryCache;
import org.rdfhdt.hdtjena.cache.DictionaryCacheArray;
import org.rdfhdt.hdtjena.cache.DictionaryCacheLRI;
import org.rdfhdt.hdtjena.cache.DummyMap;
/**
* Wraps all operations from ids to Nodes and vice versa using an HDT Dictionary.
*
* @author mario.arias
*
*/
public class NodeDictionary {
private final Dictionary dictionary;
private final DictionaryCache[] cacheIDtoNode = new DictionaryCache[TripleComponentRole.values().length];
@SuppressWarnings("unchecked")
Map<String, Integer>[] cacheNodeToId = new Map[TripleComponentRole.values().length];
public NodeDictionary(Dictionary dictionary) {
this.dictionary = dictionary;
// ID TO NODE
final int idToNodeSize = 20000;
if(dictionary.getNsubjects()>idToNodeSize) {
cacheIDtoNode[0] = new DictionaryCacheLRI(idToNodeSize);
} else {
cacheIDtoNode[0] = new DictionaryCacheArray((int) dictionary.getNsubjects());
}
if(dictionary.getNpredicates()>idToNodeSize) {
cacheIDtoNode[1] = new DictionaryCacheLRI(idToNodeSize);
} else {
cacheIDtoNode[1] = new DictionaryCacheArray((int) dictionary.getNpredicates());
}
if(dictionary.getNobjects()>idToNodeSize) {
cacheIDtoNode[2] = new DictionaryCacheLRI(idToNodeSize);
} else {
cacheIDtoNode[2] = new DictionaryCacheArray((int) dictionary.getNobjects());
}
// NODE TO ID
// Disabled, it does not make so much impact.
cacheNodeToId[0] = new DummyMap<String, Integer>();
cacheNodeToId[1] = new DummyMap<String, Integer>();
cacheNodeToId[2] = new DummyMap<String, Integer>();
// final int nodeToIDSize = 1000;
//
// cacheNodeToId[0] = new LRUCache<String, Integer>(nodeToIDSize);
// if(dictionary.getNpredicates()>nodeToIDSize) {
// System.out.println("Predicates LRU");
// cacheNodeToId[1] = new LRUCache<String, Integer>(nodeToIDSize);
// } else {
// System.out.println("Predicates Map");
// cacheNodeToId[1] = new ConcurrentHashMap<String, Integer>((int) dictionary.getNpredicates());
// }
// cacheNodeToId[2] = new LRUCache<String, Integer>(nodeToIDSize);
}
public Node getNode(HDTId hdtid) {
return getNode(hdtid.getId(), hdtid.getRole());
}
public Node getNode(int id, TripleComponentRole role) {
Node node = cacheIDtoNode[role.ordinal()].get(id);
if(node==null) {
CharSequence str = dictionary.idToString(id, role);
char firstChar = str.charAt(0);
if(firstChar=='_') {
node = JenaNodeCreator.createAnon(str);
} else if(firstChar=='"') {
node = JenaNodeCreator.createLiteral(str);
} else {
node = JenaNodeCreator.createURI(str);
}
cacheIDtoNode[role.ordinal()].put(id, node);
}
return node;
}
public int getIntID(Node node, TripleComponentRole role) {
return getIntID(nodeToStr(node), role);
}
public int getIntID(Node node, PrefixMapping map, TripleComponentRole role) {
return getIntID(nodeToStr(node, map), role);
}
public int getIntID(String str, TripleComponentRole role) {
Integer intValue = cacheNodeToId[role.ordinal()].get(str);
if(intValue!=null) {
return intValue.intValue();
}
int val = dictionary.stringToId(str, role);
cacheNodeToId[role.ordinal()].put(str, val);
return val;
}
public static String nodeToStr(Node node, PrefixMapping map) {
if(node.isURI()) {
return map.expandPrefix(node.getURI());
} else {
return nodeToStr(node);
}
}
public static String nodeToStr(Node node) {
if(node==null || node.isVariable()) {
return "";
}else if(node.isURI()) {
return node.getURI();
} else if(node.isLiteral()) {
RDFDatatype t = node.getLiteralDatatype();
if(t==null || XSDDatatype.XSDstring.getURI().equals(t.getURI())) {
// String
return "\""+node.getLiteralLexicalForm()+"\"";
} else if(RDFLangString.rdfLangString.equals(t)) {
// Lang
return "\""+node.getLiteralLexicalForm()+"\"@"+node.getLiteralLanguage();
} else {
// Typed
return "\""+node.getLiteralLexicalForm()+"\"^^<"+t.getURI()+">";
}
} else {
return node.toString();
}
}
public TripleID getTripleID(Triple triple, PrefixMapping map) {
return new TripleID(
getIntID(nodeToStr(triple.getSubject(), map), TripleComponentRole.SUBJECT),
getIntID(nodeToStr(triple.getPredicate(), map), TripleComponentRole.PREDICATE),
getIntID(nodeToStr(triple.getObject(), map), TripleComponentRole.OBJECT)
);
}
public TripleID getTriplePatID(Triple jenaTriple) {
int subject=0, predicate=0, object=0;
if(jenaTriple.getMatchSubject()!=null) {
subject = getIntID(jenaTriple.getMatchSubject(), TripleComponentRole.SUBJECT);
}
if(jenaTriple.getMatchPredicate()!=null) {
predicate = getIntID(jenaTriple.getMatchPredicate(), TripleComponentRole.PREDICATE);
}
if(jenaTriple.getMatchObject()!=null) {
object = getIntID(jenaTriple.getMatchObject(), TripleComponentRole.OBJECT);
}
return new TripleID(subject, predicate, object);
}
public static PrefixMapping getMapping(ExecutionContext ctx) {
Query query = (Query) ctx.getContext().get(ARQConstants.sysCurrentQuery);
return query.getPrefixMapping();
}
public static final Var asVar(Node node)
{
if ( Var.isVar(node) )
return Var.alloc(node) ;
return null ;
}
public static int translate(NodeDictionary dictionary, HDTId id, TripleComponentRole role) {
if(dictionary==id.getDictionary()) {
return id.getValue();
}
NodeDictionary dict2 = id.getDictionary();
CharSequence str = dict2.dictionary.idToString(id.getValue(), id.getRole());
return dictionary.getIntID(str.toString(), role);
}
}