KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > eclipse > mapper > extractor > HBMInfoExtractor


1 package org.hibernate.eclipse.mapper.extractor;
2
3 import java.lang.reflect.Field JavaDoc;
4 import java.lang.reflect.InvocationTargetException JavaDoc;
5 import java.lang.reflect.Method JavaDoc;
6 import java.lang.reflect.Modifier JavaDoc;
7 import java.util.ArrayList JavaDoc;
8 import java.util.Arrays JavaDoc;
9 import java.util.Collections JavaDoc;
10 import java.util.HashMap JavaDoc;
11 import java.util.List JavaDoc;
12 import java.util.Map JavaDoc;
13 import java.util.Set JavaDoc;
14
15 import org.eclipse.jdt.core.Flags;
16 import org.eclipse.jdt.core.IJavaProject;
17 import org.eclipse.jdt.core.IType;
18 import org.eclipse.jdt.core.JavaModelException;
19 import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal;
20 import org.eclipse.jdt.ui.text.java.CompletionProposalComparator;
21 import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
22 import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
23 import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
24 import org.hibernate.cfg.Environment;
25 import org.w3c.dom.NamedNodeMap JavaDoc;
26 import org.w3c.dom.Node JavaDoc;
27
28 /**
29  * Helper class that can extract information about a hbm.xml document based on e.g. DOM Nodes.
30  *
31  * @author max
32  *
33  */

34 public class HBMInfoExtractor {
35
36     final List JavaDoc hibernateTypes = new ArrayList JavaDoc(); // key: element>attributename, value: handler
37

38     final Map JavaDoc javaTypeProvider = new HashMap JavaDoc(); // key: element name, value: attribute which contains javaType
39

40     /** set of "tagname>attribname", used to decide which attributes we should react to */
41     final Map JavaDoc attributeHandlers = new HashMap JavaDoc(); // completes a possible package or classname
42

43     private String JavaDoc[] hibernatePropertyNames;
44     
45     public HBMInfoExtractor() {
46         setupTypeFinder();
47                 
48         setupJavaTypeHandlers();
49                 
50         setupPackageHandlers();
51     
52         setupFieldsPropertyHandlers();
53         
54         setupHibernateTypeHandlers();
55         
56         setupHibernateTypeDescriptors();
57         
58         setupTableNameHandlers();
59         
60         setupHibernateProperties();
61     }
62
63     private void setupHibernateProperties() {
64         hibernatePropertyNames = extractHibernateProperties();
65         
66     }
67
68     private String JavaDoc[] extractHibernateProperties() {
69         try {
70             // TODO: extract property names from the Environment class in the users hibernate configuration.
71
Class JavaDoc cl = Environment.class;
72             List JavaDoc names = new ArrayList JavaDoc();
73             Field JavaDoc[] fields = cl.getFields();
74             for (int i = 0; i < fields.length; i++) {
75                 Field JavaDoc field = fields[i];
76                 if(Modifier.isStatic(field.getModifiers()) &&
77                         field.getType().equals(String JavaDoc.class) ) {
78                     String JavaDoc str = (String JavaDoc) field.get(cl);
79                     if(str.startsWith("hibernate.")) {
80                         names.add(str);
81                     }
82                 }
83             }
84             String JavaDoc[] propertyNames = (String JavaDoc[]) names.toArray(new String JavaDoc[names.size()]);
85             Arrays.sort(propertyNames);
86             return propertyNames;
87         } catch (IllegalAccessException JavaDoc iae) {
88             // ignore
89
return new String JavaDoc[0];
90         }
91     }
92
93     private void setupTypeFinder() {
94
95         javaTypeProvider.put("class", "name");
96         javaTypeProvider.put("subclass", "name");
97         javaTypeProvider.put("joined-subclass", "name");
98         javaTypeProvider.put("union-subclass", "name");
99         // TODO: use eclipse java model to infer types of components property/fields
100
javaTypeProvider.put("composite-id", "class");
101         javaTypeProvider.put("component", "class");
102     }
103
104     private void setupHibernateTypeDescriptors() {
105         addHibernateType("long","java.lang.Long","long");
106         addHibernateType("short","java.lang.Short","short");
107         addHibernateType("integer","java.lang.Integer","int");
108         addHibernateType("byte","java.lang.Byte","byte");
109         addHibernateType("float","java.lang.Float","float");
110         addHibernateType("double","java.lang.Double","double");
111         addHibernateType("character","java.lang.Character","char");
112         addHibernateType("string","java.lang.String",null);
113         addHibernateType("time","java.util.Date",null);
114         addHibernateType("date","java.util.Date",null);
115         addHibernateType("timestamp","java.util.Date",null);
116         addHibernateType("boolean","java.lang.Boolean","boolean");
117         addHibernateType("true_false","java.lang.Boolean","boolean");
118         addHibernateType("yes_no","java.lang.Boolean","boolean");
119         addHibernateType("big_decimal","java.math.BigDecimal",null);
120         addHibernateType("binary","byte[]",null);
121         addHibernateType("text","java.lang.String",null);
122         addHibernateType("blob","java.sql.Blob",null);
123         addHibernateType("clob","java.sql.Clob",null);
124         addHibernateType("calendar","java.util.Calendar",null);
125         addHibernateType("calendar_date","java.util.Calendar",null);
126         addHibernateType("locale","java.util.Locale",null);
127         addHibernateType("currency","java.util.Currency",null);
128         addHibernateType("timezone","java.util.TimeZone",null);
129         addHibernateType("class","java.lang.Class",null);
130         addHibernateType("serializable","java.io.Serializable",null);
131         addHibernateType("object","java.lang.Object",null);
132         Collections.sort(hibernateTypes);
133     }
134
135     private void setupHibernateTypeHandlers() {
136         HBMInfoHandler hibernateTypeFinder = new HibernateTypeHandler(this);
137         attributeHandlers.put("filter-param>type", hibernateTypeFinder);
138         attributeHandlers.put("id>type", hibernateTypeFinder);
139         attributeHandlers.put("discriminator>type", hibernateTypeFinder);
140         attributeHandlers.put("version>type", hibernateTypeFinder);
141         attributeHandlers.put("property>type", hibernateTypeFinder);
142         attributeHandlers.put("key-property>type", hibernateTypeFinder);
143         attributeHandlers.put("element>type", hibernateTypeFinder);
144         attributeHandlers.put("map-key>type", hibernateTypeFinder);
145         attributeHandlers.put("index>type", hibernateTypeFinder);
146         attributeHandlers.put("collection-id>type", hibernateTypeFinder);
147         attributeHandlers.put("return-scalar>type", hibernateTypeFinder);
148     }
149
150     private void setupTableNameHandlers() {
151         HBMInfoHandler hih = new TableNameHandler();
152         attributeHandlers.put("class>table", hih);
153         attributeHandlers.put("join>table", hih);
154         attributeHandlers.put("joined-subclass>table", hih);
155         attributeHandlers.put("union-subclass>table", hih);
156         attributeHandlers.put("map>table", hih);
157         attributeHandlers.put("set>table", hih);
158         attributeHandlers.put("bag>table", hih);
159         attributeHandlers.put("idbag>table", hih);
160         attributeHandlers.put("list>table", hih);
161         attributeHandlers.put("array>table", hih);
162         attributeHandlers.put("primitive-array>table", hih);
163         attributeHandlers.put("synchronize>table", hih);
164     }
165     
166     private void setupFieldsPropertyHandlers() {
167         
168         HBMInfoHandler fieldsFinder = new FieldPropertyHandler(this);
169         attributeHandlers.put("version>name", fieldsFinder);
170         attributeHandlers.put("timestamp>name", fieldsFinder);
171         attributeHandlers.put("property>name", fieldsFinder);
172         attributeHandlers.put("key-property>name", fieldsFinder);
173         attributeHandlers.put("id>name", fieldsFinder);
174         attributeHandlers.put("composite-id>name", fieldsFinder);
175         attributeHandlers.put("set>name", fieldsFinder);
176         attributeHandlers.put("key-property>name", fieldsFinder);
177         attributeHandlers.put("property>name", fieldsFinder);
178         attributeHandlers.put("key-many-to-one>name", fieldsFinder);
179         attributeHandlers.put("many-to-one>name", fieldsFinder);
180         attributeHandlers.put("one-to-one>name", fieldsFinder);
181         attributeHandlers.put("component>name", fieldsFinder);
182         attributeHandlers.put("dynamic-component>name", fieldsFinder);
183         attributeHandlers.put("properties>name", fieldsFinder);
184         attributeHandlers.put("any>name", fieldsFinder);
185         attributeHandlers.put("map>name", fieldsFinder);
186         attributeHandlers.put("set>name", fieldsFinder);
187         attributeHandlers.put("list>name", fieldsFinder);
188         attributeHandlers.put("bag>name", fieldsFinder);
189         attributeHandlers.put("idbag>name", fieldsFinder);
190         attributeHandlers.put("array>name", fieldsFinder);
191         attributeHandlers.put("primitive-array>name", fieldsFinder);
192         attributeHandlers.put("query-list>name", fieldsFinder);
193     }
194
195     private void setupPackageHandlers() {
196         HBMInfoHandler packageFinder = new PackageHandler(this);
197         attributeHandlers.put("hibernate-mapping>package", packageFinder);
198     }
199
200     private void setupJavaTypeHandlers() {
201         HBMInfoHandler classFinder = new JavaTypeHandler(this);
202         attributeHandlers.put("class>name", classFinder);
203         attributeHandlers.put("subclass>name", classFinder);
204         attributeHandlers.put("joined-subclass>name", classFinder);
205         attributeHandlers.put("union-subclass>name", classFinder);
206         attributeHandlers.put("many-to-one>class", classFinder);
207         attributeHandlers.put("one-to-many>class", classFinder);
208         attributeHandlers.put("many-to-many>class", classFinder);
209         attributeHandlers.put("composite-element>class", classFinder);
210         attributeHandlers.put("component>class", classFinder);
211         attributeHandlers.put("composite-id>class", classFinder);
212         attributeHandlers.put("key-many-to-one>class", classFinder);
213     }
214     
215     List JavaDoc findMatchingHibernateTypes(String JavaDoc item) {
216         List JavaDoc l = new ArrayList JavaDoc();
217         boolean foundFirst = false;
218         for (int i = 0; i < hibernateTypes.size(); i++) {
219             HibernateTypeDescriptor element = (HibernateTypeDescriptor) hibernateTypes.get(i);
220             if(element.getName().startsWith(item)) {
221                 foundFirst = true;
222                 l.add(element);
223             } else if (foundFirst) {
224                 return l; // fail fast since if we dont get a match no future match can be found.
225
}
226         }
227         return l;
228     }
229
230     public List JavaDoc findMatchingPropertyTypes(String JavaDoc prefix) {
231         List JavaDoc l = new ArrayList JavaDoc();
232         boolean foundFirst = false;
233         for (int i = 0; i < hibernatePropertyNames.length; i++) {
234             String JavaDoc element = hibernatePropertyNames[i];
235             if(element.startsWith(prefix)) {
236                 foundFirst = true;
237                 l.add(element);
238             } else if (element.startsWith("hibernate." + prefix)) {
239                 foundFirst = true;
240                 l.add(element.substring("hibernate.".length()));
241             } else if (foundFirst) {
242                 return l; // fail fast since if we dont get a match no future match can be found.
243
}
244         }
245         return l;
246     }
247
248     /**
249      * @param start
250      * @param offset
251      * @param results replacementoffset is changed and array is sorted inplace for relevance
252      */

253     void transpose(String JavaDoc start, int offset, IJavaCompletionProposal[] results) {
254         // As all completions have made with the assumption on a empty
255
// (or almost empty) string
256
// we move the replacementoffset on every proposol to fit nicely
257
// into our non-java code
258
for (int i = 0; i < results.length; i++) {
259             if(results[i] instanceof JavaCompletionProposal) {
260                 JavaCompletionProposal proposal = (JavaCompletionProposal) results[i]; // TODO: eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84998
261
int wanted = proposal.getReplacementOffset() + (offset /*- start.length()*/);
262                 if(wanted==proposal.getReplacementOffset()) {
263                     System.out.println("NO TRANSPOSE!");
264                 }
265                 proposal.setReplacementOffset(wanted);
266             } else {
267                 Class JavaDoc c = results[i].getClass();
268                 try {
269                     Method JavaDoc setMethod = c.getMethod("setReplacementOffset", new Class JavaDoc[] { int.class });
270                     Method JavaDoc GetMethod = c.getMethod("getReplacementOffset", new Class JavaDoc[0]);
271                     
272                     Integer JavaDoc offsetx = (Integer JavaDoc) GetMethod.invoke(results[i], null);
273                     int wanted = offsetx.intValue() + (offset /*- start.length()*/);
274                     setMethod.invoke(results[i], new Object JavaDoc[] { new Integer JavaDoc(wanted) });
275                 } catch (SecurityException JavaDoc e) {
276                     // TODO Auto-generated catch block
277
e.printStackTrace();
278                 } catch (NoSuchMethodException JavaDoc e) {
279                     // TODO Auto-generated catch block
280
e.printStackTrace();
281                 } catch (IllegalArgumentException JavaDoc e) {
282                     // TODO Auto-generated catch block
283
e.printStackTrace();
284                 } catch (IllegalAccessException JavaDoc e) {
285                     // TODO Auto-generated catch block
286
e.printStackTrace();
287                 } catch (InvocationTargetException JavaDoc e) {
288                     // TODO Auto-generated catch block
289
e.printStackTrace();
290                 }
291                 // M7
292
// LazyJavaCompletionProposal proposal = (LazyJavaCompletionProposal) results[i]; // TODO: eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84998
293
// int wanted = proposal.getReplacementOffset() + (offset /*- start.length()*/);
294
// if(wanted==proposal.getReplacementOffset()) {
295
// System.out.println("NO TRANSPOSE!");
296
// }
297
// proposal.setReplacementOffset(proposal.getReplacementOffset() + (offset /*- start.length()*/));
298
}
299         }
300         Arrays.sort(results, new CompletionProposalComparator());
301     }
302
303
304     
305
306     /**
307      * @param holder
308      * @param root TODO
309      * @return nearest package attribute, null if none found.
310      */

311     String JavaDoc getPackageName(Node JavaDoc root) {
312         if(root!=null) {
313             while(!"hibernate-mapping".equals(root.getNodeName())) {
314                 root = root.getParentNode();
315                 if(root==null) return null;
316             }
317             NamedNodeMap JavaDoc attributes = root.getAttributes();
318             for(int count = 0; count<attributes.getLength(); count++) {
319                 Node JavaDoc att = attributes.item(count);
320                 if("package".equals(att.getNodeName())) {
321                     return att.getNodeValue();
322                 }
323             }
324         }
325         return null;
326     }
327
328     protected boolean beginsWith(String JavaDoc aString, String JavaDoc prefix) {
329         if (aString == null || prefix == null)
330             return true;
331         // (pa) 221190 matching independent of case to be consistant with Java
332
// editor CA
333
return aString.toLowerCase().startsWith(prefix.toLowerCase());
334     }
335
336     void generateTypeProposals(String JavaDoc matchString, int offset, List JavaDoc proposals, Set JavaDoc alreadyFound, IType[] classes) throws JavaModelException {
337         for (int j = 0; j < classes.length; j++) {
338             IType type = classes[j];
339             if (!Flags.isAbstract(type.getFlags())) {
340                 String JavaDoc fullName = type.getFullyQualifiedName();
341                 String JavaDoc shortName = type.getElementName();
342                 if(alreadyFound.contains(fullName)) {
343                     continue;
344                 } else {
345                     alreadyFound.add(fullName);
346                 }
347                 if (beginsWith(fullName,matchString) || beginsWith(shortName,matchString)) {
348                     CustomCompletionProposal proposal = new CustomCompletionProposal(fullName, //$NON-NLS-2$//$NON-NLS-1$
349
offset, matchString.length(), fullName.length() + 1, null/*XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE)*/,
350                             fullName, null, null, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
351                     proposals.add(proposal);
352                 }
353             }
354         }
355     }
356
357
358     
359     private void addHibernateType(String JavaDoc name, String JavaDoc returnClass, String JavaDoc primitiveClass) {
360         hibernateTypes.add(new HibernateTypeDescriptor(name, returnClass, primitiveClass));
361     }
362
363     /**
364      * Returns attribute handler for the path.
365      * @param path a string on the form [xmltag]>[attributename] e.g. property>name
366      * @return
367      */

368     public HBMInfoHandler getAttributeHandler(String JavaDoc path) {
369         return (HBMInfoHandler) attributeHandlers.get(path);
370     }
371
372     /**
373      * @param node
374      * @return the name of the nearest type from the node or null if none found.
375      */

376     public String JavaDoc getNearestType(Node JavaDoc node) {
377         if(node==null) return null;
378         while(!javaTypeProvider.containsKey(node.getNodeName())) {
379             node = node.getParentNode();
380             if(node==null) return null;
381         }
382         String JavaDoc attributeName = (String JavaDoc) javaTypeProvider.get(node.getNodeName());
383         NamedNodeMap JavaDoc attributes = node.getAttributes();
384         
385         for(int count = 0; count<attributes.getLength(); count++) {
386             Node JavaDoc att = attributes.item(count);
387             if(attributeName.equals(att.getNodeName())) {
388                 String JavaDoc typename = att.getNodeValue();
389                 if(typename!=null && typename.indexOf('.')<0) {
390                     typename = getPackageName(node) + "." + typename;
391                 }
392                 return typename;
393             }
394         }
395         
396         return null;
397     }
398
399     public IType getNearestTypeJavaElement(IJavaProject project, Node JavaDoc currentNode) {
400         String JavaDoc nearestType = getNearestType(currentNode);
401         if(nearestType!=null) {
402             try {
403                 IType type = project.findType(nearestType);
404                 return type;
405             } catch (JavaModelException e) {
406                 //ignore
407
}
408         }
409         return null;
410     }
411 }
412
Popular Tags