Repository: incubator-rya Updated Branches: refs/heads/develop 19e2e438c -> 3157bc466
RYA-35 - Added a class that converts BindingSet objects into Strings and back again. Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/3157bc46 Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/3157bc46 Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/3157bc46 Branch: refs/heads/develop Commit: 3157bc466a4faf87814ad9c81166c6f2139fc49c Parents: 19e2e43 Author: Kevin Chilton <kevin.chilton@localhost.localdomain> Authored: Sun Feb 14 15:20:15 2016 -0500 Committer: Kevin Chilton <kevin.chilton@localhost.localdomain> Committed: Tue Feb 16 16:12:18 2016 -0500 ---------------------------------------------------------------------- .../tupleSet/BindingSetStringConverter.java | 166 +++++++++++++ .../tupleSet/BindingSetStringConverterTest.java | 243 +++++++++++++++++++ 2 files changed, 409 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/3157bc46/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverter.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverter.java b/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverter.java new file mode 100644 index 0000000..d28186d --- /dev/null +++ b/extras/indexing/src/main/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverter.java @@ -0,0 +1,166 @@ +/* + * 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 mvm.rya.indexing.external.tupleSet; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.openrdf.model.URI; +import org.openrdf.model.Value; +import org.openrdf.model.ValueFactory; +import org.openrdf.model.impl.URIImpl; +import org.openrdf.model.impl.ValueFactoryImpl; +import org.openrdf.model.vocabulary.XMLSchema; +import org.openrdf.query.Binding; +import org.openrdf.query.BindingSet; +import org.openrdf.query.algebra.evaluation.QueryBindingSet; + +import mvm.rya.api.domain.RyaType; +import mvm.rya.api.resolver.RdfToRyaConversions; +import mvm.rya.indexing.external.tupleSet.PcjTables.VariableOrder; + +/** + * Converts {@link BindingSet}s to Strings and back again. + */ +public class BindingSetStringConverter { + + private static final String BINDING_DELIM = ":::"; + private static final String TYPE_DELIM = "<<~>>"; + + private static final ValueFactory valueFactory = new ValueFactoryImpl(); + + /** + * Converts a {@link BindingSet} to a String. You must provide the order the + * {@link Binding}s will be written to. + * </p> + * The resulting string does not include the binding names from the original + * object, so that must be kept with the resulting String if you want to + * convert it back to a BindingSet later. + * </p> + * + * @param bindingSet - The BindingSet that will be converted. (not null) + * @param varOrder - The order the bindings will appear in the resulting String. (not null) + * @return A {@code String} version of {@code bindingSet} whose binding are + * ordered based on {@code varOrder}. + */ + public static String toString(BindingSet bindingSet, VariableOrder varOrder) { + checkSameVariables(bindingSet, varOrder); + + final StringBuilder bindingSetString = new StringBuilder(); + + Iterator<String> it = varOrder.iterator(); + while(it.hasNext()) { + // Add a value to the binding set. + String varName = it.next(); + final Value value = bindingSet.getBinding(varName).getValue(); + final RyaType ryaValue = RdfToRyaConversions.convertValue(value); + bindingSetString.append( ryaValue.getData() ).append(TYPE_DELIM).append( ryaValue.getDataType() ); + + // If there are more values to add, include a delimiter between them. + if(it.hasNext()) { + bindingSetString.append(BINDING_DELIM); + } + } + + return bindingSetString.toString(); + } + + /** + * Checks to see if the names of all the {@link Binding}s in the {@link BindingSet} + * match the variable names in the {@link VariableOrder}. + * + * @param bindingSet - The binding set whose Bindings will be inspected. (not null) + * @param varOrder - The names of the bindings that must appear in the BindingSet. (not null) + * @throws IllegalArgumentException Indicates the number of bindings did not match + * the number of variables or that the binding names did not match the names + * of the variables. + */ + private static void checkSameVariables(BindingSet bindingSet, VariableOrder varOrder) throws IllegalArgumentException { + checkNotNull(bindingSet); + checkNotNull(varOrder); + + Set<String> bindingNames = bindingSet.getBindingNames(); + List<String> varOrderList = varOrder.getVariableOrders(); + checkArgument(bindingNames.size() == varOrderList.size(), "The number of Bindings must match the length of the VariableOrder."); + checkArgument(bindingNames.containsAll(varOrderList), "The names of the Bindings must match the variable names in VariableOrder."); + } + + /** + * Converts the String representation of a {@link BindingSet} as is created + * by {@link #toString(BindingSet, VariableOrder)} back into a BindingSet. + * <p> + * You must provide the Binding names in the order they were written to. + * </p> + * + * @param bindingSetString - The binding set values as a String. (not null) + * @param varOrder - The order the bindings appear in the String version of + * the BindingSet. (not null) + * @return A {@link BindingSet} representation of the String. + */ + public static BindingSet fromString(final String bindingSetString, final VariableOrder varOrder) { + checkNotNull(bindingSetString); + checkNotNull(varOrder); + + final String[] bindingStrings = bindingSetString.split(BINDING_DELIM); + final String[] varOrrderArr = varOrder.toArray(); + checkArgument(varOrrderArr.length == bindingStrings.length, "The number of Bindings must match the length of the VariableOrder."); + + final QueryBindingSet bindingSet = new QueryBindingSet(); + for(int i = 0; i < bindingStrings.length; i++) { + final String name = varOrrderArr[i]; + final Value value = toValue(bindingStrings[i]); + bindingSet.addBinding(name, value); + } + return bindingSet; + } + + /** + * Creates a {@link Value} from a String representation of it. + * + * @param valueString - The String representation of the value. (not null) + * @return The {@link Value} representation of the String. + */ + private static Value toValue(final String valueString) { + checkNotNull(valueString); + + // Split the String that was stored in Fluo into its Value and Type parts. + final String[] valueAndType = valueString.split(TYPE_DELIM); + if(valueAndType.length != 2) { + throw new IllegalArgumentException("Array must contain data and type info!"); + } + + final String dataString = valueAndType[0]; + final String typeString = valueAndType[1]; + + // Convert the String Type into a URI that describes the type. + final URI typeURI = valueFactory.createURI(typeString); + + // Convert the String Value into a Value. + final Value value = typeURI.equals(XMLSchema.ANYURI) ? + valueFactory.createURI(dataString) : + valueFactory.createLiteral(dataString, new URIImpl(typeString)); + + return value; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/3157bc46/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverterTest.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverterTest.java b/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverterTest.java new file mode 100644 index 0000000..0a7f399 --- /dev/null +++ b/extras/indexing/src/test/java/mvm/rya/indexing/external/tupleSet/BindingSetStringConverterTest.java @@ -0,0 +1,243 @@ +/* + * 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 mvm.rya.indexing.external.tupleSet; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.junit.Test; +import org.openrdf.model.impl.BooleanLiteralImpl; +import org.openrdf.model.impl.DecimalLiteralImpl; +import org.openrdf.model.impl.IntegerLiteralImpl; +import org.openrdf.model.impl.URIImpl; +import org.openrdf.query.BindingSet; +import org.openrdf.query.impl.MapBindingSet; + +import mvm.rya.indexing.external.tupleSet.PcjTables.VariableOrder; + +/** + * Tests the methods of {@link BindingSetStringConverter}. + */ +public class BindingSetStringConverterTest { + + @Test + public void toString_URIs() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new URIImpl("http://a")); + originalBindingSet.addBinding("y", new URIImpl("http://b")); + originalBindingSet.addBinding("z", new URIImpl("http://c")); + + // Convert it to a String. + final VariableOrder varOrder = new VariableOrder("y", "z", "x"); + final String bindingSetString = BindingSetStringConverter.toString(originalBindingSet, varOrder); + + // Ensure it converted to the expected result. + final String expected = + "http://b<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" + + "http://c<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" + + "http://a<<~>>http://www.w3.org/2001/XMLSchema#anyURI"; + + assertEquals(expected, bindingSetString); + } + + @Test + public void toString_Decimal() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new DecimalLiteralImpl(new BigDecimal(2.5))); + + // Convert it to a String. + final VariableOrder varOrder = new VariableOrder("x"); + final String bindingSetString = BindingSetStringConverter.toString(originalBindingSet, varOrder); + + // Ensure it converted to the expected result. + final String expected = "2.5<<~>>http://www.w3.org/2001/XMLSchema#decimal"; + assertEquals(expected, bindingSetString); + } + + @Test + public void toString_Boolean() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new BooleanLiteralImpl(true)); + + // Convert it to a String. + final VariableOrder varOrder = new VariableOrder("x"); + final String bindingSetString = BindingSetStringConverter.toString(originalBindingSet, varOrder); + + // Ensure it converted to the expected result. + final String expected = "true<<~>>http://www.w3.org/2001/XMLSchema#boolean"; + assertEquals(expected, bindingSetString); + } + + @Test + public void toString_Integer() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new IntegerLiteralImpl(BigInteger.valueOf(5))); + + // Convert it to a String. + final VariableOrder varOrder = new VariableOrder("x"); + final String bindingSetString = BindingSetStringConverter.toString(originalBindingSet, varOrder); + + // Ensure it converted to the expected result. + final String expected = "5<<~>>http://www.w3.org/2001/XMLSchema#integer"; + assertEquals(expected, bindingSetString); + } + + @Test(expected = IllegalArgumentException.class) + public void toString_varOrderTooShort() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new URIImpl("http://a")); + originalBindingSet.addBinding("y", new URIImpl("http://b")); + + // This variable order that is too short. + final VariableOrder varOrder = new VariableOrder("y"); + + // The conversion should throw an exception. + BindingSetStringConverter.toString(originalBindingSet, varOrder); + } + + @Test(expected = IllegalArgumentException.class) + public void toString_varOrderTooLong() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new URIImpl("http://a")); + originalBindingSet.addBinding("y", new URIImpl("http://b")); + + // This variable order is too long. + final VariableOrder varOrder = new VariableOrder("x", "y", "z"); + + // The conversion should throw an exception. + BindingSetStringConverter.toString(originalBindingSet, varOrder); + } + + @Test(expected = IllegalArgumentException.class) + public void toString_varOrderWrongBindingNames() { + // Setup the binding set that will be converted. + final MapBindingSet originalBindingSet = new MapBindingSet(); + originalBindingSet.addBinding("x", new URIImpl("http://a")); + originalBindingSet.addBinding("y", new URIImpl("http://b")); + + // This variable order has the wrong binding names. + final VariableOrder varOrder = new VariableOrder("x", "a"); + + // The conversion should throw an exception. + BindingSetStringConverter.toString(originalBindingSet, varOrder); + } + + @Test + public void fromString() { + // Setup the String that will be converted. + final String bindingSetString = + "http://b<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" + + "http://c<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" + + "http://a<<~>>http://www.w3.org/2001/XMLSchema#anyURI"; + + // Convert it to a BindingSet + final VariableOrder varOrder = new VariableOrder("y", "z", "x"); + final BindingSet bindingSet = BindingSetStringConverter.fromString(bindingSetString, varOrder); + + // Ensure it converted to the expected result. + final MapBindingSet expected = new MapBindingSet(); + expected.addBinding("x", new URIImpl("http://a")); + expected.addBinding("y", new URIImpl("http://b")); + expected.addBinding("z", new URIImpl("http://c")); + + assertEquals(expected, bindingSet); + } + + @Test + public void fromString_Decimal() { + // Setup the String that will be converted. + final String bindingSetString = "2.5<<~>>http://www.w3.org/2001/XMLSchema#decimal"; + + // Convert it to a BindingSet + final BindingSet bindingSet = BindingSetStringConverter.fromString(bindingSetString, new VariableOrder("x")); + + // Ensure it converted to the expected result. + final MapBindingSet expected = new MapBindingSet(); + expected.addBinding("x", new DecimalLiteralImpl(new BigDecimal(2.5))); + + assertEquals(expected, bindingSet); + } + + @Test + public void fromString_Boolean() { + // Setup the String that will be converted. + final String bindingSetString = "true<<~>>http://www.w3.org/2001/XMLSchema#boolean"; + + // Convert it to a BindingSet + final BindingSet bindingSet = BindingSetStringConverter.fromString(bindingSetString, new VariableOrder("x")); + + // Ensure it converted to the expected result. + final MapBindingSet expected = new MapBindingSet(); + expected.addBinding("x", new BooleanLiteralImpl(true)); + + assertEquals(expected, bindingSet); + } + + @Test + public void fromString_Integer() { + // Setup the String that will be converted. + final String bindingSetString = "5<<~>>http://www.w3.org/2001/XMLSchema#integer"; + + // Convert it to a BindingSet + final BindingSet bindingSet = BindingSetStringConverter.fromString(bindingSetString, new VariableOrder("x")); + + // Ensure it converted to the expected result. + final MapBindingSet expected = new MapBindingSet(); + expected.addBinding("x", new IntegerLiteralImpl(BigInteger.valueOf(5))); + + assertEquals(expected, bindingSet); + } + + @Test(expected = IllegalArgumentException.class) + public void fromString_varOrderTooShort() { + // Setup the String that will be converted. + final String bindingSetString = + "http://a<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" + + "http://b<<~>>http://www.w3.org/2001/XMLSchema#anyURI"; + + // This variable order is too short. + VariableOrder varOrder = new VariableOrder("x"); + + // The conversion should throw an exception. + BindingSetStringConverter.fromString(bindingSetString, varOrder); + } + + @Test(expected = IllegalArgumentException.class) + public void fromString_varOrderTooLong() { + // Setup the String that will be converted. + final String bindingSetString = + "http://a<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" + + "http://b<<~>>http://www.w3.org/2001/XMLSchema#anyURI"; + + // This variable order is too long. + VariableOrder varOrder = new VariableOrder("x", "y", "z"); + + // The conversion should throw an exception. + BindingSetStringConverter.fromString(bindingSetString, varOrder); + } +} \ No newline at end of file