/*
 * Copyright (C) 2009-2011 Mathias Doenitz
 *
 * Licensed 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.parboiled.support;

import com.github.fge.grappa.buffers.InputBuffer;
import com.github.fge.grappa.internal.NonFinalForTesting;
import com.github.fge.grappa.stack.ValueStack;
import org.parboiled.errors.ParseError;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;

/**
 * A simple container encapsulating the result of a parsing run.
 */
@NonFinalForTesting
public class ParsingResult<V>
{

    /**
     * DO NOT USE DIRECTLY!
     *
     * <p>Use {@link #isSuccess()} instead</p>
     */
    private final boolean matched;

    /**
     * DO NOT USE DIRECTLY!
     *
     * <p>Use {@link #getTopStackValue()} instead</p>
     */
    private final V resultValue;

    /**
     * DO NOT USE DIRECTLY!
     *
     * <p>Use {@link #getValueStack()} instead</p>
     */
    private final ValueStack<V> valueStack;

    /**
     * DO NOT USE DIRECTLY!
     *
     * <p>Use {@link #getParseErrors()} instead</p>
     */
    private final List<ParseError> parseErrors;

    /**
     * DO NOT USE DIRECTLY!
     *
     * <p>Use {@link #getInputBuffer()} instead</p>
     */
    private final InputBuffer inputBuffer;

    /**
     * Creates a new ParsingResult.
     *
     * @param matched true if the rule matched the input
     * @param valueStack the value stack of the parsing run
     * @param parseErrors the list of parse errors
     * @param inputBuffer the input buffer
     */
    public ParsingResult(final boolean matched,
        @Nonnull final ValueStack<V> valueStack,
        @Nonnull final List<ParseError> parseErrors,
        @Nonnull final InputBuffer inputBuffer)
    {
        this.matched = matched;
        this.valueStack = Objects.requireNonNull(valueStack);
        resultValue = valueStack.isEmpty() ? null : valueStack.peek();
        this.parseErrors = Objects.requireNonNull(parseErrors);
        this.inputBuffer = Objects.requireNonNull(inputBuffer);
    }


    /**
     * Return true if this parse result is a match
     *
     * @return see description
     */
    public boolean isSuccess()
    {
        return matched;
    }

    /**
     * Gets the value at the top of the stack, if any
     *
     * <p>Note that unfortunately the top of the stack can also be null, so this
     * method is not reliable.</p>
     *
     * @return see description
     */
    @Nullable
    public V getTopStackValue()
    {
        return resultValue;
    }

    /**
     * Get the value stack
     *
     * @return the value stack used during the parsing run
     */
    @Nonnull
    public ValueStack<V> getValueStack()
    {
        return valueStack;
    }

    /**
     * Get the parse errors generated by the parsing process, if any
     *
     * @return see description
     * @see #isSuccess()
     */
    @Nonnull
    public List<ParseError> getParseErrors()
    {
        return parseErrors;
    }

    /**
     * Get the input buffer used by the parsing run
     *
     * @return see description
     */
    @Nonnull
    public InputBuffer getInputBuffer()
    {
        return inputBuffer;
    }

    /**
     * Has this result collected any parse errors?
     *
     * <p><strong>note</strong>: this method does not guarantee that the result
     * is a success; for this use {@link #isSuccess()} instead.</p>
     *
     * @return true if the parse error list is not empty
     */
    // TODO: not clear whether parseErrors can be null
    public boolean hasCollectedParseErrors()
    {
        return !parseErrors.isEmpty();
    }
}

@@ -874,29 +874,25 @@
 java
-x.annotation.Nullable
+.util.Collections
 ;%0Aim
@@ -1068,683 +1068,134 @@
 %3E%0A%7B%0A
-%0A    /**%0A     * DO NOT USE DIRECTLY!%0A     *%0A     * %3Cp%3EUse %7B@link #isSuccess()%7D instead%3C/p%3E%0A     */%0A    private final boolean matched;%0A%0A    /**%0A     * DO NOT USE DIRECTLY!%0A     *%0A     * %3Cp%3EUse %7B@link #getTopStackValue()%7D instead%3C/p%3E%0A     */%0A    private final V resultValue;%0A%0A    /**%0A     * DO NOT USE DIRECTLY!%0A     *%0A     * %3Cp%3EUse %7B@link #getValueStack()%7D instead%3C/p%3E%0A     */%0A    private final ValueStack%3CV%3E valueStack;%0A%0A    /**%0A     * DO NOT USE DIRECTLY!%0A     *%0A     * %3Cp%3EUse %7B@link #getParseErrors()%7D instead%3C/p%3E%0A     */%0A    private final List%3CParseError%3E parseErrors;%0A%0A    /**%0A     * DO NOT USE DIRECTLY!%0A     *%0A     * %3Cp%3EUse %7B@link #getInputBuffer()%7D instead%3C/p%3E%0A     */
+    private final boolean matched;%0A    private final ValueStack%3CV%3E valueStack;%0A    private final List%3CParseError%3E parseErrors;
 %0A   
@@ -1807,79 +1807,8 @@
 k);%0A
-        resultValue = valueStack.isEmpty() ? null : valueStack.peek();%0A
     
@@ -2192,154 +2192,141 @@
   * 
-%3Cp%3ENote that unfortunately the top of the stack can also be null, so this%0A     * method is not reliable.%3C/p%3E%0A     *%0A     * @return see description
+@return the value at the top of the stack%0A     * @throws IllegalArgumentException stack is empty%0A     *%0A     * @see ValueStack#peek()
 %0A   
@@ -2340,15 +2340,14 @@
   @N
+onn
 ull
-able
 %0A   
@@ -2400,19 +2400,25 @@
 urn 
-resultValue
+valueStack.peek()
 ;%0A  
@@ -2852,16 +2852,45 @@
  return 
+Collections.unmodifiableList(
 parseErr
@@ -2888,24 +2888,25 @@
 (parseErrors
+)
 ;%0A    %7D%0A%0A   

change the API