001package org.unix4j.codegen.def; 002 003import java.lang.reflect.Field; 004import java.lang.reflect.Modifier; 005import java.util.LinkedHashMap; 006import java.util.Map; 007 008import freemarker.template.ObjectWrapper; 009import freemarker.template.TemplateHashModel; 010import freemarker.template.TemplateModel; 011import freemarker.template.TemplateModelException; 012 013/** 014 * Abstract base class for all element definitions. Public fields define visible 015 * properties or nested elements. 016 */ 017abstract public class AbstractElementDef implements TemplateHashModel { 018 019 private Map<String, Field> fields; 020 021 private final Map<String, Field> getFields() { 022 if (fields == null) { 023 fields = initFields(); 024 } 025 return fields; 026 } 027 private final Map<String, Field> initFields() { 028 final Map<String, Field> fields = new LinkedHashMap<String, Field>(); 029 for (final Field field : getClass().getFields()) { 030 if (0 == (field.getModifiers() & Modifier.STATIC)) { 031 fields.put(field.getName(), field); 032 } 033 } 034 return fields; 035 } 036 037 @Override 038 public boolean isEmpty() throws TemplateModelException { 039 return getFields().isEmpty(); 040 } 041 042 @Override 043 public TemplateModel get(String key) throws TemplateModelException { 044 final Object value = getFieldValue(key); 045 if (value instanceof TemplateModel) { 046 return (TemplateModel) value; 047 } 048 return value == null ? null : ObjectWrapper.DEFAULT_WRAPPER.wrap(value); 049 } 050 051 public Object getFieldValue(String name) { 052 final Field field = getFields().get(name); 053 try { 054 return field == null ? null : field.get(this); 055 } catch (Exception e) { 056 return "ERROR: cannot read field " + field.getName() + "e=" + e; 057 } 058 } 059 060 @Override 061 public String toString() { 062 return toMap().toString(); 063 } 064 065 public Map<String, Object> toMap() { 066 final Map<String, Object> map = new LinkedHashMap<String, Object>(); 067 for (final String name : getFields().keySet()) { 068 map.put(name, getFieldValue(name)); 069 } 070 return map; 071 } 072 073 public String toString(String indent) { 074 return toMultiLineString(indent, toMap()); 075 } 076 077 protected static String toMultiLineString(String indent, Map<String, ?> map) { 078 final StringBuilder sb = new StringBuilder(); 079 int maxKeyLen = 0; 080 for (final String key : map.keySet()) { 081 maxKeyLen = Math.max(maxKeyLen, String.valueOf(key).length()); 082 } 083 for (final Map.Entry<String, ?> e : map.entrySet()) { 084 sb.append(indent).append(e.getKey()).append(": "); 085 final int keyLen = String.valueOf(e.getKey()).length(); 086 for (int i = keyLen; i < maxKeyLen; i++) { 087 sb.append(' '); 088 } 089 sb.append(e.getValue()).append('\n'); 090 } 091 return sb.toString(); 092 } 093}