/*
 * This file is part of Sponge, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered.org <http://www.spongepowered.org>
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.spongepowered.api.service.persistence.data;

import com.google.common.collect.ImmutableList;

import java.util.List;
import java.util.regex.Pattern;

/**
 * Represents a query that can be done on views. Queries do not depend on
 * their separator, it is just a way to construct them.
 */
public final class DataQuery {

    /**
     * The parts that make up this query.
     */
    private final String[] parts;

    /**
     * Constructs a query using the given separator and path.
     *
     * <p>As an example, {@code new Query("/", "a/b/c")} and
     * {@code new Query(".", "a.b.c")} represent the same path but are
     * constructed using different separators.</p>
     *
     * @param separator The separator
     * @param path The path
     */
    public DataQuery(String separator, String path) {
        this.parts = path.split(Pattern.quote(separator));
    }

    /**
     * Constructs a query using the given separator character and path.
     *
     * <p>As an example, {@code new Query('/', "a/b/c")} and
     * {@code new Query('.', "a.b.c")} represent the same path but are
     * constructed using different separators.</p>
     *
     * @param separator The separator
     * @param path The path
     */
    public DataQuery(char separator, String path) {
        this(String.valueOf(separator), path);
    }

    /**
     * Constructs a query using the given parts.
     *
     * @param parts The parts
     */
    public DataQuery(String... parts) {
        this.parts = parts.clone();
    }

    /**
     * Constructs a query using the given parts.
     *
     * @param parts The parts
     */
    public DataQuery(List<String> parts) {
       this(parts.toArray(new String[0]));
    }

    /**
     * Gets the parts that make up this query.
     *
     * @return The parts of this query
     */
    public List<String> getParts() {
        return new ImmutableList.Builder<String>().add(parts).build();
    }

    /**
     * Returns a new query that is made up of this query's parts followed by the
     * given query's parts.
     *
     * @param that The given query to follow this one
     * @return The constructed query
     */
    public DataQuery then(DataQuery that) {
        ImmutableList.Builder<String> builder =
                new ImmutableList.Builder<String>();

        builder.addAll(getParts());
        builder.addAll(that.getParts());

        return new DataQuery(builder.build());
    }

    /**
     * Returns the parts of this query as individual queries.
     *
     * @return The constructed queries
     */
    public List<DataQuery> getQueryParts() {
        ImmutableList.Builder<DataQuery> builder =
                new ImmutableList.Builder<DataQuery>();

        for (String part: getParts()) {
            builder.add(new DataQuery(part));
        }

        return builder.build();
    }

    /**
     * Gets this query as a string separated by the given separator.
     *
     * @param separator The separator
     * @return This query as a string
     */
    public String asString(String separator) {
        StringBuilder builder = new StringBuilder();

        if (parts.length > 0) {
            builder.append(parts[0]);
        }

        for (int i = 1; i < parts.length; i++) {
            builder.append(separator);
            builder.append(parts[i]);
        }

        return builder.toString();
    }

    /**
     * Gets this query as a string separated by the given separator character.
     *
     * @param separator The separator
     * @return This query as a string
     */
    public String asString(char separator) {
        return asString(String.valueOf(separator));
    }

}

@@ -1301,16 +1301,54 @@
 .data;%0A%0A
+import com.google.common.base.Joiner;%0A
 import c
@@ -1387,16 +1387,16 @@
 leList;%0A
-
 %0Aimport 
@@ -1694,484 +1694,36 @@
 nal 
-String%5B%5D parts;%0A%0A    /**%0A     * Constructs a query using the given separator and path.%0A     *%0A     * %3Cp%3EAs an example, %7B@code new Query(%22/%22, %22a/b/c%22)%7D and%0A     * %7B@code new Query(%22.%22, %22a.b.c%22)%7D represent the same path but are%0A     * constructed using different separators.%3C/p%3E%0A     *%0A     * @param separator The separator%0A     * @param path The path%0A     */%0A    public DataQuery(String separator, String path) %7B%0A        this.parts = path.split(Pattern.quote(separator));%0A    %7D
+ImmutableList%3CString%3E parts;
 %0A%0A  
@@ -2136,16 +2136,41 @@
    this(
+path.split(Pattern.quote(
 String.v
@@ -2190,14 +2190,10 @@
 tor)
-, path
+))
 );%0A 
@@ -2365,20 +2365,34 @@
 s = 
-parts.clone(
+ImmutableList.copyOf(parts
 );%0A 
@@ -2557,37 +2557,43 @@
 this
-(
+.
 parts
-.toArray(new String%5B0%5D)
+ = ImmutableList.copyOf(parts
 );%0A 
@@ -2714,24 +2714,33 @@
 %0A    public 
+Immutable
 List%3CString%3E
@@ -2772,62 +2772,18 @@
 urn 
-new ImmutableList.Builder%3CString%3E().add(parts).build()
+this.parts
 ;%0A  
@@ -3179,26 +3179,26 @@
 .addAll(
-getP
+this.p
 arts
-()
 );%0A     
@@ -3220,26 +3220,21 @@
 ll(that.
-getP
+p
 arts
-()
 );%0A%0A    
@@ -3418,16 +3418,25 @@
  public 
+Immutable
 List%3CDat
@@ -3932,304 +3932,51 @@
     
-StringBuilder builder = new StringBuilder();%0A%0A        if (parts.length %3E 0) %7B%0A            builder.append(parts%5B0%5D);%0A        %7D%0A%0A        for (int i = 1; i %3C parts.length; i++) %7B%0A            builder.append(separator);%0A            builder.append(parts%5Bi%5D);%0A        %7D%0A%0A        return builder.toString(
+return Joiner.on(separator).join(this.parts
 );%0A 

Refactor DataQuery internals. DataQuery now uses ImmutableList which internally uses an array. This allows DataQuery to return its internal list when necessary. Also fixes ambiguous constructor.