/*
* Copyright (C) 2014 Civilian Framework.
*
* Licensed under the Civilian License (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.civilian-framework.org/license.txt
*
* 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.civilian.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.civilian.request.RequestHeaders;
import org.civilian.response.ResponseHeaders;
import org.civilian.type.Type;
import org.civilian.type.fn.StandardSerializer;
import org.civilian.util.ArrayUtil;
import org.civilian.util.Check;
import org.civilian.util.ClassUtil;
import org.civilian.util.Iterators;
import org.civilian.util.Value;
/**
* ParamList is a helper class to build parameter or header
* lists used in request or response implementations.
*/
public class ParamList implements RequestHeaders, ResponseHeaders
{
private static final String[] EMPTY_VALUES = new String[0];
public static final ParamList EMPTY = new ParamList(false, Collections.<String, String[]>emptyMap() /*immutable*/);
public ParamList()
{
this(false);
}
public ParamList(boolean caseInsensitiveNames)
{
this(caseInsensitiveNames, null);
}
public ParamList(boolean caseInsensitiveNames, Map<String,String[]> map)
{
caseInsensitiveNames_ = caseInsensitiveNames;
map_ = map;
}
public void clear()
{
map_ = null;
}
@Override public boolean contains(String name)
{
return map_ != null ? get(name) != null : false;
}
@Override public boolean is(String name, String value)
{
return ClassUtil.equals(get(name), value);
}
@Override public String get(String name)
{
String[] v = map_ != null ? map_.get(normName(name)) : null;
if (v == null)
return getNext(name);
else if (v.length > 0)
return v[0];
else
return null;
}
/**
* Allows chaining of ParamLists.
* The default implementation returns false
*/
protected String getNext(String name)
{
return null;
}
/**
* Allows chaining of ParamLists.
* The default implementation returns -1L.
*/
protected long getDateNext(String name)
{
return -1L;
}
@Override public String[] getAll(String name)
{
String[] v = map_ != null ? map_.get(normName(name)) : null;
if (v == null)
v = getNextAll(name);
return v != null ? v : EMPTY_VALUES;
}
/**
* Allows chaining of ParamLists.
* The default implementation returns null.
*/
protected String[] getNextAll(String name)
{
return null;
}
@Override public int getInt(String name)
{
String s = get(name);
if (s == null)
return -1;
try
{
return Integer.parseInt(s);
}
catch(NumberFormatException e)
{
throw new IllegalArgumentException("not a int value '" + s + "'", e);
}
}
@Override public long getDate(String name)
{
if (map_ != null)
{
String[] s = map_.get(normName(name));
if ((s != null) && (s.length > 0))
{
String v = s[0];
try
{
return Long.parseLong(v);
}
catch(NumberFormatException e)
{
throw new IllegalArgumentException("not a date value '" + v + "'", e);
}
}
}
return getDateNext(name);
}
@Override public <T> Value<T> get(String name, Type<T> type)
{
return new Value<>(type, get(name), StandardSerializer.INSTANCE);
}
@Override public Iterator<String> iterator()
{
Iterator<String> thisNames = map_ != null ? map_.keySet().iterator() : null;
Iterator<String> nextNames = getNextNames();
if ((thisNames != null) && (nextNames != null))
return Iterators.unique(Iterators.join(thisNames, nextNames));
else if (nextNames != null)
return nextNames;
else if (thisNames != null)
return thisNames;
else
return Iterators.empty();
}
/**
* Allows chaining of ParamLists.
* The default implementation returns an empty array.
*/
protected Iterator<String> getNextNames()
{
return null;
}
@Override public void set(String name, String... values)
{
if (values == null)
values = EMPTY_VALUES;
getMap().put(normName(name), values);
}
@Override public void setDate(String name, long value)
{
set(name, String.valueOf(value));
}
@Override public void setInt(String name, int value)
{
set(name, String.valueOf(value));
}
public void setNull(String name)
{
set(name, (String[])null);
}
@Override public void add(String name, String value)
{
if (value != null)
{
name = normName(name);
String[] v = getAll(name);
set(name, ArrayUtil.addLast(v, value));
}
}
@Override public void addDate(String name, long value)
{
add(name, String.valueOf(value));
}
@Override public void addInt(String name, int value)
{
add(name, String.valueOf(value));
}
public Map<String, String[]> getMap()
{
if (map_ == null)
map_ = new HashMap<>();
return map_;
}
private String normName(String name)
{
Check.notNull(name, "name");
return caseInsensitiveNames_ ? name.toLowerCase() : name;
}
private boolean caseInsensitiveNames_;
private Map<String,String[]> map_;
}