View Javadoc

1   package org.kite9.diagram.builders;
2   
3   import java.lang.reflect.GenericArrayType;
4   import java.lang.reflect.ParameterizedType;
5   import java.lang.reflect.Type;
6   import java.util.Collection;
7   import java.util.Stack;
8   
9   import org.kite9.framework.alias.Aliaser;
10  import org.kite9.framework.common.Kite9ProcessingException;
11  
12  public class ValueHelper {
13  
14      Unraveller[] unravellers = new Unraveller[] {
15  	    new CollectionUnraveller(),
16  	    new ArrayUnraveller(),
17      };
18      
19      public static class ToEnd {
20      
21          private Stack<String> labels = new Stack<String>();
22          Object to;
23      
24      }
25  
26      protected static interface Unraveller {
27      
28      	boolean unravel(ToEnd to, Aliaser a);
29      
30          }
31  
32      public ToEnd setupToEnd(Object to, Aliaser a) {
33          ToEnd toEnd = new ToEnd();
34          toEnd.to = to;
35      
36          unravel(toEnd, a);
37          
38          return toEnd;
39      }
40  
41      public String generateArrowLabel(ToEnd toEnd) {
42          StringBuilder sb = new StringBuilder();
43          for (int i = toEnd.labels.size()-1; i>=0; i--) {
44              if (i>0) {
45          	sb.insert(0, " of "+toEnd.labels.get(i)+"s");
46              } else {
47          	sb.insert(0, toEnd.labels.get(i));
48              }
49          }
50          
51          
52          return sb.toString();
53      }
54  
55      public String generateTextLineLabel(ToEnd toEnd, String toClass) {
56          StringBuilder sb = new StringBuilder();
57          for (int i = toEnd.labels.size()-1; i>=0; i--) {
58              if (i>0) {
59          	sb.insert(0, " of "+toEnd.labels.get(i)+"s");
60              } else {
61          	sb.insert(0, toEnd.labels.get(i));
62              }
63          }
64          
65          if (toEnd.labels.size()>0) {
66              sb.append(" of ");
67              sb.append(toClass);
68              sb.append("s");
69          } else {
70              sb.append(toClass);
71          }
72          
73          return sb.toString();
74      }
75  
76      private void unravel(ToEnd toEnd, Aliaser a) {
77          boolean cont = true;
78          while (cont) {
79              cont = false;
80              for (Unraveller u : unravellers) {
81          	cont = cont || u.unravel(toEnd, a);
82              }
83          }        
84      }
85  
86      public static class CollectionUnraveller implements Unraveller {
87      
88          public boolean unravel(ToEnd to, Aliaser a) {
89              if (to.to instanceof ParameterizedType) {
90          	ParameterizedType pt = (ParameterizedType) to.to;
91          	Type raw = pt.getRawType();
92          	Type[] args = pt.getActualTypeArguments();
93          	if ((raw instanceof Class<?>) && (Collection.class.isAssignableFrom((Class<?>) raw))) {
94          		if (args.length != 1) {
95          		    throw new Kite9ProcessingException("Could not handle collection with more than one type argument: "
96          			    + to);
97          		} else {
98          		    to.to = args[0];
99          		    to.labels.push(a.getAlias(pt));
100         		    return true;
101         		}
102         	}
103     	    }
104             
105             return false;
106         }
107     
108     }
109 
110     public static class ArrayUnraveller implements Unraveller {
111     
112         public boolean unravel(ToEnd to, Aliaser a) {
113             if (to.to instanceof GenericArrayType) {
114         	GenericArrayType gt = (GenericArrayType) to.to;
115         	Type raw = gt.getGenericComponentType();
116         	to.to = raw;
117         	to.labels.push("array");
118         	return true;
119     	    } else if ((to.to instanceof Class<?>) && (((Class<?>)to.to).isArray())) {
120     		to.labels.push("array");
121     		to.to = ((Class<?>)to.to).getComponentType();
122     		return true;
123     	    }
124             
125             return false;
126         }
127     
128     }
129   
130     public ValueHelper() {
131 	super();
132     }
133 
134 }