Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/jdt/util/PersistentItem.java


1   package com.port80.eclipse.jdt.util;
2   
3   import java.sql.Timestamp;
4   
5   import org.eclipse.core.resources.IFile;
6   import org.eclipse.core.resources.IProject;
7   import org.eclipse.core.resources.IResource;
8   import org.eclipse.core.resources.IWorkspaceRoot;
9   import org.eclipse.core.resources.ResourcesPlugin;
10  import org.eclipse.core.runtime.IAdaptable;
11  import org.eclipse.core.runtime.IPath;
12  import org.eclipse.core.runtime.Path;
13  import org.eclipse.jdt.core.IClassFile;
14  import org.eclipse.jdt.core.ICompilationUnit;
15  import org.eclipse.jdt.core.IJavaElement;
16  import org.eclipse.jdt.core.IJavaProject;
17  import org.eclipse.jdt.core.IMember;
18  import org.eclipse.jdt.core.IMethod;
19  import org.eclipse.jdt.core.IType;
20  import org.eclipse.jdt.core.JavaModelException;
21  import org.eclipse.jdt.core.Signature;
22  import org.eclipse.jdt.internal.ui.JavaPluginImages;
23  import org.eclipse.swt.graphics.Image;
24  import org.eclipse.ui.IElementFactory;
25  import org.eclipse.ui.IMemento;
26  import org.eclipse.ui.IPersistableElement;
27  import org.eclipse.ui.ISharedImages;
28  import org.eclipse.ui.PlatformUI;
29  
30  import com.port80.eclipse.jdt.JdtPlugin;
31  import com.port80.eclipse.jdt.Util;
32  import com.port80.eclipse.util.UtilPluginImages;
33  
34  /**
35   * Wrapper around object to make it a tree item and persistable.
36   * <p>
37   * Currently, valid objects that can be persisted are IType, IMethod, 
38   * other object type are not persisted.
39   * <p>
40   * Each item is uniquely identified by its Kind, FullName, FullPath, Project.
41   * Items with the fields equal is the same item.
42   * <p>
43   * When the presistable object is resolved to an actual object in the workspace,
44   * it is cached and subsequently return by getCached().  Use resolve() to
45   * force resolving again.
46   * <p>
47   * Used by MethodView and WorkingSetView to save history objects.
48   *  
49   * @author chrisl
50   */
51  public class PersistentItem implements IPersistableElement, IElementFactory, IAdaptable {
52  
53    public static final String NAME = "PersistentItem";
54    public static final String ID = "com.port80.eclipse.jdt.util.PersistentItem";
55  
56    public static final String[] KIND_NAMES =
57      new String[] { "None", "Class", "Interface", "Method", "Folder", "File" };
58    public static final int NONE = 0;
59    public static final int CLASS = 1;
60    public static final int INTERFACE = 2;
61    public static final int METHOD = 3;
62    public static final int FOLDER = 4;
63    public static final int FILE = 5;
64  
65    public static final int IS_ERR = 0x0001;
66    public static final int IS_NOTEXIST = 0x0001;
67    public static final int IS_ACTIVE = 0x0100;
68  
69    private static final boolean DEBUG = false;
70  
71    /** Icons for the item (without any java decoration).*/
72    private static final Image[] ICONS;
73    private static final Image ICON_ERROR;
74    private static final Image ICON_OPEN_FOLDER;
75    static {
76      ICONS =
77        new Image[] {
78          PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT),
79          JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CLASS),
80          JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE),
81          JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC),
82          UtilPluginImages.get(UtilPluginImages.IMGKEY_CLOSED_FOLDER),
83          PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE)};
84      ICON_ERROR = UtilPluginImages.get(UtilPluginImages.IMGKEY_DELETE);
85      ICON_OPEN_FOLDER = UtilPluginImages.get(UtilPluginImages.IMGKEY_OPEN_FOLDER);
86    }
87  
88    // Persistent fields.
89    private int fKind;
90    /** Number of visits. */
91    private int fCount;
92    /** Short name of the item, eg. simple type name or method signature. */
93    private String fName;
94    /** Full name eg. FullyQualifiedName of types or type qualified method signature. */
95    private String fFullName;
96    /** 
97     * Full path to the object's underlying resource, relative to workspace root 
98     * or absolute if resource is external to workspace. 
99     */
100   private String fFullPath;
101   /** Project name in workspace. */
102   private String fProject;
103   /** A flag (the name is obsoleted). For JavaElement, 1 for binary, 0 for source. */
104   private int fExternal;
105   private String fAnnotation;
106   private Timestamp fCreateTime;
107   private Timestamp fAccessTime;
108   /** The parent folder name. */
109   private String fParent;
110 
111   // Transient fields.
112   private Object fCached;
113   private int fStatus; /** Error resolving to actual object.*/
114 
115   ////////////////////////////////////////////////////////////////////////
116 
117   /** 
118    * Static factory method to create a PersistentItem. 
119    * @return Item created or null if fail to create item.
120    */
121   public static PersistentItem create(Object a) {
122     if (!(a instanceof IJavaElement) && !(a instanceof IFile))
123       return null;
124     PersistentItem ret = new PersistentItem();
125     return ret.init(a);
126   }
127 
128   public static PersistentItem create(Object a, String parent) {
129     if (!(a instanceof IJavaElement) && !(a instanceof IFile))
130       return null;
131     PersistentItem ret = new PersistentItem();
132     ret.fParent = parent;
133     return ret.init(a);
134   }
135 
136   /** 
137    * Static factory method to create a PersistentItem from an IMemento. 
138    * @return Item created or null if fail to create item.
139    */
140   public static PersistentItem restore(IMemento m) {
141     PersistentItem ret = new PersistentItem();
142     ret = (PersistentItem) ret.restoreState(m);
143     return ret;
144   }
145 
146   ////////////////////////////////////////////////////////////////////////
147 
148   private PersistentItem() {
149   }
150 
151   public PersistentItem(int kind, String name) {
152     fKind = kind;
153     fName = name;
154     fFullName = name;
155   }
156 
157   public Object clone() {
158     PersistentItem ret = new PersistentItem();
159     ret.fParent = fParent;
160     ret.fKind = fKind;
161     ret.fName = fName;
162     ret.fFullName = fFullName;
163     ret.fFullPath = fFullPath;
164     ret.fProject = fProject;
165     ret.fExternal = fExternal;
166     ret.fAnnotation = fAnnotation;
167     ret.fCreateTime = fCreateTime;
168     ret.fAccessTime = fAccessTime;
169     ret.fCount = fCount;
170     return ret;
171   }
172 
173   ////////////////////////////////////////////////////////////////////////
174 
175   private PersistentItem init(Object a) {
176     if (a == null)
177       return null;
178     fKind = NONE;
179     fCount = 1;
180     if (a instanceof IJavaElement)
181       return initJavaElement((IJavaElement) a);
182     if (a instanceof IFile)
183       return initFile((IFile) a);
184     return null;
185   }
186 
187   private PersistentItem initJavaElement(IJavaElement element) {
188     try {
189       IType type;
190       if (element instanceof IType) {
191         type = (IType) element;
192         fKind = (type.isClass()) ? CLASS : INTERFACE;
193         fFullName = ((IType) element).getFullyQualifiedName();
194         fName = Signature.getSimpleName(fFullName);
195       } else if (element instanceof IMethod) {
196         fKind = METHOD;
197         fFullName = Util.getFullMethodSignature((IMethod)element);
198         fName = Util.getMethodSignature((IMethod) element);
199       }
200       if (fKind != NONE) {
201         fCached = element;
202         ICompilationUnit unit = ((IMember) element).getCompilationUnit();
203         if (unit != null) {
204           fProject = unit.getJavaProject().getProject().getName();
205           fFullPath = unit.getPath().toString();
206           fExternal = 0;
207           if (fKind != METHOD)
208             fName += ".java";
209         } else {
210           IClassFile file = ((IMember) element).getClassFile();
211           //NOTE: IJavaElement.getResource() return null for external jar.
212           //          So it useless.
213           //        if (file != null && file.getResource() != null) {
214           //          resource = file.getResource();
215           //          fProject = resource.getProject().getName();
216           //          fFullPath = resource.getFullPath().toString();
217           //        }
218           // This would be an absolute path to the class/jar file in the file system.
219           fProject = file.getJavaProject().getProject().getName();
220           fFullPath = file.getPath().toString();
221           fExternal = 1;
222           if (fKind != METHOD)
223             fName += ".class ";
224         }
225       }
226       if (false)
227         System.err.println(
228           NAME
229             + ".init(): fProject="
230             + fProject
231             + ", fFullPath="
232             + fFullPath
233             + ", fFullName="
234             + fFullName);
235       fCreateTime = new Timestamp(System.currentTimeMillis());
236     } catch (JavaModelException e) {
237       JdtPlugin.log(NAME + ".init()", element, e);
238       return null;
239     }
240     if (fKind == NONE)
241       return null;
242     return this;
243   }
244 
245   private PersistentItem initFile(IFile file) {
246     fKind = FILE;
247     fProject = file.getProject().getName();
248     fFullPath = file.getFullPath().toString();
249     fName = file.getName();
250     fFullName = fName;
251     fCreateTime = new Timestamp(System.currentTimeMillis());
252     fExternal = 0;
253     return this;
254   }
255 
256   ////////////////////////////////////////////////////////////////////////
257 
258   public void setParent(String parent) {
259     fParent = parent;
260   }
261   public void setActive(boolean isactive) {
262     fStatus |= IS_ACTIVE;
263     if (!isactive)
264       fStatus ^= IS_ACTIVE;
265   }
266   public void setATime(Timestamp t) {
267     ++fCount;
268     if (t != null)
269       fAccessTime = t;
270     else
271       fAccessTime = fCreateTime;
272   }
273   public void setAnnotation(String text) {
274     fAnnotation = text;
275   }
276 
277   public String getParent() {
278     return fParent;
279   }
280   public boolean isExternal() {
281     return fExternal != 0;
282   }
283   public boolean isActive() {
284     return (fStatus & IS_ACTIVE) != 0;
285   }
286   public boolean isNotExist() {
287     return (fStatus & IS_NOTEXIST) != 0;
288   }
289   public int getStatus() {
290     return fStatus;
291   }
292   public int getKind() {
293     return fKind;
294   }
295   public String getKindName() {
296     return KIND_NAMES[fKind];
297   }
298   public int getCount() {
299     return fCount;
300   }
301   public String getName() {
302     return fName;
303   }
304   public String getFullName() {
305     return fFullName;
306   }
307   public String getFullPath() {
308     return fFullPath;
309   }
310   public String getProject() {
311     return fProject;
312   }
313   public String getAnnotation() {
314     return fAnnotation;
315   }
316   public Timestamp getATime() {
317     return fAccessTime;
318   }
319   public Timestamp getCTime() {
320     return fCreateTime;
321   }
322 
323   ////////////////////////////////////////////////////////////////////////
324 
325   public Image getImage() {
326     if ((fStatus & IS_ERR) != 0)
327       return ICON_ERROR;
328     if (fKind == FOLDER && isActive())
329       return ICON_OPEN_FOLDER;
330     return ICONS[fKind];
331   }
332 
333   // IPersistableElement interface //////////////////////////////////////
334   //
335   public String getFactoryId() {
336     return ID;
337   }
338 
339   public void saveState(IMemento m) {
340     m.putInteger("Kind", fKind);
341     m.putString("Parent", fParent);
342     m.putString("KindName", KIND_NAMES[fKind]);
343     m.putInteger("Count", fCount);
344     m.putInteger("External", fExternal);
345     m.putString("Name", fName);
346     m.putString("FullName", fFullName);
347     m.putString("FullPath", fFullPath);
348     m.putString("Project", fProject);
349     m.putString("Annotation", fAnnotation);
350     if (fCreateTime != null)
351       m.putString("CreateTime", fCreateTime.toString());
352     if (fAccessTime != null)
353       m.putString("AccessTime", fAccessTime.toString());
354   }
355 
356   // IElementFactory interface ///////////////////////////////////////////
357   //
358   public IAdaptable createElement(IMemento m) {
359     return restoreState(m);
360   }
361 
362   public IAdaptable restoreState(IMemento m) {
363     String ret;
364     fKind = getIntDef(m, "Kind", NONE);
365     fCount = getIntDef(m, "Count", 1);
366     fExternal = getIntDef(m, "External", 0);
367     fParent = m.getString("Parent");
368     fName = m.getString("Name");
369     if (fName == null)
370       fName = "";
371     fFullName = m.getString("FullName");
372     if (fFullName == null)
373       fFullName = fName;
374     fFullPath = m.getString("FullPath");
375     fProject = m.getString("Project");
376     fAnnotation = m.getString("Annotation");
377     ret = m.getString("CreateTime");
378     if (ret == null)
379       fCreateTime = new Timestamp(System.currentTimeMillis());
380     else
381       fCreateTime = Timestamp.valueOf(ret);
382     ret = m.getString("AccessTime");
383     if (ret == null)
384       fAccessTime = fCreateTime;
385     else
386       fAccessTime = Timestamp.valueOf(ret);
387     return this;
388   }
389 
390   // IAdaptable interface ///////////////////////////////////////////////
391   //
392   public Object getAdapter(Class c) {
393     if (c.isInstance(this))
394       return this;
395     return null;
396   }
397 
398   /** 
399    * Get the cached object if it have been resolved, 
400    * else resolve to an actual object, cache it and return it. 
401    */
402   public Object getCached() {
403     if (fCached == null)
404       fCached = resolve();
405     return fCached;
406   }
407 
408   public Object resolve() {
409     if (fKind == CLASS || fKind == INTERFACE || fKind == METHOD)
410       return resolveJavaElement();
411     if (fKind == FILE)
412       return resolveFile();
413     return null;
414   }
415 
416   private IFile resolveFile() {
417     IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
418     IFile file = root.getFile(new Path(fFullPath));
419     fStatus |= IS_NOTEXIST;
420     if (file != null)
421       fStatus ^= IS_NOTEXIST;
422     if (DEBUG)
423       System.err.println(NAME + ".resolveFile():  file=" + file.getFullPath().toString());
424     return file;
425   }
426 
427   /** 
428    * Resolve the persistable reference to an actual object.  
429    * If cahed object does not equal to the resolved object, the cache it cleared.  
430    * If cached object equals to the resolved object, it stay in the cache.
431    */
432   private IJavaElement resolveJavaElement() {
433     final String METHODNAME = NAME + ".resolveJavaElement";
434     fStatus |= IS_NOTEXIST;
435     IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
436     IResource resource = null;
437     if (fFullPath == null)
438       return null;
439     if (fProject == null)
440       return null;
441     IProject project = root.getProject(fProject);
442     if (project == null) {
443       if (DEBUG)
444         System.err.println(METHODNAME + "(): project not exist.");
445       return null;
446     }
447     IJavaElement ret = null;
448     if (isExternal()) {
449       IJavaProject javaproject = JavaUtil.getJavaProject(project);
450       if (javaproject == null)
451         if (DEBUG)
452           System.err.println(METHODNAME + "(): javaproject==null");
453       try {
454         ret = javaproject.findPackageFragmentRoot(new Path(fFullPath));
455         if (ret == null)
456           return null;
457       } catch (Exception e) {
458         JdtPlugin.log(METHODNAME + "(): javaproject==null", e);
459         return null;
460       }
461       switch (fKind) {
462         case CLASS :
463         case INTERFACE :
464           ret = Util.findJavaType(ret, fFullName);
465           break;
466         case METHOD :
467           ret = Util.findJavaMethod(ret, fFullName);
468           break;
469       }
470     } else {
471       // Resource local to workspace.
472       IJavaProject javaproject = JavaUtil.getJavaProject(project);
473       if (javaproject == null) {
474         if (DEBUG)
475           System.err.println(
476             METHODNAME + "(): Java project not found: project=" + fProject);
477         return null;
478       }
479       String typename = fFullName;
480       if(fKind==METHOD) typename=Util.getTypeNameOfMethodSignature(typename);
481       fFullName.replace('.', '/');
482       typename += ".java";
483       IPath path = new Path(typename);
484       if (DEBUG)
485         System.err.println(METHODNAME + "(): path=" + path.toString());
486       try {
487         ret = javaproject.findElement(path);
488       } catch (JavaModelException e) {
489         JdtPlugin.log(
490           METHODNAME + "(): finding element: " + resource.getFullPath().toString(),
491           e);
492         return null;
493       }
494       if (fKind == METHOD)
495         ret = Util.findJavaMethod(ret, fFullName);
496       //      if (resource != null)
497       //        ret = JavaCore.create(resource);
498     }
499     if (false)
500       System.err.println(JdtPlugin.msg(METHODNAME + "(): 1: ", ret));
501     if (fCached != null && !fCached.equals(ret))
502       fCached = null;
503     if (ret != null)
504       fStatus ^= IS_NOTEXIST;
505     if (DEBUG)
506       System.err.println(JdtPlugin.msg(METHODNAME + "(): ret=", ret));
507     return ret;
508   }
509 
510   ////////////////////////////////////////////////////////////////////////
511 
512   public int hashCode() {
513     StringBuffer buf = new StringBuffer();
514     buf.append(fParent);
515     buf.append('#');
516     buf.append(fFullPath);
517     buf.append('#');
518     buf.append(fFullName);
519     buf.append('#');
520     buf.append(fName);
521     buf.append('#');
522     buf.append(fKind);
523     return (buf.toString().hashCode());
524   }
525 
526   public boolean equals(Object a) {
527     if (!(a instanceof PersistentItem))
528       return false;
529     PersistentItem item = (PersistentItem) a;
530     if (fKind != item.fKind)
531       return false;
532     if (!(fFullName == null ? item.fFullName == null : fFullName.equals(item.fFullName)))
533       return false;
534     //NOTE:
535     // FullPath already have the project name for source item.  
536     // For binary item, the project is ignored.  
537     // As long as the FullPath points to the same file, it is same object.
538     if (!(fFullPath == null ? item.fFullPath == null : fFullPath.equals(item.fFullPath)))
539       return false;
540     if (!(fParent == null ? item.fParent == null : fParent.equals(item.fParent)))
541       return false;
542     return true;
543   }
544 
545   /** String representation in format: Parent*Project@FullPath#FullName:KindName. */
546   public String toString() {
547     StringBuffer buf = new StringBuffer("# PersistentItem\n# ");
548     if (fParent != null)
549       buf.append(fParent);
550     buf.append("\n# ");
551     if (fProject != null)
552       buf.append(fProject);
553     buf.append("\n# ");
554     if (fFullPath != null)
555       buf.append(fFullPath);
556     buf.append("\n# ");
557     buf.append(fFullName);
558     buf.append("\n# ");
559     buf.append(getKindName());
560     buf.append("\n");
561     if (fAnnotation != null)
562       buf.append(fAnnotation);
563     buf.append("\n");
564     return buf.toString();
565   }
566 
567   ////////////////////////////////////////////////////////////////////////
568 
569   private int getIntDef(IMemento m, String key, int def) {
570     Integer n = m.getInteger(key);
571     if (n != null)
572       return n.intValue();
573     else
574       return def;
575   }
576 
577   ////////////////////////////////////////////////////////////////////////
578 }