use of us.parr.bookish.model.ModelElement in project bookish by parrt.
the class ModelConverter method walk.
public ST walk(OutputModelObject omo) {
if (omo == null)
return null;
// CREATE TEMPLATE FOR THIS OUTPUT OBJECT
Class<? extends OutputModelObject> cl = omo.getClass();
String templateName = cl.getSimpleName();
if (templateName == null) {
System.err.println("no model to template mapping for " + cl.getSimpleName());
return new ST("[" + templateName + " invalid]");
}
ST st = templates.getInstanceOf(templateName);
if (st == null) {
System.err.println("no model to template mapping for " + cl.getSimpleName());
return new ST("[" + templateName + " invalid]");
}
if (st.impl.formalArguments == null) {
System.err.println("no formal arguments for " + templateName);
return st;
}
// LinkedHashMap
Map<String, FormalArgument> formalArgs = st.impl.formalArguments;
// PASS IN OUTPUT MODEL OBJECT TO TEMPLATE AS FIRST ARG
Set<String> argNames = formalArgs.keySet();
Iterator<String> arg_it = argNames.iterator();
// ordered so this is first arg
String modelArgName = arg_it.next();
st.add(modelArgName, omo);
Field[] allAnnotatedFields = getAllAnnotatedFields(cl);
List<Field> modelFields = new ArrayList<>();
for (Field fi : allAnnotatedFields) {
ModelElement annotation = fi.getAnnotation(ModelElement.class);
if (annotation != null) {
modelFields.add(fi);
}
}
// Make sure all @ModelElement fields are public (ST won't see otherwise)
for (Field fi : allAnnotatedFields) {
ModelElement annotation = fi.getAnnotation(ModelElement.class);
if (annotation != null && !Modifier.isPublic(fi.getModifiers())) {
System.err.println("non-public @ModelElement in " + templateName + ": " + fi.getName());
}
}
// Ensure that @ModelElement fields match up with the parameters
{
List<String> fieldNames = map(modelFields, Field::getName);
Set<String> t = new HashSet<>(argNames);
t.remove(modelArgName);
if (!t.equals(new HashSet<>(fieldNames))) {
System.err.println("mismatch in template " + templateName + " between arguments and @ModelElement fields: " + t + "!=" + fieldNames);
}
}
// COMPUTE STs FOR EACH NESTED MODEL OBJECT MARKED WITH @ModelElement AND MAKE ST ATTRIBUTE
Set<String> usedFieldNames = new HashSet<>();
for (Field fi : modelFields) {
ModelElement annotation = fi.getAnnotation(ModelElement.class);
if (annotation == null) {
continue;
}
String fieldName = fi.getName();
if (!usedFieldNames.add(fieldName)) {
System.err.println("Model object " + omo.getClass().getSimpleName() + " has multiple fields named '" + fieldName + "'");
continue;
}
// Just don't set @ModelElement fields w/o formal arg in target ST
if (formalArgs.get(fieldName) == null)
continue;
try {
Object o = fi.get(omo);
if (o instanceof OutputModelObject) {
// SINGLE MODEL OBJECT?
OutputModelObject nestedOmo = (OutputModelObject) o;
ST nestedST = walk(nestedOmo);
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
st.add(fieldName, nestedST);
} else if (o instanceof Collection || o instanceof OutputModelObject[]) {
// LIST OF MODEL OBJECTS?
if (o instanceof OutputModelObject[]) {
o = Arrays.asList((OutputModelObject[]) o);
}
Collection<?> nestedOmos = (Collection<?>) o;
for (Object nestedOmo : nestedOmos) {
if (nestedOmo == null)
continue;
ST nestedST = walk((OutputModelObject) nestedOmo);
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
st.add(fieldName, nestedST);
}
} else if (o instanceof Map) {
Map<?, ?> nestedOmoMap = (Map<?, ?>) o;
Map<Object, ST> m = new LinkedHashMap<Object, ST>();
for (Map.Entry<?, ?> entry : nestedOmoMap.entrySet()) {
ST nestedST = walk((OutputModelObject) entry.getValue());
// System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
m.put(entry.getKey(), nestedST);
}
st.add(fieldName, m);
} else if (o != null) {
System.err.println("type of " + fieldName + "'s model element isn't recognized: " + o.getClass().getSimpleName());
}
} catch (IllegalAccessException iae) {
System.err.printf("code generation template <%s> has missing, misnamed, or incomplete arg list; missing <%s>\n", templateName, fieldName);
}
}
// st.impl.dump();
return st;
}
Aggregations