001 /* 002 Copyright (C) 2001-2002 Renaud Pawlak, Eddy Truyen. 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 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA */ 018 019 package org.objectweb.jac.core; 020 021 import java.util.Collection; 022 import java.util.HashMap; 023 import java.util.HashSet; 024 import java.util.Hashtable; 025 import java.util.Iterator; 026 import java.util.Map; 027 028 /** 029 * This class represents a set of contextual informations for a given 030 * thread of a running JAC system. 031 * 032 * <p>For each method call on a JAC object, a new interaction is 033 * started on the current collaboration. At any point of the program, 034 * the programmer can get the current collaboration for the current 035 * thread by using <code>get()</code>. 036 * 037 * <p>The <code>CollaborationParticipant</code> interface provides a 038 * more friendly interface to access the current collaboration. In a 039 * clean design, only the classes that implement this interface may 040 * access the collaboration. 041 * 042 * @see Collaboration#get() 043 * @see CollaborationParticipant 044 * 045 * @author Renaud Pawlak 046 * @author Eddy Truyen 047 */ 048 049 public class Collaboration implements java.io.Serializable { 050 051 /** The attribute is global to all the sites (it is serialized and 052 transmitted with the collaboration) */ 053 public static Object GLOBAL=new Integer(1); 054 055 transient static Hashtable attrTypes=new Hashtable(); 056 057 /** 058 * Returns true if the attribute is global. The attribute is 059 * then transmitted to the remote sites reached by the 060 * collaboration. Note that a global attribute must always be 061 * serializable. If the attribute is not global, it 062 * always stays on the site where it has been defined. 063 * 064 * <p>By default, if the <code>setGlobal</code> method is not 065 * called, all the attributes are local. 066 * 067 * @see #setGlobal(String) 068 */ 069 public static boolean isGlobal(String attrName) { 070 if(attrTypes.get(attrName)==GLOBAL) { 071 return true; 072 } else { 073 return false; 074 } 075 } 076 077 /** 078 * Sets an attribute to be global. 079 * 080 * <p>This method should only be called once for each attribute and 081 * before the first initialization of the attribute value in the 082 * collaboration since the globality is an inherent caracteristic 083 * of an attribute. 084 */ 085 public static void setGlobal(String attrName) { 086 attrTypes.put(attrName,GLOBAL); 087 } 088 089 /** Stores collaborations for all threads. */ 090 transient static Hashtable collaborations = new Hashtable(); 091 092 /** Static initialization of the collaborations. */ 093 094 static { 095 Thread current = Thread.currentThread(); 096 collaborations.put ( current, new Collaboration() ); 097 } 098 099 /** 100 * Get the collaboration for the current thread. 101 * 102 * @return the current collaboration 103 */ 104 public static Collaboration get() { 105 Thread current = Thread.currentThread(); 106 Collaboration ret = (Collaboration) collaborations.get(current); 107 if ( ret == null ) { 108 collaborations.put ( current, ret = new Collaboration() ); 109 } 110 return ret; 111 } 112 113 /** 114 * Set a new collaboration for the current thread. 115 * 116 * @param collaboration the collaboration 117 */ 118 public static void set(Collaboration collaboration) { 119 Thread current = Thread.currentThread(); 120 collaborations.put(current, collaboration); 121 } 122 123 /** Store the attributes of the interaction. */ 124 private HashMap attrs; 125 126 /** 127 * Creates an new collaboration. 128 * 129 * <p>The programmer should not explicitly create a new 130 * collaboration since this is automatically done by the system for 131 * any new thread. 132 * 133 * <p> At any point of the program, the programmer can get the 134 * current collaboration for the current thread by using 135 * <code>Collaboration.get()</code>. 136 * 137 * @see Collaboration#get() 138 */ 139 public Collaboration() { 140 reset(); 141 } 142 143 /** 144 * Create a new Collaboration and initialiaze it's attribute from a 145 * parent Collaboration. 146 * 147 * @param parent the parent collaboration 148 */ 149 public Collaboration(Collaboration parent) { 150 reset(); 151 if (parent!=null) { 152 Iterator it = parent.attributeNames().iterator(); 153 while (it.hasNext()) { 154 String attrName = (String)it.next(); 155 addAttribute( 156 attrName,parent.getAttribute(attrName)); 157 } 158 } 159 } 160 161 /** 162 * Returns a collection of all attribute names 163 */ 164 public Collection attributeNames() { 165 HashSet names = new HashSet(); 166 names.addAll(attrs.keySet()); 167 return names; 168 } 169 170 public static Collection globalAttributeNames() { 171 HashSet names = new HashSet(); 172 names.addAll(attrTypes.keySet()); 173 return names; 174 } 175 176 /** 177 * Returns the map of attribute's name -> value 178 */ 179 public Map getAttributes() { 180 return (Map)attrs.clone(); 181 } 182 183 /** 184 * Set some attributes. Do not override current attributes. 185 * @param attributes map of name->value of attributes to set. 186 */ 187 public void setAttributes(Map attributes) { 188 Iterator it = attributes.entrySet().iterator(); 189 while (it.hasNext()) { 190 Map.Entry entry = (Map.Entry)it.next(); 191 if (!attrs.containsKey(entry.getKey())) 192 attrs.put(entry.getKey(),entry.getValue()); 193 } 194 } 195 196 /** 197 * Reset the Collaboration. 198 * <p>Clears interactions, and all attributes. 199 */ 200 public void reset() { 201 attrs = new HashMap(); 202 } 203 204 /** 205 * Add a persistent attribute to the collaboration (can be done by 206 * any Jac object). 207 * 208 * <p>NOTE: a persitent attribute is visible for all the objects of a 209 * collaboration. 210 * 211 * @param name the name of the attribute 212 * @param att the value of the attribute 213 */ 214 public Object addAttribute(String name, Object att) { 215 if ( name != null ) { 216 attrs.put(name, att); 217 } 218 return att; 219 } 220 221 /** 222 * Return the value of an attribute for the current collaboration. 223 * 224 * <p>This method first seeks into the persistent attributes. If 225 * none matches, it seeks into the transient attributes. If still 226 * not found, finally seeks into the transient local attributes. If 227 * all the lookups failed, return null. 228 * 229 * @param name the name of the attribute 230 * @return the value of the attribute 231 */ 232 public Object getAttribute(String name) { 233 if (attrs.containsKey(name)) { 234 return attrs.get(name); 235 } 236 return null; 237 } 238 239 /** 240 * Removes the attribute from the current collaboration. 241 */ 242 public void removeAttribute(String name) { 243 attrs.remove(name); 244 } 245 246 String cur_App; 247 248 public final void setCurApp(String app) { 249 this.cur_App = app; 250 } 251 252 public final String getCurApp() { 253 return cur_App; 254 } 255 256 /** 257 * Returns a textual representation of the collaboration. 258 */ 259 public String toString() { 260 return "Collaboration: \n" + 261 "attributes = " + attrs.toString(); 262 } 263 264 265 }