/******************************************************************************* * 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/query/Attic/BasicNodeConverter.java,v $ * Created by: Lee Feigenbaum (<a href="mailto:feigenbl@us.ibm.com">feigenbl@us.ibm.com</a>) * Created on: 10/27/06 * Revision: $Id: BasicNodeConverter.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.adapter; import java.lang.ref.SoftReference; import java.nio.charset.Charset; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import org.openanzo.exceptions.AnzoRuntimeException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.glitter.exception.GlitterRuntimeException; import org.openanzo.glitter.query.PatternSolution; import org.openanzo.glitter.query.PatternSolutionImpl; import org.openanzo.rdf.Bindable; import org.openanzo.rdf.BlankNode; import org.openanzo.rdf.MemPlainLiteral; import org.openanzo.rdf.MemTypedLiteral; import org.openanzo.rdf.MemURI; import org.openanzo.rdf.MemValueFactory; import org.openanzo.rdf.MemVariable; import org.openanzo.rdf.PlainLiteral; import org.openanzo.rdf.RDFFormat; import org.openanzo.rdf.TriplePatternComponent; import org.openanzo.rdf.TypedLiteral; import org.openanzo.rdf.Value; import org.openanzo.rdf.Variable; import org.openrdf.model.BNode; import org.openrdf.model.Literal; import org.openrdf.model.URI; import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.ValueFactoryImpl; import org.openrdf.query.Binding; import org.openrdf.query.BindingSet; import org.openrdf.query.impl.MapBindingSet; /** * Convert between Anzo and OpenRDF nodes. * * @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>) * */ public class BasicNodeConverter { /** Static RIO valuefactory */ public static final ValueFactory valueFactory = new ValueFactoryImpl(); private final Map<BlankNode, BNode> bnodeMap; /** * Since you can be parsing an extremely large RDF file, you can't cache all values, since it can cause the memory stack to overflow */ private final WeakHashMap<org.openrdf.model.Value, SoftReference<Value>> cachedNodes; /** * Create a new BasicNodeConverter */ public BasicNodeConverter() { this.bnodeMap = new HashMap<BlankNode, BNode>(); this.cachedNodes = new WeakHashMap<org.openrdf.model.Value, SoftReference<Value>>(); } /** * Convert glitter node to Anzo Value * * @param glitterNode * Node to convert * @param blankNodesAsVariables * are blanknodes being converted to variables in this scope * @return converted Anzo value, or null if glitterNode was blank, was a variable, or was a bnode with blankNodeAsVariable true */ protected org.openrdf.model.Value convert(TriplePatternComponent glitterNode, boolean blankNodesAsVariables) { if (glitterNode == null || glitterNode instanceof Variable) { return null; } if (blankNodesAsVariables && glitterNode instanceof BlankNode) { return null; } if (glitterNode instanceof BlankNode) { if (!this.bnodeMap.containsKey(glitterNode)) { this.bnodeMap.put((BlankNode) glitterNode, BasicNodeConverter.valueFactory.createBNode(((BlankNode) glitterNode).getLabel())); } return this.bnodeMap.get(glitterNode); } else if (glitterNode instanceof org.openanzo.rdf.Literal) { if (glitterNode instanceof TypedLiteral) { TypedLiteral glitterTypedLit = (TypedLiteral) glitterNode; if (glitterTypedLit.getDatatypeURI() != null) { return BasicNodeConverter.valueFactory.createLiteral(glitterTypedLit.getLabel(), BasicNodeConverter.valueFactory.createURI(glitterTypedLit.getDatatypeURI().toString())); } } else if (glitterNode instanceof PlainLiteral) { org.openanzo.rdf.PlainLiteral glitterPlainLit = (org.openanzo.rdf.PlainLiteral) glitterNode; String lang = glitterPlainLit.getLanguage(); return BasicNodeConverter.valueFactory.createLiteral(glitterPlainLit.getLabel(), lang); } } else if (glitterNode instanceof org.openanzo.rdf.URI) { return BasicNodeConverter.valueFactory.createURI(((org.openanzo.rdf.URI) glitterNode).toString()); } throw new GlitterRuntimeException(ExceptionConstants.GLITTER.NO_PRODUCE_NODE, glitterNode.getClass().getName()); } // long hits = 0; /** * Convert Anzo value to glitter RDFTerm * * @param value * Anzo value to convert * @return Glitter RDFTerm version of value */ protected Value convert(org.openrdf.model.Value value) { SoftReference<Value> resultRef = cachedNodes.get(value); Value result = (resultRef != null) ? resultRef.get() : null; if (result != null) { return result; } if (value instanceof URI) { result = MemURI.create(value.toString()); } else if (value instanceof org.openrdf.model.Literal) { Literal lit = (Literal) value; if (lit.getDatatype() == null) { if (lit.getLanguage() == null) { result = MemPlainLiteral.create(lit.getLabel()); } else { result = MemPlainLiteral.create(lit.getLabel(), lit.getLanguage()); } } else { result = MemTypedLiteral.create(lit.getLabel(), MemURI.create(lit.getDatatype().toString())); } } else if (value instanceof BNode) { result = MemValueFactory.defaultFactory.createBNode(((BNode) value).toString()); } if (result != null) { cachedNodes.put(value, new SoftReference<Value>(result)); } return result; } /** * Convert binding set to pattern solution * * @param solution * binding set to convert * @return converted pattern solution */ public PatternSolution convert(BindingSet solution) { PatternSolution patternSolution = new PatternSolutionImpl(); Set<String> bindings = solution.getBindingNames(); for (String binding : bindings) { Binding b = solution.getBinding(binding); patternSolution.setBinding(MemVariable.createVariable(b.getName()), convert(b.getValue())); } return patternSolution; } /** * Convert pattern solution to binding set * * @param solution * pattern solution * @return binding sets */ public BindingSet convert(PatternSolution solution) { MapBindingSet binding = new MapBindingSet(); for (int i = 0; i < solution.size(); i++) { Bindable bindable = solution.getBinding(i); String key = (bindable instanceof Variable) ? ((Variable) bindable).getName() : bindable.toString(); org.openrdf.model.Value value = convert(solution.getValue(i), false); binding.addBinding(key, value); } return binding; } private static final org.openrdf.rio.RDFFormat sparqlTbl = new org.openrdf.rio.RDFFormat("Solution Table", "application/anzo-sparql-results+tbl", Charset.forName("UTF-8"), Collections.singleton("tbl"), false, false); private static final org.openrdf.rio.RDFFormat jsonFormat = new org.openrdf.rio.RDFFormat("JSON", RDFFormat.JSON.getDefaultMIMEType(), Charset.defaultCharset(), ".json", false, true); /** * Convert RIO RDFFormat to RDFFOrmat object * * @param format * format to convert * @return converted RDFFormat */ public static RDFFormat convert(org.openrdf.rio.RDFFormat format) { if (format.equals(org.openrdf.rio.RDFFormat.RDFXML)) { return RDFFormat.RDFXML; } else if (format.equals(org.openrdf.rio.RDFFormat.NTRIPLES)) { return RDFFormat.NTRIPLES; } else if (format.equals(org.openrdf.rio.RDFFormat.N3)) { return RDFFormat.N3; } else if (format.equals(org.openrdf.rio.RDFFormat.TURTLE)) { return RDFFormat.TURTLE; } else if (format.equals(org.openrdf.rio.RDFFormat.TRIX)) { return RDFFormat.TRIX; } else if (format.equals(org.openrdf.rio.RDFFormat.TRIG)) { return RDFFormat.TRIG; } else if (format.equals(jsonFormat)) { return RDFFormat.JSON; } else if (format.equals(sparqlTbl)) { return RDFFormat.TBL; } else throw new AnzoRuntimeException(ExceptionConstants.IO.UNSUPPORTED_FORMAT_ERROR, format.toString()); } /** * Convert RDFFormat to RIO RDFFormat * * @param format * RDFFormat to convert * @return converted format */ public static org.openrdf.rio.RDFFormat convert(RDFFormat format) { switch (format) { case RDFXML: return org.openrdf.rio.RDFFormat.RDFXML; case NTRIPLES: return org.openrdf.rio.RDFFormat.NTRIPLES; case N3: return org.openrdf.rio.RDFFormat.N3; case TURTLE: return org.openrdf.rio.RDFFormat.TURTLE; case TRIX: return org.openrdf.rio.RDFFormat.TRIX; case TRIG: return org.openrdf.rio.RDFFormat.TRIG; case JSON: return jsonFormat; case TBL: return sparqlTbl; case SPARQL: return org.openrdf.rio.RDFFormat.N3; default: throw new AnzoRuntimeException(ExceptionConstants.IO.UNSUPPORTED_FORMAT_ERROR, format.toString()); } } }