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 }