source: trunk/docx4j/src/main/java/org/docx4j/utils/AbstractTraversalUtilVisitorCallback.java @ 1479

Revision 1479, 3.2 KB checked in by jharrop, 13 months ago (diff)

Alberto's extension to TraversalUtil?, which allows you to define the tag you are interested in as a generic of the visitor class.

Line 
1package org.docx4j.utils;
2
3import java.lang.reflect.ParameterizedType;
4import java.lang.reflect.Type;
5import java.lang.reflect.TypeVariable;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
9
10import org.docx4j.TraversalUtil;
11import org.docx4j.XmlUtils;
12
13/** @author alberto */
14public abstract class AbstractTraversalUtilVisitorCallback extends TraversalUtil.CallbackImpl {
15       
16        /**
17         * Get the actual type arguments a child class has used to extend a generic base class.
18         * based on http://www.artima.com/weblogs/viewpost.jsp?thread=208860
19         */
20        protected Class findClassParameter(Class childClass) {
21    Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
22    Type type = childClass;
23            // start walking up the inheritance hierarchy until we hit baseClass
24            while (! getTypeClass(type).equals(TraversalUtilVisitor.class)) {
25                if (type instanceof Class) {
26                        // there is no useful information for us in raw types, so just keep going.
27                        type = ((Class) type).getGenericSuperclass();
28                }
29                else {
30                        ParameterizedType parameterizedType = (ParameterizedType) type;
31                        Class<?> rawType = (Class)parameterizedType.getRawType();
32                        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
33                        TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
34                        for (int i = 0; i < actualTypeArguments.length; i++) {
35                          resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
36                        }
37                 
38                        if (!rawType.equals(TraversalUtilVisitor.class)) {
39                          type = rawType.getGenericSuperclass();
40                        }
41                }
42            }
43           
44            // finally, for each actual type argument provided to baseClass, determine (if possible)
45            // the raw class for that type argument.
46            Type baseType =
47                (type instanceof Class ?
48                        ((Class)type).getTypeParameters()[0] :
49                        ((ParameterizedType)type).getActualTypeArguments()[0]);
50           
51            // resolve types by chasing down type variables.
52            while (resolvedTypes.containsKey(baseType)) {
53                baseType = resolvedTypes.get(baseType);
54            }
55            return getTypeClass(baseType);
56        }
57
58   
59        protected Class getTypeClass(Type type) {
60        return (type instanceof Class ?
61                        (Class)type :
62                        (type instanceof ParameterizedType ?
63                         getTypeClass(((ParameterizedType) type).getRawType()) : null));
64        } 
65
66        // Depth first
67        @Override
68        public void walkJAXBElements(Object parent) {
69        List children = getChildren(parent);
70                if (children != null) {
71                        for (Object o : children) {
72                                // if its wrapped in javax.xml.bind.JAXBElement, get its
73                                // value; this is ok, provided the results of the Callback
74                                // won't be marshalled
75                                o = XmlUtils.unwrap(o);
76                                this.apply(o, parent, children);
77                                if (this.shouldTraverse(o)) {
78                                        walkJAXBElements(o);
79                                }
80                        }
81                }
82        }
83
84        @Override
85        public final List<Object> apply(Object o) {
86                throw new UnsupportedOperationException("Invalid apply method - Abstract traversal util should use apply(Object child, Object parent, List siblings)");
87        }
88       
89        protected abstract List<Object> apply(Object child, Object parent, List children);
90
91}
Note: See TracBrowser for help on using the repository browser.