001    /*
002      Copyright (C) 2002-2003 Laurent Martelli <laurent@aopsys.com>
003      
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.core.rtti;
019    
020    import java.lang.reflect.*;
021    /**
022     * This class defines a meta item that corresponds to a field or a
023     * method.
024     *
025     * @author Renaud Pawlak
026     * @author Laurent Martelli
027     */
028    
029    public abstract class MemberItem extends MetaItemDelegate {
030    
031        /**
032         * A util method to get a member item reference from a full name.
033         *
034         * @param str member's full name, E.g.: myPackage.Person.name. 
035         */
036        public static MemberItem getMemberFromFullName(String str) throws Exception {
037            MemberItem ret=null;
038            int index = -1;
039            int paren = str.indexOf("(");
040            if (paren==-1)
041                index = str.lastIndexOf(".");
042            else
043                index = str.lastIndexOf(".",paren);
044            if (index!=-1) {
045                ClassItem classItem = 
046                    ClassRepository.get().getClass
047                    (str.substring(0,index));
048                ret = classItem.getMember(str.substring(index+1));
049            } else {
050                new Exception("Failed to convert "+str+
051                              " into a class member");
052            }
053            return ret;
054        }
055    
056        static Class wrappeeClass = ClassRepository.wrappeeClass;
057    
058        public MemberItem(ClassItem parent) {
059            this.parent = parent;
060        }
061    
062        public MemberItem(Object delegate, ClassItem parent) throws InvalidDelegateException {
063            super(delegate);
064            this.parent = parent;
065        }
066    
067        public abstract Class getType();
068    
069        public final ClassItem getTypeItem() {
070            return ClassRepository.get().getClass(getType());
071        }
072    
073        /** Returns the class item that owns the field (like getParent). */ 
074        public final ClassItem getClassItem() {
075            return (ClassItem)getParent();
076        }
077    
078        MethodItem[] dependentMethods = MethodItem.emptyArray;
079        /**
080         * @see #getDependentMethods()
081         */
082        public final void addDependentMethod(MethodItem method) {
083            MethodItem[] tmp = new MethodItem[dependentMethods.length+1];
084            System.arraycopy(dependentMethods, 0, tmp, 0, dependentMethods.length);
085            tmp[dependentMethods.length] = method;
086            dependentMethods = tmp;
087            ClassItem superClass = getClassItem().getSuperclass();
088            if (superClass!=null) {
089                FieldItem superField = superClass.getFieldNoError(getName());
090                if (superField!=null)
091                    superField.addDependentMethod(method);
092            }
093        }
094        /**
095         * Returns an array of methods whose result depend on the member.
096         * @see #addDependentMethod(MethodItem)
097         */
098        public final MethodItem[] getDependentMethods() {
099            return dependentMethods;
100        }
101    
102    
103        protected boolean role;
104       
105        /**
106         * Tells if this field is actually implemented by a role wrapper
107         * field.
108         *
109         * @return value of role
110         * @see #setRole(ClassItem,String,String) */
111    
112        public boolean isRole() {
113            return role;
114        }
115    
116        protected ClassItem roleClassType = null;
117        protected String roleType = null;
118        protected String roleName = null;
119       
120        /**
121         * Sets this field to be actually implemented by a field of a role
122         * wrapper.
123         *
124         * <p>When this method is called once, the <code>isRole()</code>
125         * method will return true. Moreover, the actually accessed and
126         * modified field when using set, get, etc, is the field of the
127         * role wrapper.
128         */
129        public void setRole(ClassItem roleClassType, String roleType, String roleName) {
130            this.role = true;
131            this.roleClassType = roleClassType;
132            this.roleType = roleType;
133            this.roleName = roleName;
134        }
135       
136        /**
137         * Returns the name prfixed with the owning class name.
138         */
139        public String getLongName() {
140            return parent!=null ? parent.getName()+"."+getName() : "???";
141        }
142    
143        public int getModifiers() {
144            return ((Member)delegate).getModifiers();
145        }
146    
147        public String toString() {
148            return getLongName()+":"+getType().getName();
149        }
150    
151        /**
152         * Two members are equal if the class of one is a subclass of the
153         * other's class and they have the same name
154         */
155        public boolean equals(Object o) {
156            if (!(o instanceof MemberItem)) 
157                return false;
158            MemberItem m = (MemberItem)o;
159            return (m.getClassItem().isSubClassOf(getClassItem()) ||
160                    getClassItem().isSubClassOf(m.getClassItem()))
161                && getName().equals(m.getName());
162        }
163    }