Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Energy, onHostDestruction: ensured ptr existence
[simgrid.git] / contrib / psg / src / peersim / dynamics / WireByMethod.java
1 /*
2  * Copyright (c) 2003-2005 The BISON Project
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  */
18
19 package peersim.dynamics;
20
21 import peersim.graph.*;
22 import peersim.core.*;
23 import peersim.config.*;
24 import java.lang.reflect.*;
25 import java.util.ArrayList;
26
27 /**
28  * Takes a {@link Linkable} protocol and adds connections using an arbitrary
29  * method.
30  * No connections are removed.
31  * The connections are added by an arbitrary method that can be specified
32  * in the configuration. 
33  * The properties the method has to fulfill are the following
34  <ul>
35  <li>It MUST be static</li>
36  <li>It MUST have a first argument that can be assigned from a class
37  that implements {@link Graph}.</li>
38  <li>It MAY contain zero or more arguments following the first one.</li>
39  <li>All the arguments after the first one MUST be of primitive type int,
40  long or double, except
41  the last one, which MAY be of type that can be assigned from
42  <code>java.util.Random</code></li>
43  </ul>
44  The arguments are initialized using the configuration as follows.
45  <ul>
46  <li>The first argument is the {@link Graph} that is passed to
47  {@link #wire}.</li>
48  <li>The arguments after the first one (indexed as 1,2,etc) are initialized
49  from configuration parameters of the form {@value #PAR_ARG}i, where i is the
50  index.
51  <li>If the last argument can be assigned from 
52  <code>java.util.Random</code> then it is initialized with
53  {@link CommonState#r}, the central source of randomness for the
54  simulator.</li>
55  </ul>
56  For example, the class {@link WireWS} can be emulated by configuring
57  <pre>
58  init.0 WireByMethod
59  init.0.class GraphFactory
60  init.0.method wireWS
61  init.0.arg1 10
62  init.0.arg2 0.1
63  ...
64  </pre>
65  Note that the {@value #PAR_CLASS} parameter defaults to {@link GraphFactory},
66  and {@value #PAR_METHOD} defaults to "wire".
67  */
68 public class WireByMethod extends WireGraph {
69
70 //--------------------------------------------------------------------------
71 //Parameters
72 //--------------------------------------------------------------------------
73
74 /**
75  * The prefix for the configuration properties that describe parameters.
76  * @config
77  */
78 private static final String PAR_ARG = "arg";
79
80 /**
81 * The class that has the method we want to use. Defaults to
82 * {@link GraphFactory}.
83 * @config
84 */
85 private static final String PAR_CLASS = "class";
86
87 /**
88 * The name of the method for wiring the graph. Defaults to <code>wire</code>.
89 * @config
90 */
91 private static final String PAR_METHOD = "method";
92
93 //--------------------------------------------------------------------------
94 //Fields
95 //--------------------------------------------------------------------------
96
97 private final Object[] args;
98
99 private final Method method;
100
101 //--------------------------------------------------------------------------
102 //Initialization
103 //--------------------------------------------------------------------------
104
105 /**
106  * Loads configuration. It verifies the constraints defined
107  * in {@link WireByMethod}.
108  * @param prefix the configuration prefix for this class
109  */
110 public WireByMethod(String prefix)
111 {
112         super(prefix);
113         
114         // get the method
115         try
116         {
117                 final Class wire =
118                         Configuration.getClass(prefix + "." + PAR_CLASS,
119                 Class.forName("peersim.graph.GraphFactory"));
120                 method = WireByMethod.getMethod(
121                         wire,
122                         Configuration.getString(prefix+"."+PAR_METHOD,"wire"));
123         }
124         catch( Exception e )
125         {
126                 throw new RuntimeException(e);
127         }
128         
129         // set the constant args (those other than 0th)
130         Class[] argt = method.getParameterTypes();
131         args = new Object[argt.length];
132         for(int i=1; i<args.length; ++i)
133         {
134                 
135                 if( argt[i]==int.class )
136                         args[i]=Configuration.getInt(prefix+"."+PAR_ARG+i);
137                 else if( argt[i]==long.class )
138                         args[i]=Configuration.getLong(prefix+"."+PAR_ARG+i);
139                 else if( argt[i]==double.class )
140                         args[i]=Configuration.getDouble(prefix+"."+PAR_ARG+i);
141                 else if(i==args.length-1 && argt[i].isInstance(CommonState.r))
142                         args[i]=CommonState.r;
143                 else
144                 {
145                         // we should neve get here
146                         throw new RuntimeException("Unexpected error, please "+
147                         "report this problem to the peersim team");
148                 }
149         }
150 }
151
152 //--------------------------------------------------------------------------
153
154 /**
155  * Search a wiring method in the specified class.
156  * @param cl
157  *          the class where to find the method
158  * @param methodName
159  *          the method to be searched
160  * @return the requested method, if it fully conforms to the definition of
161  * the wiring methods.
162  */
163 private static Method getMethod(Class cl, String methodName)
164                 throws NoSuchMethodException, ClassNotFoundException {
165                 
166         // Search methods
167         Method[] methods = cl.getMethods();
168         ArrayList<Method> list = new ArrayList<Method>();
169         for (Method m: methods) {
170                 if (m.getName().equals(methodName)) {
171                         list.add(m);
172                 }
173         }
174         
175         if (list.size() == 0) {
176                 throw new NoSuchMethodException("No method "
177                 + methodName + " in class " + cl.getSimpleName());
178         } else if (list.size() > 1) {
179                 throw new NoSuchMethodException("Multiple methods called "
180                 + methodName + " in class " + cl.getSimpleName());
181         }
182         
183         // Found a single method with the right name; check if
184         // it is a setter.
185         final Class graphClass = Class.forName("peersim.graph.Graph");
186         final Class randomClass = Class.forName("java.util.Random");
187         Method method = list.get(0);
188         Class[] pars = method.getParameterTypes();
189         if( pars.length < 1 || !pars[0].isAssignableFrom(graphClass) )
190                 throw new NoSuchMethodException(method.getName() + " of class "
191                 + cl.getSimpleName() + " is not a valid graph wiring method,"+
192                 " it has to have peersim.graph.Graph as first argument type");
193         for(int i=1; i<pars.length; ++i)
194                 if( !( pars[i]==int.class || pars[i]==long.class ||
195                 pars[i]==double.class ||
196                 (i==pars.length-1 && pars[i].isAssignableFrom(randomClass)) ) )
197                         throw new NoSuchMethodException(method.getName() +
198                         " of class "+ cl.getSimpleName()
199                         + " is not a valid graph wiring method");
200                         
201         if(method.toString().indexOf("static")<0)
202                 throw new NoSuchMethodException(method.getName() +
203                 " of class "+ cl.getSimpleName()
204                 + " is not a valid graph wiring method; it is not static");
205         
206         return method;
207 }
208
209
210 //--------------------------------------------------------------------------
211 //Methods
212 //--------------------------------------------------------------------------
213
214 /** Invokes the method passing g to it.*/
215 public void wire(Graph g) {
216
217         args[0]=g;
218         try { method.invoke(null,args); }
219         catch( Exception e ) { throw new RuntimeException(e); }
220 }
221
222 }
223