/*
 * Copyright 2012 Splunk, Inc.
 *
 * 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 com.splunk;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Wraps an individual event or result returned by
 * {@link ResultsReader#getNextEvent()}.
 * 
 * An event maps each field name to a list of zero of more values.
 * If accessed as a {@link Map}, the values are encoded as a delimited
 * string. If accessed via {@link #getArray(String, String)} or 
 * {@link #getArray(String)}, the values are returned as a {@code String[]}.
 * 
 * The delimiter for field values depends on the underlying result format.
 * If the underlying format does not specify a delimiter, such as with
 * {@link ResultsReaderXml}, the delimiter is comma (,). 
 */
public class Event extends HashMap<String, String> {
    private Map<String, String[]> arrayValues = new HashMap<String, String[]>();
    
    /**
     * Returns the single value or delimited set of values for the specified
     * field name, or {@code null} if the specified field is not present.
     */
    public String get(String key) {
        return super.get(key);
    }
    
    /**
     * Sets the single value or delimited set of values for the specified
     * field name.
     * 
     * When setting a multi-valued field, {@link #putArray(String, String[])}
     * is recommended instead.
     */
    public String put(String key, String valueOrDelimitedValues) {
        return super.put(key, valueOrDelimitedValues);
    }
    
    /**
     * Sets the value(s) for the specified field name.
     */
    public void putArray(String key, String[] values) {
        super.put(key, Util.join(",", values)); // for backward compatibility
        arrayValues.put(key, values);
    }
    
    /**
     * Gets the value(s) for the specified field name.
     * 
     * <b>Caution:</b> This variant of {@link #getArray(String, String)} is
     * unsafe for {@link ResultsReader} implementations that require a
     * delimiter. Therefore this method should only be used for results
     * returned by {@link ResultsReaderXml}. For other readers, use
     * {@link #getArray(String, String)} instead.
     */
    public String[] getArray(String key) {
        String[] arrayValue = arrayValues.get(key);
        if (arrayValue != null) {
            return arrayValue;
        }
        
        String singleValue = super.get(key);
        if (singleValue == null) {
            return null;
        }
        return new String[] { singleValue };
    }
    
    /**
     * Gets the value(s) for the specified field name.
     * 
     * The delimiter must be determined empirically based on the search
     * string and the data format of the index. The delimiter can differ
     * between fields in the same {@link Event}.
     * 
     * The delimiter is ignored for {@link ResultsReader} implementations
     * that do not require a delimiter, such as {@link ResultsReaderXml}.
     */
    public String[] getArray(String key, String delimiter) {
        String[] arrayValue = arrayValues.get(key);
        if (arrayValue != null) {
            return arrayValue;
        }
        
        String delimitedValues = super.get(key);
        if (delimitedValues == null) {
            return null;
        }
        return delimitedValues.split(Pattern.quote(delimiter));
    }
}

@@ -866,216 +866,183 @@
 %0A * 
-If accessed as a %7B@link Map%7D, the values are encoded as a delimited%0A * string. If accessed via %7B@link #getArray(String, String)%7D or %0A * %7B@link #getArray(String)%7D, the value
+These values can be accessed as either an array (via %7B@link #getArray%7D or%0A * as a delimited string (via %7B@link #get%7D). It i
 s 
-a
 re
- returned as a %7B@code String%5B%5D%7D
+commended to access as an%0A * array when possible
 .%0A *
@@ -1245,17 +1245,16 @@
 mma (,).
- 
 %0A */%0Apub
@@ -1548,16 +1548,160 @@
 resent.%0A
+     * %0A     * When getting a multi-valued field, %7B@link #getArray(String)%7D or%0A     * %7B@link #getArray(String, String)%7D is recommended instead.%0A
      */%0A
@@ -2196,24 +2196,87 @@
 field name.%0A
+     * %0A     * The value delimiter is assumed to be comma (,).%0A
      */%0A    
@@ -2339,52 +2339,59 @@
     
-super.put(key, Util.join(%22,%22, values));
+arrayValues.put(key, values);%0A        %0A       
  // 
-f
+F
 or b
@@ -2415,36 +2415,68 @@
 lity
-%0A        arrayValues.put(key
+ with the Map interface%0A        super.put(key, Util.join(%22,%22
 , va
@@ -2476,24 +2476,25 @@
 %22,%22, values)
+)
 ;%0A    %7D%0A    

Improve documentation.