|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.java.bridge; import java.beans.*; import java.io.IOException; import java.util.*; import java.lang.ref.WeakReference; import java.net.URL; import org.openide.nodes.Node; import org.openide.nodes.CookieSet; import org.openide.src.*; import org.netbeans.modules.java.ElementFactory; import javax.jmi.reflect.RefBaseObject; import javax.jmi.reflect.RefObject; import javax.jmi.reflect.InvalidObjectException; import org.netbeans.api.mdr.MDRepository; import org.netbeans.api.mdr.events.*; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.classpath.GlobalPathRegistry; import org.netbeans.jmi.javamodel.Array; import org.netbeans.jmi.javamodel.Codebase; import org.netbeans.jmi.javamodel.Feature; import org.netbeans.jmi.javamodel.JavaClass; import org.netbeans.jmi.javamodel.TypeReference; import org.netbeans.jmi.javamodel.ArrayReference; import org.netbeans.jmi.javamodel.ClassDefinition; import org.netbeans.jmi.javamodel.JavaModelPackage; import org.netbeans.jmi.javamodel.JavaPackage; import org.netbeans.jmi.javamodel.MultipartId; import org.netbeans.jmi.javamodel.NamedElement; import org.netbeans.jmi.javamodel.ParameterizedType; import org.netbeans.jmi.javamodel.PrimitiveType; import org.netbeans.jmi.javamodel.PrimitiveTypeKind; import org.netbeans.jmi.javamodel.PrimitiveTypeKindEnum; import org.netbeans.jmi.javamodel.Resource; import org.netbeans.jmi.javamodel.TypeParameter; import org.netbeans.jmi.javamodel.UnresolvedClass; import org.netbeans.mdr.handlers.InstanceHandler; import org.netbeans.modules.java.JavaDataObject; import org.netbeans.modules.javacore.ClassIndex; import org.netbeans.modules.javacore.internalapi.JavaMetamodel; import org.netbeans.modules.javacore.jmiimpl.javamodel.TypeClassImpl; import org.netbeans.modules.javacore.internalapi.JMIElementCookie; import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.openide.text.EditorSupport; import org.openide.util.Utilities; /** * * @author Dan Prusa */ public abstract class ElementImpl implements Element.Impl, Element.Impl2, ElementProperties, Node.Cookie, ElementEvents { public static final String JAVA_LANG_OBJECT = "java.lang.Object"; // NOI18N /** The element for this class. */ private transient Element element; /** * Collection of registered PropertyChangeListeners. */ private transient Collection propListeners; /** Vetoable change support. * PENDING: Need to create special VetoableChangeSupport, as the standard one * is not sufficient for the fine-grained events. */ private transient VetoableChangeSupport vetoSupport; /** * Binding to the underlying source/whatever. */ protected transient Binding binding; /** * True, if the element has been already created and was not destroyed. */ private transient boolean valid; /** * Set of cookies for this element. The set conveniently contains only cookies for * the implementation class hierarchy. */ private CookieSet cookieSet; /** * Model that has created this element and that is used to manage the element. * The element delegates management functions like locking and event queueing to * its model. */ protected transient DefaultLangModel model; /** * Flag that is used to signal that the element is being created. Some processing * is reduced to minimum during this mode and event firing is supressed. */ private transient boolean inCreation; protected JavaDocImpl javadoc; /** * Java element in repository corresponding to this element. */ protected transient RefObject javaElement; protected transient JavaModelPackage javaModelPackage; protected transient MDRepository repository; private static final Binding NULL_BINDING = new NullBinding(); /** * Enables debug trace messages for event generation */ private static final boolean DEBUG_EVENTS = false; private static final long serialVersionUID = -6337836874152020892L; protected ElementImpl(DefaultLangModel model) { this.model = model; this.javaElement = null; this.inCreation = false; this.valid = true; this.repository = JavaMetamodel.getDefaultRepository (); binding = NULL_BINDING; } protected ElementImpl(DefaultLangModel model, RefObject javaElement) { this.model = model; this.javaElement = javaElement; this.inCreation = false; this.valid = true; this.repository = JavaMetamodel.getDefaultRepository (); binding = NULL_BINDING; try { javaModelPackage = (JavaModelPackage) javaElement.refImmediatePackage (); } catch (javax.jmi.reflect.InvalidObjectException e) { } } public RefObject getJavaElement () { return javaElement; } public Type descrToType (org.netbeans.jmi.javamodel.Type type) { return descrToType (TypeClassImpl.getRealType(type), null); } public Type descrToType (org.netbeans.jmi.javamodel.Type descr, String sourceName) { if (descr == null) return null; if (descr instanceof TypeParameter) { return Type.createClass (createClassIdentifier (JAVA_LANG_OBJECT)); } if (descr instanceof ParameterizedType) { if (((ParameterizedType)descr).getParameters().size() == 0) { descr = ((ParameterizedType)descr).getDefinition(); } else { if (sourceName == null) return Type.createClass (createClassIdentifier (JAVA_LANG_OBJECT)); else return Type.createClass (createClassIdentifier (JAVA_LANG_OBJECT, sourceName)); } } if (descr instanceof Array) { return Type.createArray (descrToType (((Array) descr).getType ())); } else if (descr instanceof JavaClass) { // [MaM] migration String name = ((JavaClass) descr).getName (); // if (name.equals ("String")) { // name = "java.lang.String"; // } // System.out.println("descrToType, CLASS: " + name); if (sourceName == null) return Type.createClass (createClassIdentifier (name)); else return Type.createClass (createClassIdentifier (name, sourceName)); } else { // primitive type PrimitiveTypeKind kind = ((PrimitiveType) descr).getKind (); if (PrimitiveTypeKindEnum.BOOLEAN.equals (kind)) return Type.BOOLEAN; if (PrimitiveTypeKindEnum.INT.equals (kind)) return Type.INT; if (PrimitiveTypeKindEnum.CHAR.equals (kind)) return Type.CHAR; if (PrimitiveTypeKindEnum.BYTE.equals (kind)) return Type.BYTE; if (PrimitiveTypeKindEnum.SHORT.equals (kind)) return Type.SHORT; if (PrimitiveTypeKindEnum.LONG.equals (kind)) return Type.LONG; if (PrimitiveTypeKindEnum.FLOAT.equals (kind)) return Type.FLOAT; if (PrimitiveTypeKindEnum.DOUBLE.equals (kind)) return Type.DOUBLE; return descr != null ? Type.VOID : null; // [PENDING] should null be returned ??? } } // [MaM] this method should probably by changed to "resolveType" public org.netbeans.jmi.javamodel.Type typeToDescr (Type type) { if (type.isArray ()) { return javaModelPackage.getArray().resolveArray(typeToDescr(type.getElementType())); } else { if (type.isClass()) { return getClassDescriptor(type.getClassName().getFullName()); } else { // primitive type return (PrimitiveType) javaModelPackage.getType().resolve(type.getFullString()); // [MaM] migration to the new infrastructure // PrimitiveTypeKind tag; // if (Type.BOOLEAN.equals (type)) // tag = PrimitiveTypeKindEnum.BOOLEAN; // else if (Type.INT.equals (type)) // tag = PrimitiveTypeKindEnum.INT; // else if (Type.CHAR.equals (type)) // tag = PrimitiveTypeKindEnum.CHAR; // else if (Type.BYTE.equals (type)) // tag = PrimitiveTypeKindEnum.BYTE; // else if (Type.SHORT.equals (type)) // tag = PrimitiveTypeKindEnum.SHORT; // else if (Type.LONG.equals (type)) // tag = PrimitiveTypeKindEnum.LONG; // else if (Type.FLOAT.equals (type)) // tag = PrimitiveTypeKindEnum.FLOAT; // else if (Type.DOUBLE.equals (type)) // tag = PrimitiveTypeKindEnum.DOUBLE; // else // tag = PrimitiveTypeKindEnum.VOID; // return codeBase.createPrimitive(tag); } } } public TypeReference typeToTypeReference(Type type) { if (type.isArray ()) { int dimCount = 0; do { dimCount++; type = type.getElementType(); } while (type.isArray()); String name = type.getSourceString(); if (name == null) name = type.getFullString(); MultipartId parent = javaModelPackage.getMultipartId().createMultipartId(name, null, null); return javaModelPackage.getArrayReference().createArrayReference("", parent, dimCount); } else { String name = type.getSourceString(); if (name == null) name = type.getFullString(); return javaModelPackage.getMultipartId().createMultipartId(name, null, null); } } public Type stringToType (String name) { return stringToType(name, name); } public Type stringToType (String fullName, String sourceName) { if ("boolean".equals(fullName)) // NOI18N return Type.BOOLEAN; if ("int".equals (fullName)) // NOI18N return Type.INT; if ("char".equals (fullName)) // NOI18N return Type.CHAR; if ("byte".equals (fullName)) // NOI18N return Type.BYTE; if ("short".equals (fullName)) // NOI18N return Type.SHORT; if ("long".equals (fullName)) // NOI18N return Type.LONG; if ("float".equals (fullName)) // NOI18N return Type.FLOAT; if ("double".equals (fullName)) // NOI18N return Type.DOUBLE; if ("void".equals (fullName) || fullName == null) // [PENDING] // NOI18N return Type.VOID; return Type.createClass (createClassIdentifier(fullName, sourceName)); } public Type typeReferenceToType (TypeReference descr) { if (descr == null) return null; Type type = null; if (descr instanceof ArrayReference) { type = multipartIdToType(descr.getParent()); int dimCount = ((ArrayReference) descr).getDimCount(); for (int x = 0; x < dimCount; x++) { type = Type.createArray (type); } } else { type = multipartIdToType((MultipartId)descr); } return type; } private Type multipartIdToType(MultipartId id) { String sourceName = multipartIdToName(id); String fullName; NamedElement elem = id.getElement(); int resolved = Identifier.RESOLVED; if (elem instanceof PrimitiveType) return stringToType(sourceName, null); if (JAVA_LANG_OBJECT.equals(sourceName)) { fullName = sourceName; } else { if (elem != null && (elem instanceof JavaClass)) { fullName = ((JavaClass) elem).getName(); } else { fullName = null; } // for some reason the fullname is sometimes null even if the // above condition is true (a class returns null from get name?) if (fullName == null) { fullName = sourceName; resolved = Identifier.UNRESOLVED; } } return Type.createClass(Identifier.create(fullName, sourceName, resolved)); } // [MaM] - migration to the new infrastructure // this method should probably by changed to "resolveClass" public JavaClass getClassDescriptor (String fullName) { return (JavaClass) javaModelPackage.getType().resolve(fullName); // ClassDescriptor res = getCodebase ().findClassDescriptor(fullName, true); // return res; } public Identifier createClassIdentifier (MultipartId id) { String sourceName = multipartIdToName(id); String fullName = null; JavaClass jcls = (JavaClass)id.getElement(); if (JAVA_LANG_OBJECT.equals(sourceName)) { fullName = sourceName; } else { fullName = jcls == null ? sourceName : typeToFullName(jcls); } int resolved = Identifier.RESOLVED; if (jcls == null || jcls instanceof UnresolvedClass) resolved = Identifier.UNRESOLVED; return Identifier.create(fullName, sourceName, resolved); } public static String multipartIdToName(MultipartId id) { LinkedList list = new LinkedList(); while (id != null) { if (!id.getTypeArguments().isEmpty()) { return JAVA_LANG_OBJECT; } list.addFirst(id.getName()); id = id.getParent(); } StringBuffer buf = new StringBuffer(); for (Iterator iter = list.iterator(); iter.hasNext();) { buf.append((String)iter.next()); if (iter.hasNext()) buf.append('.'); } return buf.toString(); } public String typeToFullName(JavaClass jc) { if (jc instanceof ParameterizedType) { ParameterizedType p = (ParameterizedType) jc; StringBuffer buf = new StringBuffer(); buf.append(typeToFullName(p.getDefinition())); List pars = p.getParameters(); if (pars.size() > 0) { buf.append('<'); for (Iterator iter = pars.iterator(); iter.hasNext(); ) { JavaClass par = (JavaClass) iter.next(); buf.append(typeToFullName(par)); if (iter.hasNext()) buf.append(','); } buf.append('>'); } return buf.toString(); } else { return jc.getName(); } } public Identifier createClassIdentifier (String fullName) { return createClassIdentifier (fullName, fullName); } public Identifier createClassIdentifier (String fullName, String sourceName) { // ProjectModel pm = ProjectModel.getDefault (); // [MaM] migration to the new infrastructure repository.beginTrans(false); try { setClassPath(); boolean exists = ClassIndex.hasClass(fullName, JavaMetamodel.getManager().getClassPath()); //boolean exists = pm.getDefaultClassPath ().exists (fullName); return Identifier.create ( fullName, sourceName, exists ? Identifier.RESOLVED : Identifier.UNRESOLVED ); } finally { repository.endTrans(false); } } public void checkIsValid () throws SourceException { try { javaElement.refImmediatePackage (); } catch (javax.jmi.reflect.InvalidObjectException e) { throwIsInvalid (); } } public void throwIsInvalid () throws SourceException { Util.throwException("Element was deleted", "EXC_ElementInvalid"); // NOI18N } public abstract void connectListener (); /** * Attaches the abstract layer to the element; since the all properties required * for the Binding to operate are available, the binding is created as well. */ public void attachedToElement(Element el) { this.element = el; if (!valid) return; repository.beginTrans (false); try { try { javaElement.refImmediateComposite(); } catch (javax.jmi.reflect.InvalidObjectException e) { setValid(false); } connectListener (); setValid (true); } catch (javax.jmi.reflect.InvalidObjectException e) { } finally { repository.endTrans (false); } } /** * Binds the element to a particular underlying Binding. The function does nothing * if the binding was already establised; it is impossible to rebind an element once * the binding was established (this constraint may be overriden by descendants) * * @param b binding to use for element i/o operations. */ public void setBinding(Binding b) { if (this.binding != null) return; if (b instanceof Node.Cookie) { getCookieSet().add((Node.Cookie)b); } binding = b; } // Listener interface functions /////////////////////////////////////////////////////////////////////////////////// private String describeEvent(PropertyChangeEvent evt) { StringBuffer sb = new StringBuffer(); sb.append(evt.getPropertyName()); Object oldV = evt.getOldValue(); sb.append(" old = " + describeValue(evt.getOldValue())); // NOI18N sb.append(" new = " + describeValue(evt.getNewValue())); // NOI18N return sb.toString(); } private String describeValue(Object o) { if (o instanceof Identifier) { Identifier id = (Identifier)o; return id.getSourceName() + "/" + id.getFullName() + "/" + // NOI18N id.getResolutionStatus(); } else if (o instanceof Identifier[]) { StringBuffer sb = new StringBuffer(); sb.append("[ "); // NOI18N Identifier[] ids = (Identifier[])o; for (int i = 0; i < ids.length; i++) { if (i > 0) sb.append(", "); // NOI18N sb.append(describeValue(ids[i])); } sb.append(" ]"); // NOI18N return sb.toString(); } else if (o instanceof MethodParameter[]) { MethodParameter[] pars = (MethodParameter[])o; if (pars.length == 0) return "()"; // NOI18N StringBuffer sb = new StringBuffer(); for (int i = 0; i < pars.length; i++) { if (i > 0) sb.append(", "); // NOI18N sb.append(pars[i].getSourceString()); sb.append("/"); // NOI18N Type t = pars[i].getType(); sb.append(t.getFullString()); while (t.isArray()) t = t.getElementType(); if (t.isClass()) { sb.append('/'); sb.append(new Integer(t.getTypeIdentifier().getResolutionStatus()).toString()); } } return sb.toString(); } else if (o instanceof Type) { Type t = (Type)o; String s = t.getSourceString() + "/" + t.getFullString(); // NOI18N while (t.isArray()) t = t.getElementType(); if (t.isClass()) { s = s + "/" + t.getTypeIdentifier().getResolutionStatus(); // NOI18N } return s; } else if (o != null) { return o.toString(); } else return "null"; // NOI18N } /** Adds property listener. */ public void addPropertyChangeListener (PropertyChangeListener l) { if (DEBUG_EVENTS) { System.err.println("[" + this + "] attaching listener " + l); // NOI18N } if (propListeners == null) { synchronized (this) { // new test under synchronized block if (propListeners == null) { propListeners = new LinkedList(); initializeListenerSupport(); } } } synchronized (propListeners) { propListeners.add(l); } } /** * Returns true, if the element is fully created. This yes/no test is used for supression * of some event firing and lightweight operations. */ protected boolean isCreated() { return this.inCreation; } /** Removes property listener */ public void removePropertyChangeListener (PropertyChangeListener l) { if (DEBUG_EVENTS) { System.err.println("[" + this + "] removing listener " + l); // NOI18N } if (propListeners != null) { synchronized (propListeners) { propListeners.remove(l); } } } /** Adds property vetoable listener */ public void addVetoableChangeListener (VetoableChangeListener l) { if (DEBUG_EVENTS) { System.err.println("[" + this + "] attaching veto listener " + l); // NOI18N } if (vetoSupport == null) { synchronized (this) { // new test under synchronized block if (vetoSupport == null) { vetoSupport = new VetoableChangeSupport (element); initializeListenerSupport(); } } } vetoSupport.addVetoableChangeListener (l); } /** Removes property vetoable listener */ public void removeVetoableChangeListener (VetoableChangeListener l) { if (DEBUG_EVENTS) { System.err.println("[" + this + "] removing veto listener " + l); // NOI18N } if (vetoSupport != null) { vetoSupport.removeVetoableChangeListener (l); } } /** true if some vetoable listener is currently registered */ public boolean hasVetoableListeners (String propName) { if (vetoSupport == null) return false; else return vetoSupport.hasListeners (propName); } /** Base method for marking the current insertion point. */ public void markCurrent(boolean beforeAfter) { // PENDING: redirect to the new facilities for element ordering. } /** Returns the abstract wrapper for this implementation. */ public final Element getElement() { return element; } /** * Returns the cookie set so that extension objects can plug in and * extend the element implementation. * @return r/w cookie set instance. */ public final CookieSet getCookieSet() { if (cookieSet == null) { synchronized (this) { if (cookieSet == null) { cookieSet = new CookieSet(); initializeCookies(cookieSet); } } } return cookieSet; } protected void initializeCookies(CookieSet set) { set.add(this); set.add(new JMIElementCookieImpl()); } /** * Returns true, if the element is still valid - that is present in the model. * @return true, iff the element is still valid. */ public boolean isValid() { return this.valid; } // Support functions ///////////////////////////////////////////////////////////////////////////////// /** Fires property change event. The event is fired as "own" property change event, * so it is captured in the queue and counted for the summary information. * @param name property name * @param o old value * @param n new value */ protected final void firePropertyChange(String name, Object o, Object n) { fireOwnPropertyChange(new PropertyChangeEvent(getElement(), name, o, n)); } /** * Fires a PropertyChangeEvent to the listeners, if there's a listener. */ protected final void firePropertyChangeEvent(PropertyChangeEvent evt) { if (DEBUG_EVENTS) { StringBuffer sb = new StringBuffer(); sb.append('['); sb.append(toString()); sb.append("] Dispatching change: "); // NOI18N sb.append(describeEvent(evt)); System.err.println(sb.toString()); } if (propListeners == null) return; Vector listeners; synchronized (propListeners) { listeners = new Vector(propListeners); } for (int i = 0; i < listeners.size(); i++) { PropertyChangeListener l = (PropertyChangeListener)listeners.elementAt(i); l.propertyChange(evt); } } /** * Fires an arbitrary property change event about intrinsic property change. * Events fired though this method will show up in the change summary events * fired after the model's lock is released. The method does nothing if the element * is in the creation phase. |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.