//////////////////////////////////////////////////////////////////////////
// Complex
//////////////////////////////////////////////////////////////////////////
/// <summary>
/// complex := type [fields]
/// fields := "{" field (eos field)* "}"
/// field := name "=" obj
/// </summary>
private object readComplex(int line, Type t, bool root)
{
Map toSet = new Map(Sys.FieldType, Sys.ObjType.toNullable());
List toAdd = new List(Sys.ObjType.toNullable());
// read fields/collection into toSet/toAdd
readComplexFields(t, toSet, toAdd);
// get the make constructor
Method makeCtor = t.method("make", false);
if (makeCtor == null || !makeCtor.isPublic())
throw err("Missing public constructor " + t.qname() + ".make", line);
// get argument lists
List args = null;
if (root && options != null)
args = (List)options.get("makeArgs");
// construct object
object obj = null;
bool setAfterCtor = true;
try
{
// if first parameter is an function then pass toSet
// as an it-block for setting the fields
Param p = (Param)makeCtor.@params().first();
if (args == null && p != null && p.type().fits(Sys.FuncType))
{
args = new List(Sys.ObjType).add(Field.makeSetFunc(toSet));
setAfterCtor = false;
}
// invoke make to construct object
obj = makeCtor.callList(args);
}
catch (System.Exception e)
{
throw err("Cannot make " + t + ": " + e, line, e);
}
// set fields (if not passed to ctor as it-block)
if (setAfterCtor && toSet.size() > 0)
{
IDictionaryEnumerator en = toSet.pairsIterator();
while (en.MoveNext())
{
complexSet(obj, (Field)en.Key, en.Value, line);
}
}
// add
if (toAdd.size() > 0)
{
Method addMethod = t.method("add", false);
if (addMethod == null) throw err("Method not found: " + t.qname() + ".add", line);
for (int i=0; i<toAdd.sz(); ++i)
complexAdd(t, obj, addMethod, toAdd.get(i), line);
}
return obj;
}