Github user stain commented on a diff in the pull request:

    https://github.com/apache/incubator-commonsrdf/pull/23#discussion_r81151848
  
    --- Diff: 
jena/src/main/java/org/apache/commons/rdf/jena/JenaRDFTermFactory.java ---
    @@ -0,0 +1,874 @@
    +/**
    + * Licensed to the Apache Software Foundation (ASF) under one
    + * or more contributor license agreements.  See the NOTICE file
    + * distributed with this work for additional information
    + * regarding copyright ownership.  The ASF licenses this file
    + * to you under the Apache License, Version 2.0 (the
    + * "License"); you may not use this file except in compliance
    + * with the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.apache.commons.rdf.jena;
    +
    +import java.util.Optional;
    +import java.util.UUID;
    +import java.util.function.Consumer;
    +
    +import org.apache.commons.rdf.api.BlankNode;
    +import org.apache.commons.rdf.api.BlankNodeOrIRI;
    +import org.apache.commons.rdf.api.Dataset;
    +import org.apache.commons.rdf.api.Graph;
    +import org.apache.commons.rdf.api.IRI;
    +import org.apache.commons.rdf.api.Literal;
    +import org.apache.commons.rdf.api.Quad;
    +import org.apache.commons.rdf.api.QuadLike;
    +import org.apache.commons.rdf.api.RDFSyntax;
    +import org.apache.commons.rdf.api.RDFTerm;
    +import org.apache.commons.rdf.api.RDFTermFactory;
    +import org.apache.commons.rdf.api.Triple;
    +import org.apache.commons.rdf.api.TripleLike;
    +import org.apache.commons.rdf.jena.impl.JenaFactory;
    +import org.apache.jena.datatypes.RDFDatatype;
    +import org.apache.jena.datatypes.xsd.XSDDatatype;
    +import org.apache.jena.graph.Node;
    +import org.apache.jena.graph.NodeFactory;
    +import org.apache.jena.riot.Lang;
    +import org.apache.jena.riot.RDFDataMgr;
    +import org.apache.jena.riot.RDFLanguages;
    +import org.apache.jena.riot.system.StreamRDF;
    +import org.apache.jena.riot.system.StreamRDFBase;
    +import org.apache.jena.sparql.core.DatasetGraph;
    +import org.apache.jena.sparql.graph.GraphFactory;
    +
    +/**
    + * RDFTermFactory with Jena-backed objects.
    + * <p>
    + * This factory can also convert existing objects from/to Jena with 
methods like
    + * {@link #fromJena(org.apache.jena.graph.Graph)} and {@link 
#toJena(Graph)}.
    + * <p>
    + * For the purpose of {@link BlankNode} identity, this factory will use an 
internal
    + * {@link UUID} as a salt. See {@link BlankNode#uniqueReference()} for 
details.
    + * 
    + * @see RDFTermFactory
    + */
    +public final class JenaRDFTermFactory implements RDFTermFactory {
    +
    +   private final UUID salt;
    +
    +   /**
    +    * Create a JenaRDFTermFactory.
    +    * <p>
    +    * This constructor will use a randomly generated {@link UUID} as a 
salt 
    +    * for the purposes of {@link BlankNode} identity, see {@link 
#getSalt()}.
    +    */
    +   public JenaRDFTermFactory() {
    +           this.salt = UUID.randomUUID();
    +   }
    +
    +   /**
    +    * Create a JenaRDFTermFactory.
    +    * <p>
    +    * This constructor will use the specified {@link UUID} as a salt 
    +    * for the purposes of {@link BlankNode} identity.
    +    * 
    +    * @param salt {@link UUID} to use as salt
    +    */     
    +   public JenaRDFTermFactory(UUID salt) {
    +           this.salt = salt;
    +   }
    +
    +   @Override
    +   public JenaBlankNode createBlankNode() {
    +           return JenaFactory.createBlankNode(getSalt());
    +   }
    +
    +   @Override
    +   public JenaBlankNode createBlankNode(String name) {
    +           return JenaFactory.createBlankNode(name, getSalt());
    +   }
    +   
    +   @Override
    +   public JenaDataset createDataset() {
    +           return JenaFactory.createDataset(getSalt());
    +   }
    +
    +   @Override
    +   public JenaGraph createGraph() {
    +           return JenaFactory.createGraph(getSalt());
    +   }
    +
    +   @Override
    +   public JenaIRI createIRI(String iri) {
    +           validateIRI(iri);
    +           return JenaFactory.createIRI(iri);
    +   }
    +
    +   @Override
    +   public JenaLiteral createLiteral(String lexicalForm) {
    +           return JenaFactory.createLiteral(lexicalForm);
    +   }
    +
    +   @Override
    +   public JenaLiteral createLiteral(String lexicalForm, IRI dataType) {
    +           return JenaFactory.createLiteralDT(lexicalForm, 
dataType.getIRIString());
    +   }
    +
    +   @Override
    +   public JenaLiteral createLiteral(String lexicalForm, String 
languageTag) {
    +           validateLang(languageTag);
    +           return JenaFactory.createLiteralLang(lexicalForm, languageTag);
    +   }
    +
    +   @Override
    +   public JenaTriple createTriple(BlankNodeOrIRI subject, IRI predicate, 
RDFTerm object) {
    +           return JenaFactory.createTriple(subject, predicate, object);
    +   }
    +   
    +   @Override
    +   public JenaQuad createQuad(BlankNodeOrIRI graphName, BlankNodeOrIRI 
subject, IRI predicate, RDFTerm object)
    +                   throws IllegalArgumentException, 
UnsupportedOperationException {
    +           return JenaFactory.createQuad(subject, predicate, object, 
graphName);
    +   }
    +   
    +   /**
    +    * Adapt a generalized Jena Triple to a CommonsRDF {@link TripleLike} 
statement.
    +    * <p>
    +    * The generalized triple supports any {@link RDFTerm} as its {@link 
TripleLike#getSubject()}
    +    * {@link TripleLike#getPredicate()} or {@link TripleLike#getObject()}. 
    +    * <p>
    +    * If the Jena triple contains any {@link Node#isBlank()}, then any 
corresponding
    +    * {@link BlankNode} will use a {@link UUID} salt from this
    +    * {@link JenaRDFTermFactory} instance in combination with
    +    * {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    *
    +    * @see #fromJena(org.apache.jena.graph.Triple, UUID)
    +    * @see #fromJena(RDFTermFactory, org.apache.jena.graph.Triple)
    +    * 
    +    * @param subject The subject of the statement
    +    * @param predicate The predicate of the statement
    +    * @param object The object of the statement
    +
    +    *            
    +    * @return Adapted {@link TripleLike}. Note that the generalized triple 
does
    +    *         <strong>not</strong> implement {@link Triple#equals(Object)} 
or
    +    *         {@link Triple#hashCode()}.
    +    * @throws ConversionException
    +    *             if any of the triple's nodes are not concrete
    +    */
    +   public JenaTripleLike<RDFTerm, RDFTerm, RDFTerm> 
createGeneralizedTriple(
    +                   RDFTerm subject, RDFTerm predicate, RDFTerm object) {
    +           return JenaFactory.createGeneralizedTriple(subject, predicate, 
object);
    +   }
    +
    +   /**
    +    * Adapt an existing Jena Node to CommonsRDF {@link RDFTerm}.
    +    * <p>
    +    * If {@link Node#isLiteral()}, then the returned value is a {@link 
Literal}.
    +    * If {@link Node#isURI()}, the returned value is a IRI. If {$@link 
Node#isBlank()},
    +    * the returned value is a {@link BlankNode}, which will use a {@link 
UUID}
    +    * salt from this {@link JenaRDFTermFactory} instance in combination 
with
    +    * {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    * 
    +    * @see #fromJena(Node, UUID)
    +    * @see #fromJena(RDFTermFactory, Node)
    +    * 
    +    * @param node
    +    *            The Jena Node to adapt. It's {@link Node#isConcrete()} 
must be
    +    *            <code>true</code>.
    +    * @return Adapted {@link JenaRDFTerm}
    +    * @throws ConversionException
    +    *             if the node is not concrete.
    +    */
    +   public JenaRDFTerm fromJena(Node node) throws ConversionException {
    +           return JenaFactory.fromJena(node, getSalt());
    +   }
    +
    +   /**
    +    * Adapt an existing Jena Node to CommonsRDF {@link RDFTerm}.
    +    * <p>
    +    * If {@link Node#isLiteral()}, then the returned value is a {@link 
Literal}.
    +    * If {@link Node#isURI()}, the returned value is a IRI. If {@link 
Node#isBlank()},
    +    * the returned value is a {@link BlankNode}, which will use the 
provided
    +    * {@link UUID} salt in combination with {@link Node#getBlankNodeId()} 
for
    +    * the purpose of its {@link BlankNode#uniqueReference()}.
    +    * 
    +    * @see #fromJena(Node)
    +    * @see #fromJena(RDFTermFactory, Node)
    +    * 
    +    * @param node
    +    *            The Jena Node to adapt. It's {@link Node#isConcrete()} 
must be
    +    *            <code>true</code>.
    +    * @param salt
    +    *            UUID salt for the purpose of
    +    *            {@link BlankNode#uniqueReference()}
    +    * @return Adapted {@link JenaRDFTerm}
    +    * @throws ConversionException
    +    *             if the node is not concrete.
    +    */
    +   public static JenaRDFTerm fromJena(Node node, UUID salt) {
    +           return JenaFactory.fromJena(node, salt);
    +   }
    +   
    +   /**
    +    * Convert from Jena {@link Node} to any Commons RDF implementation.
    +    * <p>
    +    * Note that if the {@link Node#isBlank()}, then the factory's 
    +    * {@link RDFTermFactory#createBlankNode(String)} will be used, meaning
    +    * that care should be taken if reusing an {@link RDFTermFactory} 
instance
    +    * for multiple conversion sessions.
    +    * 
    +    * @see #fromJena(Node)
    +    * @see #fromJena(Node, UUID)
    +    * 
    +    * @param factory {@link RDFTermFactory} to use for creating {@link 
RDFTerm}.
    +    * @param node
    +    *            The Jena Node to adapt. It's {@link Node#isConcrete()} 
must be
    +    *            <code>true</code>.
    +    * @return Adapted {@link RDFTerm}            
    +    * @throws ConversionException
    +    *             if the node is not concrete.
    +    */
    +   public static RDFTerm fromJena(RDFTermFactory factory, Node node) {
    +           if (node == null) {
    +                   return null;
    +           }
    +           if (factory instanceof JenaRDFTermFactory) {
    +                   // No need to convert, just wrap
    +                   return ((JenaRDFTermFactory) factory).fromJena(node);
    +           }
    +           if (node.isURI())
    +                   return factory.createIRI(node.getURI());
    +           if (node.isLiteral()) {
    +                   String lang = node.getLiteralLanguage();
    +                   if (lang != null && !lang.isEmpty())
    +                           return 
factory.createLiteral(node.getLiteralLexicalForm(), lang);
    +                   if 
(node.getLiteralDatatype().equals(XSDDatatype.XSDstring))
    +                           return 
factory.createLiteral(node.getLiteralLexicalForm());
    +                   IRI dt = 
factory.createIRI(node.getLiteralDatatype().getURI());
    +                   return 
factory.createLiteral(node.getLiteralLexicalForm(), dt);
    +           }
    +           if (node.isBlank())
    +                   // The factory
    +                   return 
factory.createBlankNode(node.getBlankNodeLabel());
    +           throw new ConversionException("Node is not a concrete RDF Term: 
" + node);
    +   }       
    +   
    +   /**
    +    * Adapt an existing Jena Triple to CommonsRDF {@link Triple}.
    +    * <p>
    +    * If the triple contains any {@link Node#isBlank()}, then any 
corresponding
    +    * {@link BlankNode} will use a {@link UUID} salt from this
    +    * {@link JenaRDFTermFactory} instance in combination with
    +    * {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    *
    +    * @see #fromJena(org.apache.jena.graph.Triple, UUID)
    +    * @see #fromJena(RDFTermFactory, org.apache.jena.graph.Triple)
    +    * 
    +    * @param triple
    +    *            Jena {@link org.apache.jena.graph.Triple} to adapt
    +    * @return Adapted {@link JenaTriple}
    +    * @throws ConversionException
    +    *             if any of the triple's nodes are not concrete or the 
triple
    +    *             is a generalized triple
    +    */
    +   public JenaTriple fromJena(org.apache.jena.graph.Triple triple) throws 
ConversionException {
    +           return JenaFactory.fromJena(triple, getSalt());
    +   }
    +
    +
    +   /**
    +    * Adapt a generalized Jena Triple to a CommonsRDF {@link TripleLike}.
    +    * <p>
    +    * The generalized triple supports any {@link RDFTerm} as its {@link 
TripleLike#getSubject()}
    +    * {@link TripleLike#getPredicate()} or {@link TripleLike#getObject()}. 
    +    * <p>
    +    * If the Jena triple contains any {@link Node#isBlank()}, then any 
corresponding
    +    * {@link BlankNode} will use the provided {@link UUID} salt 
    +    * in combination with
    +    * {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    *
    +    * @see #fromJena(org.apache.jena.graph.Triple, UUID)
    +    * @see #fromJena(RDFTermFactory, org.apache.jena.graph.Triple)
    +    * 
    +    * @param triple
    +    *            Jena triple
    +    * @param salt
    +    *            UUID salt for the purpose of
    +    *            {@link BlankNode#uniqueReference()}
    +    * @return Adapted {@link TripleLike}. Note that the generalized triple 
does
    +    *         <strong>not</strong> implement {@link Triple#equals(Object)} 
or
    +    *         {@link Triple#hashCode()}.
    +    * @throws ConversionException
    +    *             if any of the triple's nodes are not concrete
    +    */
    +   public JenaTripleLike<RDFTerm, RDFTerm, RDFTerm> 
fromJenaGeneralized(org.apache.jena.graph.Triple triple, UUID salt) throws 
ConversionException {
    +           return JenaFactory.fromJenaGeneralized(triple, salt);
    +   }
    +   
    +   /**
    +    * Adapt a generalized Jena {@link org.apache.jena.graph.Triple} to a 
CommonsRDF {@link TripleLike}.
    +    * <p>
    +    * The generalized triple supports any {@link RDFTerm} as its {@link 
TripleLike#getSubject()}
    +    * {@link TripleLike#getPredicate()} or {@link TripleLike#getObject()}, 
including 
    +    * the extensions {@link JenaAny} and {@link JenaVariable}.
    +    * <p>
    +    * If the Jena triple contains any {@link Node#isBlank()}, then any 
corresponding
    +    * {@link BlankNode} will use a {@link UUID} salt from this
    +    * {@link JenaRDFTermFactory} instance in combination with
    +    * {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    *
    +    * @see #fromJena(org.apache.jena.graph.Triple, UUID)
    +    * @see #fromJena(RDFTermFactory, org.apache.jena.graph.Triple)
    +    * 
    +    * @param triple
    +    *            Jena triple
    +    * @return Adapted {@link TripleLike}. Note that the generalized triple 
does
    +    *         <strong>not</strong> implement {@link Triple#equals(Object)} 
or
    +    *         {@link Triple#hashCode()}.
    +    * @throws ConversionException
    +    *             if any of the triple's nodes are not concrete
    +    */
    +   public JenaTripleLike<RDFTerm, RDFTerm, RDFTerm> 
fromJenaGeneralized(org.apache.jena.graph.Triple triple) throws 
ConversionException {
    +           return JenaFactory.fromJenaGeneralized(triple, getSalt());
    +   }
    +
    +   /**
    +    * Adapt a generalized Jena {@link org.apache.jena.sparql.core.Quad} to 
a CommonsRDF {@link QuadLike}.
    +    * <p>
    +    * The generalized quad supports any {@link RDFTerm} as its 
    +    * {@link QuadLike#getGraphName()}, 
    +    * {@link QuadLike#getSubject()}
    +    * {@link QuadLike#getPredicate()} or 
    +    * {@link QuadLike#getObject()}, including 
    +    * the extensions 
    +    * {@link JenaAny} and {@link JenaVariable}. 
    +    * <p>
    +    * If the Jena quad contains any {@link Node#isBlank()}, then any 
corresponding
    +    * {@link BlankNode} will use a {@link UUID} salt from this
    +    * {@link JenaRDFTermFactory} instance in combination with
    +    * {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    *
    +    * @see #fromJena(org.apache.jena.sparql.core.Quad)
    +    * @see #fromJenaGeneralized(org.apache.jena.graph.Triple)
    +    * 
    +    * @param quad
    +    *            Jena quad
    +    * @return Adapted {@link QuadLike}. Note that the generalized quad does
    +    *         <strong>not</strong> implement {@link Quad#equals(Object)} or
    +    *         {@link Quad#hashCode()}.
    +    * @throws ConversionException
    +    *             if any of the quad nodes are not concrete
    +    */
    +   public JenaQuadLike<RDFTerm, RDFTerm, RDFTerm, RDFTerm> 
fromJenaGeneralized(org.apache.jena.sparql.core.Quad quad) throws 
ConversionException {
    +           return JenaFactory.fromJenaGeneralized(quad, getSalt());
    +   }
    +   
    +   
    +   /**
    +    * Adapt an existing Jena Triple to CommonsRDF {@link Triple}.
    +    * <p>
    +    * If the triple contains any {@link Node#isBlank()}, then any 
corresponding
    +    * {@link BlankNode} will use the provided a {@link UUID} salt in
    +    * combination with {@link Node#getBlankNodeId()} for the purpose of its
    +    * {@link BlankNode#uniqueReference()}.
    +    * 
    +    * @param triple
    +    *            Jena triple
    +    * @param salt
    +    *            A {@link UUID} salt for adapting any {@link BlankNode}s
    +    * @return Adapted triple
    +    * @throws ConversionException
    +    *             if any of the triple's nodes are not concrete or the 
triple
    +    *             is a generalized triple
    +    */
    +   public static JenaTriple fromJena(org.apache.jena.graph.Triple triple, 
UUID salt) throws ConversionException {
    +           return JenaFactory.fromJena(triple, salt);
    +   }
    +
    +   /**
    +    * Convert from Jena {@link org.apache.jena.graph.Triple} to a Commons 
RDF
    +    * {@link Triple}.
    +    * <p>
    +    * Note that if any of the triple's nodes {@link Node#isBlank()}, then 
the factory's 
    +    * {@link RDFTermFactory#createBlankNode(String)} will be used, meaning
    +    * that care should be taken if reusing an {@link RDFTermFactory} 
instance
    +    * for multiple conversion sessions.
    +    * 
    +    * @see #fromJena(org.apache.jena.graph.Triple)
    +    * @see #fromJena(org.apache.jena.graph.Triple, UUID)
    +    *
    +    * @param factory {@link RDFTermFactory} to use for creating the {@link 
Triple} and its
    +    * {@link RDFTerm}s.
    +    * @param triple
    +    *            Jena triple
    +    * @return Converted triple
    +    * @throws ConversionException
    +    *             if any of the triple's nodes are not concrete or the 
triple
    +    *             is a generalized triple
    +    */
    +   public static Triple fromJena(RDFTermFactory factory, 
org.apache.jena.graph.Triple triple) 
    +                   throws ConversionException{
    +           if (factory instanceof JenaRDFTermFactory) {
    +                   // No need to convert, just wrap
    +                   return ((JenaRDFTermFactory) factory).fromJena(triple);
    +           }
    +           BlankNodeOrIRI subject;
    +           IRI predicate;
    +           try {
    +                   subject = (BlankNodeOrIRI) fromJena(factory, 
triple.getSubject());
    +                   predicate = (IRI) fromJena(factory, 
triple.getPredicate());
    +           } catch (ClassCastException ex) {
    +                   throw new ConversionException("Can't convert 
generalized triple: " + triple, ex);
    +           }
    +           RDFTerm object = fromJena(factory, triple.getObject());
    +           return factory.createTriple(subject, predicate, object);
    --- End diff --
    
    I dare to disagree in this instance as `ClassCastException` is unchecked - 
- the try-catch should only cover what we want to catch.
    
    Some might argue against a `return` from inside a `try` block, but I don't 
see a problem with that side (Java won't let you void through).
    
    We don't expect `fromJena()` or `createTriple()` to throw 
ClassCastException. If they do, it should be a proper `RuntimeException`, not a 
`ConversionException`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

Reply via email to