Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.dyuproject.fbsgen.compiler.Writable Maven / Gradle / Ivy
//========================================================================
//Copyright 2013 David Yu
//------------------------------------------------------------------------
//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.dyuproject.fbsgen.compiler;
import static com.dyuproject.fbsgen.compiler.CompilerUtil.$int;
import static com.dyuproject.fbsgen.compiler.TemplatedCodeGenerator.FORMAT_DELIM;
import static com.dyuproject.fbsgen.compiler.TemplatedCodeGenerator.chainedFormat;
import static com.dyuproject.fbsgen.compiler.TemplatedCodeGenerator.format;
import com.dyuproject.fbsgen.parser.Annotation;
import com.dyuproject.fbsgen.parser.AnnotationContainer;
import com.dyuproject.fbsgen.parser.HasName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Allows string templates to write/modify the members of this class.
*
* @author David Yu
* @created Aug 10, 2013
*/
public final class Writable
{
/**
* Map used against the procedures of {@link Writable}.
*/
@SuppressWarnings("serial")
static final class NewMap extends HashMap {}
static final FakeMap EMPTY = new FakeMap("EMPTY")
{
@Override
public Object get(Object arg0)
{
return "";
}
};
public Object key = null, val = null;
public int number = 0;
public final StringBuilder builder = new StringBuilder(),
builder2 = new StringBuilder();
public final ArrayList list = new ArrayList();
public final LinkedHashMap map = new LinkedHashMap();
int argCount = 0, argFalseCount = 0;
/**
* Cast the argument as integer.
*
* «writable.as_int.("1")»
*
*/
public final FakeMap as_int = new FakeMap("as_int")
{
public Object get(Object entry)
{
return entry instanceof Integer ? entry :
Integer.parseInt(String.valueOf(entry));
}
};
/**
* Appends the arg to the string builder.
*
* «writable.b.("a").b.("b").str»
*
*/
public final FakeMap b = new FakeMap("b")
{
public Object get(Object arg)
{
if (arg != null)
builder.append(arg.toString());
return Writable.this;
}
};
/**
* Appends the arg to the string builder.
*
* «writable.b2.("a").b2.("b").str2»
*
*/
public final FakeMap b2 = new FakeMap("b2")
{
public Object get(Object arg)
{
if (arg != null)
builder2.append(arg.toString());
return Writable.this;
}
};
/**
* Appends the arg to the string builder if val is truthy.
*
* «writable.v.(true).b.("a").bvt.("b").»
*
*/
public final FakeMap bvt = new FakeMap("bvt")
{
public Object get(Object arg)
{
if (arg != null && val != null && !Boolean.FALSE.equals(val))
builder.append(arg.toString());
return Writable.this;
}
};
/**
* Appends the arg to the string builder if val is not truthy.
*
* «writable.v.(false).b.("a").bvf.("b").»
*
*/
public final FakeMap bvf = new FakeMap("bvf")
{
public Object get(Object arg)
{
if (arg != null && (val == null || Boolean.FALSE.equals(val)))
builder.append(arg.toString());
return Writable.this;
}
};
/**
* Get the element at index from list if k was set. Otherwise, the arg will
* be read as 'key.0' where 'key' is used to retrieve the list from the map
* and '0' is the index.
*
* «writable.k.("0").get.(message.fields)»
* «writable.k.(1).get.(message.fields)»
* «(writable.get.("key.0"))»
*
*/
public final FakeMap get = new FakeMap("get")
{
@SuppressWarnings("unchecked")
public Object get(Object entry)
{
if (key != null)
{
int index = key instanceof Number ?
((Number)key).intValue() : Integer.parseInt(
key.toString());
key = null;
return entry instanceof List ? $get(index, (List)entry) : null;
}
if (entry == null)
return null;
// key.0
String param = entry.toString();
int dot = param.indexOf('.');
if (dot == -1)
return null;
int index = Integer.parseInt(param.substring(dot+1));
String key = param.substring(0, dot);
Object val = map.get(key);
return val instanceof List ? $get(index, (List)val) : null;
}
};
/**
* Get the element at index from list.
*
* «writable.n.(1).get_from.(message.fields)»
*
*/
public final FakeMap get_from = new FakeMap("get_from")
{
@SuppressWarnings("unchecked")
public Object get(Object entry)
{
return $get(number, (List)entry);
}
};
/**
* Get the element at index (one-based, so we deduct 1) from list.
*
* «writable.n.(1).get_from1.(message.fields)»
*
*/
public final FakeMap get_from1 = new FakeMap("get_from1")
{
@SuppressWarnings("unchecked")
public Object get(Object entry)
{
return $get(number - 1, (List)entry);
}
};
static Object $get(int index, List list)
{
if (index < 0 && (index = list.size() + index) < 0)
return null;
return list.size() > index ? list.get(index) : null;
}
/**
* Sets the first element of the list.
*
* «writable.set0.("foo")»
*
*/
public final FakeMap set0 = new FakeMap("set0")
{
public Object get(Object entry)
{
if (list.isEmpty())
list.add(entry);
else
list.set(0, entry);
return Writable.this;
}
};
/**
* Returns the key if arg is null.
*
* «writable.k.(field.name).kunless.(map.("field"))»
*
*/
public final FakeMap kunless = new FakeMap("kunless")
{
public Object get(Object arg)
{
Object k = key;
key = null;
return arg == null ? k : arg;
}
};
/**
* Returns the val if arg is null.
*
* «writable.v.(field.name).vunless.(map.("field"))»
*
*/
public final FakeMap vunless = new FakeMap("vunless")
{
public Object get(Object arg)
{
return arg == null ? val : arg;
}
};
/**
* Returns the arg if val is null.
*
* «writable.v.(message).velse.(foo)»
*
*/
public final FakeMap velse = new FakeMap("velse")
{
public Object get(Object arg)
{
return val == null ? arg : val;
}
};
/**
* Formats the val with the arg.
*
* «writable.v.(message.name).vfmt.("UC")»
*
*/
public final FakeMap vfmt = new FakeMap("vfmt")
{
public Object get(Object entry)
{
if (val == null)
throw new RuntimeException("Misuse of chain (val must not be null).");
String formatName = entry.toString(),
str = val.toString();
String[] formats = FORMAT_DELIM.split(formatName);
return formats.length == 0 ? format(str, formatName) :
chainedFormat(str, formats);
}
};
/**
* Compares the number against the arg.
*
* «writable.n.(0).eq.(0)»
*
*/
public final FakeMap eq = new FakeMap("eq")
{
public Object get(Object arg)
{
if (arg instanceof String)
{
String str = (String)arg;
return !str.isEmpty() && number == Integer.parseInt(str) ?
Boolean.TRUE : Boolean.FALSE;
}
return arg instanceof Integer && number == ((Integer)arg).intValue() ?
Boolean.TRUE : Boolean.FALSE;
}
};
/**
* Adds the number with the arg.
*
* «writable.n.(0).plus.(1)»
*
*/
public final FakeMap plus = new FakeMap("plus")
{
public Object get(Object entry)
{
return number + $int(entry);
}
};
/**
* Subtracts the number with the arg.
*
* «writable.n.(0).minus.(1)»
*
*/
public final FakeMap minus = new FakeMap("minus")
{
public Object get(Object entry)
{
return number - $int(entry);
}
};
/**
* Divides the number with the arg.
*
* «writable.n.(4).div.(2)»
*
*/
public final FakeMap div = new FakeMap("div")
{
public Object get(Object entry)
{
return number / $int(entry);
}
};
/**
* Multiplies the number with the arg.
*
* «writable.n.(4).mul.(2)»
*
*/
public final FakeMap mul = new FakeMap("mul")
{
public Object get(Object entry)
{
return number * $int(entry);
}
};
/**
* The operator "<<" applied to the number with the arg.
*
* «writable.n.("1").lshift.("2")»
*
*/
public final FakeMap lshift = new FakeMap("lshift")
{
public Object get(Object arg)
{
return number << $int(arg);
}
};
/**
* The operator "<<" applied to the number with the arg.
*
* «writable.n.("2").rshift.("1")»
*
*/
public final FakeMap rshift = new FakeMap("rshift")
{
public Object get(Object arg)
{
return number >>> $int(arg);
}
};
/**
* Compares the number against the arg.
*
* «writable.n.(0).gt.(0)»
*
*/
public final FakeMap gt = new FakeMap("gt")
{
public Object get(Object entry)
{
return number > $int(entry);
}
};
/**
* Compares the number against the arg.
*
* «writable.n.(0).gte.(0)»
*
*/
public final FakeMap gte = new FakeMap("gte")
{
public Object get(Object entry)
{
return number >= $int(entry);
}
};
/**
* Compares the number against the arg.
*
* «writable.n.(0).lt.(0)»
*
*/
public final FakeMap lt = new FakeMap("lt")
{
public Object get(Object entry)
{
return number < $int(entry);
}
};
/**
* Compares the number against the arg.
*
* «writable.n.(0).lte.(0)»
*
*/
public final FakeMap lte = new FakeMap("lte")
{
public Object get(Object entry)
{
return number <= $int(entry);
}
};
/**
* Compares the value against the arg.
*
* «writable.v.("foo").veq.("foo")»
*
*/
public final FakeMap veq = new FakeMap("veq")
{
public Object get(Object arg)
{
if (arg == null && val == null)
return true;
else
return arg != null && arg.equals(val);
}
};
/**
* Compares the key against the arg.
*
* «writable.k.("foo").keq.("foo")»
*
*/
public final FakeMap keq = new FakeMap("keq")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
Boolean ret = key.equals(arg) ? Boolean.TRUE : Boolean.FALSE;
key = null;
return ret;
}
};
/**
* Compares the key against the arg via identify.
*
* «writable.k.(foo).ksame.(bar)»
*
*/
public final FakeMap ksame = new FakeMap("ksame")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
Boolean ret = key == arg ? Boolean.TRUE : Boolean.FALSE;
key = null;
return ret;
}
};
/**
* Removes a prefix of the key based on the arg.
*
* «writable.k.("foo").ksubstr.("fo")»
*
*/
public final FakeMap ksubstr = new FakeMap("ksubstr")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (arg == null)
return k;
if (arg instanceof Integer)
{
int i = ((Integer)arg).intValue();
return i < 0 ? k.substring(0, k.length()+i) : k.substring(0, i);
}
final String sub = arg.toString();
return k.startsWith(sub) ? k.substring(sub.length()) : k;
}
};
/**
* Appends the current key with the arg.
*
* «writable.k.("foo").kappend.("bar")»
*
*/
public final FakeMap kappend = new FakeMap("kappend")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (arg == null)
return k;
return k + arg.toString();
}
};
/**
* Appends the current key with val if arg is true.
*
* «writable.k.("foo").v.(".bar").kappendv.(true)»
*
*/
public final FakeMap kappendv = new FakeMap("kappendv")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (arg == null || Boolean.FALSE.equals(arg))
return k;
return k + val.toString();
}
};
/**
* Prepends the current key with the arg.
*
* «writable.k.("foo").kprepend.("bar")»
*
*/
public final FakeMap kprepend = new FakeMap("kprepend")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (arg == null)
return k;
return arg.toString() + k;
}
};
/**
* Prepends the current key with val if arg is true.
*
* «writable.v.("foo.").k.("bar").kprependv.(true)»
*
*/
public final FakeMap kprependv = new FakeMap("kprependv")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (arg == null || Boolean.FALSE.equals(arg))
return k;
return val.toString() + k;
}
};
/**
* Formats the current key with arg as the format.
*
* «writable.k.("foo").kfmt.("bar")»
*
*/
public final FakeMap kfmt = new FakeMap("kfmt")
{
public Object get(Object arg)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (arg == null)
return k;
String formatName = arg.toString();
String[] formats = FORMAT_DELIM.split(formatName);
return formats.length == 0 ? format(k, formatName) :
chainedFormat(k, formats);
}
};
/**
* Returns true if the key is found in the arg.
*
* «writable.k.("foo").kin.("hellofooworld")»
* «writable.k.("foo").kin.(map_or_annotation)»
*
*/
public final FakeMap kin = new FakeMap("kin")
{
public Object get(Object entry)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
final String k = key.toString();
key = null;
if (entry == null)
return Boolean.FALSE;
if (entry instanceof Annotation)
return ((Annotation)entry).getP().get(k);
if (entry instanceof Map,?>)
return ((Map,?>)entry).get(k);
return -1 != entry.toString().indexOf(k);
}
};
/**
* Returns true if the key starts with the arg.
*
* «writable.k.("foo").ksw.("foo")»
*
*/
public final FakeMap ksw = new FakeMap("ksw")
{
public Object get(Object entry)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
Boolean ret = entry != null && key.toString().startsWith(entry.toString()) ?
Boolean.TRUE : Boolean.FALSE;
key = null;
return ret;
}
};
/**
* Returns true if the key ends with the arg.
*
* «writable.k.("foo").kew.("foo")»
*
*/
public final FakeMap kew = new FakeMap("kew")
{
public Object get(Object entry)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
Boolean ret = entry != null && key.toString().endsWith(entry.toString()) ?
Boolean.TRUE : Boolean.FALSE;
key = null;
return ret;
}
};
/**
* Returns true if {@link #number} & arg is not zero.
*
* «writable.n.("5").intersect.("1")»
*
*/
public final FakeMap intersect = new FakeMap("intersect")
{
public Object get(Object arg)
{
return 0 != (number & $int(arg)) ? Boolean.TRUE : Boolean.FALSE;
}
};
/**
* The operator "&=" applied to the number with the arg.
*
* «writable.n.("5").and.("7")»
*
*/
public final FakeMap and = new FakeMap("and")
{
public Object get(Object arg)
{
number &= $int(arg);
return Writable.this;
}
};
/**
* The operator "|=" applied to the number with the arg.
*
* «writable.n.("5").or.("7")»
*
*/
public final FakeMap or = new FakeMap("or")
{
public Object get(Object arg)
{
number |= $int(arg);
return Writable.this;
}
};
/**
* The operator "^=" applied to the number with the arg.
*
* «writable.n.("5").xor.("7")»
*
*/
public final FakeMap xor = new FakeMap("xor")
{
public Object get(Object arg)
{
number ^= $int(arg);
return Writable.this;
}
};
/**
* Sets the number.
*
* «(writable.setnumber.(field.number))»
*
*/
public final FakeMap setnumber = new FakeMap("setnumber")
{
public Object get(Object arg)
{
if (arg instanceof Map,?>)
number = ((Map,?>)arg).size();
else if (arg instanceof Collection>)
number = ((Collection>)arg).size();
else
number = $int(arg);
return Writable.this;
}
};
/**
* Increments the number.
*
* «(writable.incby.("2"))»
*
*/
public final FakeMap incby = new FakeMap("incby")
{
public Object get(Object arg)
{
number += $int(arg);
return Writable.this;
}
};
/**
* Decrements the number.
*
* «(writable.decby.("2")»
*
*/
public final FakeMap decby = new FakeMap("decby")
{
public Object get(Object arg)
{
number -= $int(arg);
return Writable.this;
}
};
/**
* Removes an item from the map.
*
* «(writable.map_remove.("foo"))»
*
*/
public final FakeMap map_remove = new FakeMap("map_remove")
{
public Object get(Object entry)
{
map.remove(entry);
return Writable.this;
}
};
/**
* Removes an item from the list.
*
* «(writable.list_remove.(writable.number))»
*
*/
public final FakeMap list_remove = new FakeMap("list_remove")
{
public Object get(Object entry)
{
if (entry instanceof Integer)
list.remove(((Integer)entry).intValue());
else
list.remove(entry);
return Writable.this;
}
};
/**
* The arg is evaluated.
*
* «if(writable.arg.({«message.o.("foo")»}).arg(message.o.({«message.o.("bar")»})).andArgs)»
*
*/
public final FakeMap arg = new FakeMap("arg")
{
public Object get(Object arg)
{
argCount++;
if (arg.toString().isEmpty())
argFalseCount++;
return Writable.this;
}
};
/**
* The arg is evaluated.
*
* «if(writable.notarg.({«message.o.("foo")»}).notarg(message.o.({«message.o.("bar")»})).andArgs)»
*
*/
public final FakeMap notarg = new FakeMap("notarg")
{
public Object get(Object arg)
{
argCount++;
if (!arg.toString().isEmpty())
argFalseCount++;
return Writable.this;
}
};
/**
* Checks if the key is inside the arg.
*
* «if(writable.k.("foo").in.(message.o).k.("bar").in.(message.o).andArgs)»
*
*/
public final FakeMap in = new FakeMap("in")
{
public Object get(Object map)
{
final Object k = key;
if (k == null)
throw new RuntimeException("Misuse of chain.");
key = null;
argCount++;
if (!((Map,?>)map).containsKey(k))
argFalseCount++;
return Writable.this;
}
};
/**
* Checks if the key is not inside the arg.
*
* «if(writable.k.("foo").notin.(message.o).k.("bar").notin.(message.o).andArgs)»
*
*/
public final FakeMap notin = new FakeMap("notin")
{
public Object get(Object map)
{
final Object k = key;
if (k == null)
throw new RuntimeException("Misuse of chain.");
key = null;
argCount++;
if (((Map,?>)map).containsKey(k))
argFalseCount++;
return Writable.this;
}
};
/**
* Sets the key.
*
* «writable.setkey.("key").put.("value")».
*
* You can also chain it continuously as long as its the order is key->value.
* «writable.k.("k1").put.("v1").k.("k2").put.("v2")».
*
*/
public final FakeMap setkey = new FakeMap("setkey")
{
public Object get(Object newKey)
{
if (key != null)
throw new RuntimeException("Misuse of chain.");
if (newKey == null)
throw new RuntimeException("Null key.");
key = newKey;
return Writable.this;
}
};
/**
* Sets the value.
*
* «writable.setval.("foo")»
* or
* «writable.v.("foo")».
*
*/
public final FakeMap setval = new FakeMap("setval")
{
public Object get(Object arg)
{
val = arg;
return Writable.this;
}
};
/**
* Adds to the list.
*
* «writable.add.(field)»
*
*/
public final FakeMap add = new FakeMap("add")
{
public Object get(Object entry)
{
list.add(entry);
return Writable.this;
}
};
/**
* Adds all the elements to the list.
*
* Called from stringtemplate via «(writable.addall.(field))»
*/
public final FakeMap addall = new FakeMap("addall")
{
@SuppressWarnings("unchecked")
public Object get(Object entry)
{
list.addAll((Collection)entry);
return Writable.this;
}
};
/**
* Adds to the list and puts to the map.
*
* «writable.k.(field.name).add_and_put.(field)»
*
*/
public final FakeMap add_and_put = new FakeMap("add_and_put")
{
public Object get(Object entry)
{
if (key != null)
{
$add_and_put(key, entry);
key = null;
}
else if (entry != null)
$add_and_put(entry.toString(), entry);
return Writable.this;
}
};
void $add_and_put(Object key, Object value)
{
list.add(value);
map.put(key, value);
}
/**
* Adds to the list and puts only the unique entry to the map.
*
* «writable.k.(field.name).add_and_uput.(field)»
*
*/
public final FakeMap add_and_uput = new FakeMap("add_and_uput")
{
public Object get(Object entry)
{
if (key != null)
{
$add_and_uput(key, entry);
key = null;
}
else if (entry != null)
$add_and_uput(entry.toString(), entry);
return Writable.this;
}
};
void $add_and_uput(Object key, Object value)
{
list.add(value);
if (!map.containsKey(key))
{
// unique,
map.put(key, value);
}
}
/**
* Returns a new map filled with the csv arg.
*
* «(writable.k.("foo").inc_map_value.(field))»
*
*/
public final FakeMap new_map_from_csv = new FakeMap("new_map_from_csv")
{
public Object get(Object arg)
{
if (key != null)
throw new RuntimeException("Misuse of chain.");
if (arg == null)
return Collections.EMPTY_MAP;
return CompilerUtil.fill(new LinkedHashMap(), arg.toString());
}
};
/**
* Increments the value with the arg.
*
* «(writable.k.("foo").inc_map_value.(field))»
*
*/
public final FakeMap inc_map_value = new FakeMap("inc_map_value")
{
public Object get(Object arg)
{
final Object k = key;
if (k == null)
throw new RuntimeException("Misuse of chain.");
key = null;
Object value = map.get(k);
if (value == null)
map.put(k, arg);
else
map.put(k, ((Integer)value).intValue() + $int(arg));
return Writable.this;
}
};
/**
* Clear the map or list.
*
* «(writable.clear.(map_or_list))»
*
*/
public final FakeMap clear = new FakeMap("clear")
{
public Object get(Object entry)
{
if (key != null || entry == null)
throw new RuntimeException("Misuse of chain.");
if (entry instanceof String || entry instanceof HasName)
entry = map.get(entry.toString());
if (entry instanceof Map)
((Map,?>)entry).clear();
else if (entry instanceof Collection)
((Collection>)entry).clear();
return Writable.this;
}
};
/**
* Puts the entry into the map.
*
* «(writable.k.("foo").put.(field))»
*
*/
public final FakeMap put = new FakeMap("put")
{
public Object get(Object entry)
{
if (key != null)
{
map.put(key, entry);
key = null;
}
else if (entry != null)
map.put(entry.toString(), entry);
return Writable.this;
}
};
/**
* Puts only unique entries into the map.
*
* «(writable.k.(field.name).uput.(field))»
*
*/
public final FakeMap uput = new FakeMap("uput")
{
public Object get(Object entry)
{
if (entry instanceof NewMap)
{
final Object k = key;
if (k == null)
throw new RuntimeException("Misuse of chain.");
key = null;
// returns true if unique.
return $uput(k, k, (NewMap)entry);
}
if (key != null)
{
$uput(key, entry, map);
key = null;
}
else if (entry != null)
$uput(entry.toString(), entry, map);
return Writable.this;
}
};
boolean $uput(Object key, Object value, Map map)
{
final boolean unique = !map.containsKey(key);
if (unique)
map.put(key, value);
return unique;
}
/**
* Puts only unique entries into the map and added to list.
*
* «(writable.k.(field.name).uput_and_add.(field))»
*
*/
public final FakeMap uput_and_add = new FakeMap("uput_and_add")
{
public Object get(Object entry)
{
if (key != null)
{
$uput_and_add(key, entry);
key = null;
}
else if (entry != null)
$uput_and_add(entry.toString(), entry);
return Writable.this;
}
};
void $uput_and_add(Object key, Object value)
{
if (!map.containsKey(key))
{
// unique
map.put(key, value);
list.add(value);
}
}
/**
* The entry will be a list that contains the values that are mapped to the same key.
*
* «(writable.k.(field.name).putlist.(field))»
*
*/
public final FakeMap putlist = new FakeMap("putlist")
{
public Object get(Object entry)
{
if (key != null)
{
$putlist(key, entry);
key = null;
}
else if (entry != null)
$putlist(entry.toString(), entry);
return Writable.this;
}
};
@SuppressWarnings("unchecked")
void $putlist(Object key, Object value)
{
ArrayList existing = (ArrayList)map.get(key);
if (existing == null)
{
existing = new ArrayList();
map.put(key, existing);
}
existing.add(value);
}
/**
* Returns a sublist based on the arg.
*
* «(writable.sublist.("2"))»
*
*/
public final FakeMap sublist = new FakeMap("sublist")
{
public Object get(Object entry)
{
if (entry instanceof List)
{
List> l = (List>)entry;
return number == l.size() ? Collections.EMPTY_LIST :
l.subList(number, l.size() - number);
}
int start = $int(entry);
return start == list.size() ? Collections.EMPTY_LIST :
list.subList(start, list.size() - start);
}
};
/**
* Returns a sublist based on the arg.
*
* «(writable.pfxlist.("2"))»
*
*/
public final FakeMap pfxlist = new FakeMap("pfxlist")
{
public Object get(Object entry)
{
if (entry instanceof List)
{
List> l = (List>)entry;
return number == l.size() - 1 ? l :
l.subList(0, number + 1);
}
int inclusiveEnd = $int(entry);
return inclusiveEnd == list.size() - 1 ? list :
list.subList(0, inclusiveEnd + 1);
}
};
/**
* Returns a substring based on the arg.
*
* «writable.k.("foo").substr.("1")» // returns oo
*
*/
public final FakeMap substr = new FakeMap("substr")
{
public Object get(Object entry)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
String str = key.toString();
key = null;
int i = $int(entry);
if (i == 0)
return str;
else if (i < 0)
return str.substring(0, str.length() + i);
else
return str.substring(i);
}
};
/**
* Returns a substring based on the arg.
*
* «writable.k.("foo").pfxstr.(1)» // returns fo
*
*/
public final FakeMap pfxstr = new FakeMap("pfxstr")
{
public Object get(Object entry)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
String str = key.toString();
key = null;
int inclusiveEnd = $int(entry);
return inclusiveEnd == str.length() - 1 ? str :
str.substring(0, inclusiveEnd + 1);
}
};
/**
* Returns a substring (counting the delimiter) based on the arg.
*
* «writable.k.("foo__bar__baz").pfxstr.("1")» // returns foo__bar
*
*/
public final FakeMap pfxstr__ = new FakeMap("pfxstr__")
{
public Object get(Object entry)
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
String str = key.toString();
key = null;
int count = 1 + $int(entry), start = 0;
for (int i = 0; i < count; i++)
{
int idx = str.indexOf("__", start);
if (idx == -1)
throw new RuntimeException("No __ delimiter on " + str + " starting at " + start);
start = idx + 2;
}
return str.substring(0, start - 2);
}
};
/**
* Returns the {@link Writable} if the entry is unique.
*
* «writable.k.(field.name).unique.(field).add.(field)» // adds the field if unique
*
*/
public final FakeMap unique = new FakeMap("unique")
{
public Object get(Object entry)
{
if (key != null)
{
Object ret = $unique(key, entry);
key = null;
return ret;
}
return entry == null ? null : $unique(entry.toString(), entry);
}
};
Object $unique(Object key, Object value)
{
if (!map.containsKey(key))
{
// unique
map.put(key, value);
return this;
}
return EMPTY;
}
/**
* Fill the contents based on the key.
*
* «writable.k.("@Annotation.fK").fill.(message)»
*
* Example:
* @Annotation (f0 = "foo", f1 = "bar", f2 = "baz")
* message Foo {
* required string name = 1;
* }
*
* With the example above it is equivalent to:
* map.put("f", ["f0", "f1", "f2"])
*
* If the key is "@Annotation.fV", then it is equivalent to:
* map.put("f", ["foo", "bar", "baz"])
*
* If the key is "@Annotation.fI", then it is equivalent to:
* map.put("f", ["foo", "bar", "baz"])
* map.put("foo", 0)
* map.put("bar", 1)
* map.put("baz", 2)
*
*
*/
public final FakeMap fill = new FakeMap("fill")
{
public Object get(Object entry)
{
if (key != null)
{
Object ret = $fill(key.toString(), entry);
key = null;
return ret;
}
// the entry is the key and the target to fill will be the map/list
// of this instance.
return $fill(entry.toString(), null);
}
};
Object $fill(String key, Object value)
{
switch(key.charAt(0))
{
case ':': // returns true if the string value contains the key
return value instanceof String && -1 != value.toString().indexOf(
key.substring(1)) ? Boolean.TRUE : Boolean.FALSE;
case '@': // fills the map with entries from the annotation
{
final AnnotationContainer ac = (AnnotationContainer)value;
final int dot = key.indexOf('.');
if (dot == -1)
{
// copies the contents.
Annotation a = ac.getAnnotation(key.substring(1));
if (a != null)
map.putAll(a.getP());
return this;
}
final Annotation a = ac.getAnnotation(key.substring(1, dot));
if (a != null)
{
//map.putAll(a.getP());
int last = key.length() - 1;
switch(key.charAt(last))
{
case 'K':
{
String entry = key.substring(dot+1, last);
map.put("$" + entry, AnnotationUtil.fillKeys(
new ArrayList(), a, entry));
break;
}
case 'V':
{
String entry = key.substring(dot+1, last);
map.put("$" + entry, AnnotationUtil.fillList(
new ArrayList(), a, entry));
break;
}
case 'I':
{
String entry = key.substring(dot+1, last);
map.put("#" + entry, AnnotationUtil.fillList(
new ArrayList(), a, entry, map));
break;
}
default:
String entry = key.substring(dot+1);
map.put("$" + entry, AnnotationUtil.fillMap(
new LinkedHashMap(), a, entry));
}
}
return this;
}
}
throw new RuntimeException("Unsupported fill param: " + key);
}
/* ================================================== */
/**
* Compares the last two elements in the list.
*
* Called from stringtemplate via «writable.add.(obj1).add.(obj2).same»
*/
public boolean getSame()
{
int size = list.size();
return list.get(size-1) == list.get(size-2);
}
/**
* Compares the last two elements in the list (and removes them at the same time).
*
* Called from stringtemplate via «writable.add.(obj1).add.(obj2).popsame»
*/
public boolean getPopsame()
{
int size = list.size();
return list.remove(size-1) == list.remove(size-2);
}
public int getIncandget()
{
return ++number;
}
public int getGetandinc()
{
return number++;
}
public int getDecandget()
{
return --number;
}
public int getGetanddec()
{
return number--;
}
public Writable getInc()
{
number++;
return this;
}
public Writable getDec()
{
number--;
return this;
}
/**
* Sets the number to zero.
*/
public Writable getClearnum()
{
number = 0;
return this;
}
/**
* Shorthand to {@link #number}.
*/
public int getNum()
{
return number;
}
/**
* Shorthand to {@link #setnumber}.
*/
public FakeMap getN()
{
return setnumber;
}
/**
* Gets the list's first element (counterpart to {@link #set0}).
*/
public Object getGet0()
{
return list.get(0);
}
/**
* Shorthand to {@link #arg}.
*/
public FakeMap getA()
{
return arg;
}
/**
* Shorthand to {@link #notarg}.
*/
public FakeMap getNa()
{
return notarg;
}
/**
* Evaluates the args (added to {@link #list}).
*
* Called from stringtemplate via «if(writable.a.(""+field.o.("1")).a.(""+field.o.("2")).andArgs)»
*/
public boolean getAndArgs()
{
final boolean ret = argFalseCount == 0;
argCount = 0;
argFalseCount = 0;
return ret;
}
/**
* Evaluates the args (added to {@link #list}).
*
* Called from stringtemplate via «if(writable.a.(""+field.o.("1")).a.(""+field.o.("2")).orArgs)»
*/
public boolean getOrArgs()
{
final boolean ret = argFalseCount != argCount;
argCount = 0;
argFalseCount = 0;
return ret;
}
/* ================================================== */
/**
* Shorthand to {@link #setkey}.
*/
public FakeMap getK()
{
return setkey;
}
/**
* Shorthand to {@link #setval}.
*/
public FakeMap getV()
{
return setval;
}
/**
* Returns {@link #builder}'s toString();
*/
public String getStr()
{
String str = builder.toString();
builder.setLength(0);
return str;
}
/**
* Returns {@link #builder2}'s toString();
*/
public String getStr2()
{
String str = builder2.toString();
builder2.setLength(0);
return str;
}
public boolean isEmptyList()
{
return list.isEmpty();
}
/**
* Returns a copy of the list.
*/
public ArrayList getCopyList()
{
return new ArrayList(list);
}
/**
* Clears the list.
*/
public Writable getClearList()
{
list.clear();
return this;
}
public boolean isEmptyMap()
{
return map.isEmpty();
}
/**
* Clears the map.
*/
public Writable getClearMap()
{
map.clear();
return this;
}
/**
* Clears the map.
*/
public NewMap getNewMap()
{
return new NewMap();
}
/**
* Sets the number to zero and clears the list and map.
*/
public Writable getClearAll()
{
key = null;
number = 0;
list.clear();
map.clear();
builder.setLength(0);
builder2.setLength(0);
return this;
}
@SuppressWarnings("rawtypes")
public boolean isListAndKeySameSize()
{
if (key == null)
throw new RuntimeException("Misuse of chain.");
Object existing = map.get(key);
key = null;
if (existing instanceof Map)
return list.size() == ((Map)existing).size();
return list.size() == ((Collection)existing).size();
}
public boolean isListAndMapSameSize()
{
return list.size() == map.size();
}
@SuppressWarnings("unchecked")
public T $val(Class clazz)
{
return val != null && clazz.isAssignableFrom(val.getClass()) ? (T)val : null;
}
@SuppressWarnings("unchecked")
public T $get(Class clazz)
{
return (T)map.get(clazz.getSimpleName());
}
@SuppressWarnings("unchecked")
public T $remove(Class clazz)
{
return (T)map.remove(clazz.getSimpleName());
}
/**
* Purposely empty.
*/
public String toString()
{
return "";
}
}