Subversion Repositories hibernate-spatial

Rev

Rev 121 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
165 maesenka 1
/*
2
 * $Id: FeatureAdapter.java 165 2010-03-11 20:27:08Z maesenka $
97 maesenka 3
 *
165 maesenka 4
 * This file is part of Hibernate Spatial, an extension to the
5
 * hibernate ORM solution for geographic data.
97 maesenka 6
 *
165 maesenka 7
 * Copyright © 2007-2010 Geovise BVBA
8
 *
97 maesenka 9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 *
23
 * For more information, visit: http://www.hibernatespatial.org/
24
 */
121 maesenka 25
package org.hibernatespatial.readers;
87 maesenka 26
 
27
import org.hibernate.EntityMode;
28
import org.hibernate.metadata.ClassMetadata;
121 maesenka 29
import org.hibernate.property.Getter;
30
import org.hibernate.util.ReflectHelper;
31
import org.hibernatespatial.helper.FinderException;
32
import org.hibernatespatial.helper.GeometryPropertyFinder;
87 maesenka 33
 
165 maesenka 34
import java.lang.reflect.InvocationHandler;
35
import java.lang.reflect.Method;
36
import java.lang.reflect.Proxy;
37
 
97 maesenka 38
/**
39
 * Adapts arbitrary objects to the {@link Feature} interface using dynamic proxying.
165 maesenka 40
 *
97 maesenka 41
 * @author Karel Maesen
42
 */
87 maesenka 43
public class FeatureAdapter {
44
 
165 maesenka 45
    public static Feature adapt(Object o, ClassMetadata cf) {
87 maesenka 46
 
165 maesenka 47
        return (Feature) Proxy.newProxyInstance(o.getClass().getClassLoader(),
48
                new Class[]{Feature.class},
49
                new FeatureInvocationHandler(o, cf));
50
    }
87 maesenka 51
 
165 maesenka 52
    static private class FeatureInvocationHandler implements InvocationHandler {
53
        private final Object target;
54
        private final ClassMetadata metadata;
55
        private Method targetGeomGetter;
56
        private Method targetIdGetter;
87 maesenka 57
 
121 maesenka 58
 
165 maesenka 59
        private static final Method geomGetter;
60
        private static final Method idGetter;
61
        private static final Method attrGetter;
121 maesenka 62
 
165 maesenka 63
        private static GeometryPropertyFinder geomPropertyFinder = new GeometryPropertyFinder();
64
 
65
        static {
66
            Class featureIntf = Feature.class;
67
            try {
68
                geomGetter = featureIntf.getDeclaredMethod("getGeometry", new Class[]{});
69
                idGetter = featureIntf.getDeclaredMethod("getId", new Class[]{});
70
                attrGetter = featureIntf.getDeclaredMethod("getAttribute", new Class[]{String.class});
71
            } catch (Exception e) {
72
                throw new RuntimeException("Probable programming Error", e);
73
            }
74
        }
75
 
76
        private FeatureInvocationHandler(Object o, ClassMetadata meta) {
77
            //TODO check if this is sufficiently general. What if not a POJO?
78
            if (meta.getMappedClass(EntityMode.POJO) != o.getClass()) {
79
                throw new RuntimeException("Metadata and POJO class do not cohere");
80
            }
81
            this.target = o;
82
            this.metadata = meta;
83
        }
84
 
85
        public Object invoke(Object proxy, Method method, Object[] args)
86
                throws Throwable {
87
            Method m = getTargetGetter(method, args);
88
 
89
            if (m == null) {
90
                return method.invoke(this.target, args);
91
            } else {
92
                return m.invoke(this.target);
93
            }
94
        }
95
 
96
        private Method getTargetGetter(Method invokedMethod, Object[] args) {
97
            try {
98
                if (invokedMethod.equals(geomGetter)) {
99
                    if (this.targetGeomGetter == null) {
100
                        this.targetGeomGetter = getGeomGetter();
101
                    }
102
                    return this.targetGeomGetter;
103
                } else if (invokedMethod.equals(idGetter)) {
104
                    if (this.targetIdGetter == null) {
105
                        this.targetIdGetter = getIdGetter();
106
                    }
107
                    return this.targetIdGetter;
108
                } else if (invokedMethod.equals(attrGetter)) {
109
                    String property = (String) args[0];
110
                    return getGetterFor(property);
111
                } else {
112
                    return null;
113
                }
114
            } catch (Exception e) {
115
                throw new RuntimeException("Problem getting suitable target method for method:  " + invokedMethod.getName(), e);
116
            }
117
 
118
        }
119
 
120
        private Method getGetterFor(String property) {
121
            Class cl = this.metadata.getMappedClass(EntityMode.POJO);
122
            Getter getter = ReflectHelper.getGetter(cl, property);
123
            return getter.getMethod();
124
        }
125
 
126
        private Method getGeomGetter() {
127
            try {
128
                String prop = getGeometryPropertyName();
129
                return getGetterFor(prop);
130
            } catch (Exception e) {
131
                throw new RuntimeException(e);
132
            }
133
        }
134
 
135
        public String getGeometryPropertyName() throws FinderException {
136
            return this.geomPropertyFinder.find(this.metadata);
137
        }
138
 
139
        public Method getIdGetter() {
140
            String prop = this.metadata.getIdentifierPropertyName();
141
            return getGetterFor(prop);
142
        }
143
 
144
    }
145
 
146
 
87 maesenka 147
}
148