/*
 * 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.rya.indexing.pcj.storage.accumulo;

import static org.junit.Assert.assertEquals;

import java.math.BigDecimal;
import java.math.BigInteger;

import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter.BindingSetConversionException;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.impl.MapBindingSet;
import org.junit.Test;

/**
 * Tests the methods of {@link BindingSetStringConverter}.
 */
public class BindingSetStringConverterTest {
    private static final ValueFactory VF = SimpleValueFactory.getInstance();

    @Test
    public void noBindings() throws BindingSetConversionException {
        // Create a BindingSet that doesn't have any bindings.
        final MapBindingSet original = new MapBindingSet();

        // Convert it to a String.
        final VariableOrder varOrder = new VariableOrder();
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(original, varOrder);

        // Convert it back to a binding set.
        final BindingSet converted = converter.convert(bindingSetString, varOrder);

        // Ensure it is still an empty BindingSet.
        assertEquals(original, converted);
    }

    @Test
    public void toString_URIs() throws BindingSetConversionException {
        // Setup the binding set that will be converted.
        final MapBindingSet originalBindingSet = new MapBindingSet();
        originalBindingSet.addBinding("x", VF.createIRI("http://a"));
        originalBindingSet.addBinding("y", VF.createIRI("http://b"));
        originalBindingSet.addBinding("z", VF.createIRI("http://c"));

        // Convert it to a String.
        final VariableOrder varOrder = new VariableOrder("y", "z", "x");
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(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() throws BindingSetConversionException {
        // Setup the binding set that will be converted.
        final MapBindingSet originalBindingSet = new MapBindingSet();
        originalBindingSet.addBinding("x", VF.createLiteral(new BigDecimal(2.5)));

        // Convert it to a String.
        final VariableOrder varOrder = new VariableOrder("x");
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(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() throws BindingSetConversionException {
        // Setup the binding set that will be converted.
        final MapBindingSet originalBindingSet = new MapBindingSet();
        originalBindingSet.addBinding("x", VF.createLiteral((true)));

        // Convert it to a String.
        final VariableOrder varOrder = new VariableOrder("x");
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(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() throws BindingSetConversionException {
        // Setup the binding set that will be converted.
        final MapBindingSet originalBindingSet = new MapBindingSet();
        originalBindingSet.addBinding("x", VF.createLiteral((BigInteger.valueOf(5))));

        // Convert it to a String.
        final VariableOrder varOrder = new VariableOrder("x");
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(originalBindingSet, varOrder);

        // Ensure it converted to the expected result.
        final String expected = "5<<~>>http://www.w3.org/2001/XMLSchema#integer";
        assertEquals(expected, bindingSetString);
    }

    /**
     * All of the Bindings in the BindingSet exactly match the variable order.
     * This is the simplest case and is legal.
     */
    @Test
    public void toString_bindingsMatchVarOrder() throws BindingSetConversionException {
        // Setup the Binding Set.
        final MapBindingSet originalBindingSet = new MapBindingSet();
        originalBindingSet.addBinding("x", VF.createIRI("http://a"));
        originalBindingSet.addBinding("y", VF.createIRI("http://b"));

        // Setup the variable order.
        final VariableOrder varOrder = new VariableOrder("x", "y");

        // Create the String representation of the BindingSet.
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(originalBindingSet, varOrder);

        // Ensure the expected value was created.
        final String expected =
                "http://a<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" +
                "http://b<<~>>http://www.w3.org/2001/XMLSchema#anyURI";
        assertEquals(expected, bindingSetString);
    }

    /**
     * The BindingSet has fewer Bindings than there are variables in the variable
     * order, but they are all in the variable order. This is the case where
     * the missing bindings were optional.
     */
    @Test
    public void toString_bindingsSubsetOfVarOrder() throws BindingSetConversionException {
        // Setup the Binding Set.
        final MapBindingSet originalBindingSet = new MapBindingSet();
        originalBindingSet.addBinding("x", VF.createIRI("http://a"));
        originalBindingSet.addBinding("y", VF.createIRI("http://b"));

        // Setup the variable order.
        final VariableOrder varOrder = new VariableOrder("x", "a", "y", "b");

        // Create the String representation of the BindingSet.
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final String bindingSetString = converter.convert(originalBindingSet, varOrder);

        // Ensure the expected value was created.
        final String expected =
                "http://a<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" +
                BindingSetStringConverter.NULL_VALUE_STRING + ":::" +
                "http://b<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" +
                BindingSetStringConverter.NULL_VALUE_STRING;
        assertEquals(expected, bindingSetString);
    }

    @Test
    public void fromString() throws BindingSetConversionException {
        // 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 BindingSetConverter<String> converter = new BindingSetStringConverter();
        final BindingSet bindingSet = converter.convert(bindingSetString, varOrder);

        // Ensure it converted to the expected result.
        final MapBindingSet expected = new MapBindingSet();
        expected.addBinding("x", VF.createIRI("http://a"));
        expected.addBinding("y", VF.createIRI("http://b"));
        expected.addBinding("z", VF.createIRI("http://c"));

        assertEquals(expected, bindingSet);
    }

    /**
     * Ensures that when a binding set is converted from a String back to a
     * BindingSet, null values do not get converted into Bindings.
     */
    @Test
    public void fromString_nullValues() throws BindingSetConversionException {
        // Setup the String that will be converted.
        final String bindingSetString =
                "http://value 1<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" +
                BindingSetStringConverter.NULL_VALUE_STRING + ":::" +
                "http://value 2<<~>>http://www.w3.org/2001/XMLSchema#anyURI:::" +
                BindingSetStringConverter.NULL_VALUE_STRING;

        // Convert it to a BindingSet
        final VariableOrder varOrder = new VariableOrder("x", "a", "y", "b");
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final BindingSet bindingSet = converter.convert(bindingSetString, varOrder);

        // Ensure it converted to the expected reuslt.
        final MapBindingSet expected = new MapBindingSet();
        expected.addBinding("x", VF.createIRI("http://value 1"));
        expected.addBinding("y", VF.createIRI("http://value 2"));

        assertEquals(expected, bindingSet);
    }

    @Test
    public void fromString_Decimal() throws BindingSetConversionException {
        // 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 BindingSetConverter<String> converter = new BindingSetStringConverter();
        final BindingSet bindingSet = converter.convert(bindingSetString, new VariableOrder("x"));

        // Ensure it converted to the expected result.
        final MapBindingSet expected = new MapBindingSet();
        expected.addBinding("x", VF.createLiteral((new BigDecimal(2.5))));

        assertEquals(expected, bindingSet);
    }

    @Test
    public void fromString_Boolean() throws BindingSetConversionException {
        // Setup the String that will be converted.
        final String bindingSetString = "true<<~>>http://www.w3.org/2001/XMLSchema#boolean";

        // Convert it to a BindingSet
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final BindingSet bindingSet = converter.convert(bindingSetString, new VariableOrder("x"));

        // Ensure it converted to the expected result.
        final MapBindingSet expected = new MapBindingSet();
        expected.addBinding("x", VF.createLiteral((true)));

        assertEquals(expected, bindingSet);
    }

    @Test
    public void fromString_Integer() throws BindingSetConversionException {
        // Setup the String that will be converted.
        final String bindingSetString = "5<<~>>http://www.w3.org/2001/XMLSchema#integer";

        // Convert it to a BindingSet
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        final BindingSet bindingSet = converter.convert(bindingSetString, new VariableOrder("x"));

        // Ensure it converted to the expected result.
        final MapBindingSet expected = new MapBindingSet();
        expected.addBinding("x", VF.createLiteral((BigInteger.valueOf(5))));

        assertEquals(expected, bindingSet);
    }

    @Test(expected = IllegalArgumentException.class)
    public void fromString_varOrderTooShort() throws BindingSetConversionException {
        // 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.
        final VariableOrder varOrder = new VariableOrder("x");

        // The conversion should throw an exception.
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        converter.convert(bindingSetString, varOrder);
    }

    @Test(expected = IllegalArgumentException.class)
    public void fromString_varOrderTooLong() throws BindingSetConversionException {
        // 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.
        final VariableOrder varOrder = new VariableOrder("x", "y", "z");

        // The conversion should throw an exception.
        final BindingSetConverter<String> converter = new BindingSetStringConverter();
        converter.convert(bindingSetString, varOrder);
    }
}