001    /*
002      Copyright (C) 2001-2002 Renaud Pawlak, Laurent Martelli
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    import java.util.*;
022    import org.objectweb.jac.core.ACManager;
023    import org.objectweb.jac.util.ExtArrays;
024    
025    /**
026     * This class defines the super class for all the meta items whithin
027     * the rtti aspect.<p>
028     *
029     * A meta item encapsulates a <code>java.lang.reflect</code> item so
030     * that the user of this item can add extra informations
031     * (attributes). Typically this feature can be used by an aspect to
032     * tag an element of the model to react to this tag later on.<p>
033     *
034     * Examples:<p> <ul> 
035     *
036     * <li>A persistence aspect can tag some field persistent, add methods
037     * that change the object states even if they do not fit naming
038     * conventions...<p>
039     *
040     * <li>A GUI can tag a given field to be invisible or a class to be
041     * displayed by a special view (eg a given Swing component)...
042     *
043     * </ul>
044     *
045     * @author Renaud Pawlak
046     * @author Laurent Martelli
047     */
048    
049    public abstract class MetaItem {
050    
051        /** A correspondance table between the RRTI attributes and the
052            aspect components that set them. */
053        protected static HashMap attrACs = new HashMap();
054    
055        /**
056         * Unsets all the attributes of all the RTTI items that have been
057         * set by a given aspect component.<p>
058         *
059         * @param acName the aspect component name
060         * @see #unsetAttribute(String) */
061       
062        public static void unsetAttributesFor( String acName ) {}
063    
064        /* A <code>name -> value</code> container. */
065        private HashMap attributes = new HashMap();
066    
067        static ACManager acManager;
068        static Method acManagerGetObjectMethod;
069        static Method acManagerGetMethod;
070       
071        static {
072            try {
073                acManagerGetMethod = 
074                    Class.forName("org.objectweb.jac.core.ACManager").getMethod("get",new Class[0]);
075                acManagerGetObjectMethod =
076                    Class.forName("org.objectweb.jac.core.ACManager").getMethod(
077                        "getObject",new Class[]{String.class});
078            } catch(Exception e) {
079                e.printStackTrace();
080            }
081        }
082    
083        Object getAC(String name) {
084            Object ac = null;
085            try {
086                if (acManager==null) {
087                    acManager = 
088                        (ACManager)acManagerGetMethod.invoke(null,ExtArrays.emptyObjectArray);
089                }
090                ac = acManagerGetObjectMethod.invoke(acManager,new Object[]{name});
091            } catch (Exception e) {
092                e.printStackTrace();
093            }
094            return ac;
095        }
096    
097        boolean isRegisteredAC( String name ) {
098            return getAC(name)!=null;
099        }
100    
101        static Method collabGetMethod = null;
102        static Method collabGetCurACMethod = null;
103    
104        String getCurAC() {
105            /*
106              Object acName = null;
107              try {
108              Class collaboration = Class.forName("org.objectweb.jac.core.Collaboration");
109              if (collabGetMethod==null) {
110              collabGetMethod = collaboration.getMethod("get",ExtArrays.emptyClassArray);
111              }
112              Object coll = collabGetMethod.invoke(null,ExtArrays.emptyObjectArray);
113              if (collabGetCurACMethod==null) {
114              collabGetCurACMethod = 
115              coll.getClass().getMethod("getCurAC",ExtArrays.emptyClassArray);
116              }
117              acName = collabGetCurACMethod.invoke(coll,ExtArrays.emptyObjectArray);
118              } catch (Exception e) {
119              e.printStackTrace();
120              }
121              return (String)acName;
122            */
123            return null;
124        }
125    
126        static AttributeController accessController = null;
127    
128        /**
129         * Registers a new access controller for this application.
130         *
131         * @param controller the controller object
132         */
133        public static void registerAccessController(AttributeController controller) {
134            accessController = controller;
135        }
136    
137        Object controlledAccess(Object substance, String name, Object value) {
138            if ( accessController==null || 
139                 ! (name.equals("GuiAC.VISIBLE") ||
140                    name.equals("GuiAC.EDITABLE") ||
141                    name.equals("GuiAC.ADDABLE") ||
142                    name.equals("GuiAC.CREATABLE") ||
143                    name.equals("GuiAC.REMOVABLE")) ) 
144                return value;
145    
146            Object result = null;
147            try {
148                result = accessController.controlAttribute(substance,this,name,value);
149            } catch(Exception e) {
150                e.printStackTrace();
151                return value;
152            }
153            return result;
154        }
155    
156    
157        /**
158         * Gets the value of an attribute.
159         *
160         * @param name the name of the attribute
161         * @return the value of the attribute
162         */
163    
164        public Object getAttribute(String name) {
165            return getAttribute(name,false);
166        }
167    
168        /**
169         * Gets the value of an attribute even if the aspect if not yet
170         * configured and weaved.
171         *
172         * @param name the name of the attribute
173         * @return the value of the attribute
174         */
175        public Object getAttributeAlways(String name) {
176            return getAttribute(name,true);
177        }
178    
179        /**
180         * Gets the value of an attribute.
181         *
182         * @param name the name of the attribute
183         * @param always if true, return a value even the aspect is not weaved
184         * @return the value of the attribute
185         *
186         */
187        public Object getAttribute(String name, boolean always) {
188            String acName = (String)attrACs.get(name);
189            if (!always && (acName!=null && (!isRegisteredAC(acName))) ) {
190                return null;
191            }
192            Object value=attributes.get(name);
193            if (value==null && itemClass!=null) {
194                value = itemClass.getAttribute(name);
195            }
196            return controlledAccess(null,name,value);
197        }
198    
199        /**
200         * Gets the value of a boolean attribute.
201         *
202         * @param name the name of the attribute
203         * @param defValue default value for the attribute if it is not set
204         * @return the value of the attribute
205         */
206        public boolean getBoolean(String name, boolean defValue) {
207            Boolean value = (Boolean)getAttribute(name);
208            if (value==null)
209                return defValue;
210            else
211                return value.booleanValue();
212        }
213    
214        /**
215         * Gets the value of an attribute.
216         *
217         * @param substance
218         * @param name the name of the attribute
219         * @return the value of the attribute
220         */
221    
222        public Object getAttribute(Object substance, String name) {
223            String acName = (String)attrACs.get(name);
224            if( acName!=null && (!isRegisteredAC(acName)) ) {
225                return null;
226            }
227            Object value=attributes.get(name);
228            if (value==null && itemClass!=null) {
229                value = itemClass.getAttribute(name);
230            }
231            return controlledAccess(substance,name,value);
232        }
233    
234        /**
235         * Sets the value of an attribute.
236         *
237         * @param name the name of the attribute
238         * @param value the value of the attribute
239         */
240    
241        public final void setAttribute(String name, Object value) {
242            if (name == null) 
243                return;
244            String acName = (String)getCurAC();
245            if (acName != null) {
246                if ( !attrACs.containsKey(name) ) {
247                    attrACs.put(name,acName);
248                }
249            }
250            attributes.put(name,value);
251        }
252    
253        /**
254         * Unsets the value of an attribute.
255         *
256         * @param name the name of the attribute to unset
257         */
258    
259        public void unsetAttribute(String name) {
260            attributes.remove(name);
261        }
262    
263        /**
264         * This method gets the name of the meta item by delegating to the
265         * actual <code>java.lang.reflect</code> meta item.<p>
266         *
267         * @return the item name */
268    
269        public abstract String getName();
270    
271        MetaItem itemClass;
272        public void setItemClass(MetaItem itemClass) {
273            this.itemClass = itemClass;
274        }
275        public MetaItem getItemClass() {
276            return itemClass;
277        }
278    }