Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
peersimgrid release 1.0
[simgrid.git] / contrib / psg / src / peersim / dynamics / WireByMethod.java
diff --git a/contrib/psg/src/peersim/dynamics/WireByMethod.java b/contrib/psg/src/peersim/dynamics/WireByMethod.java
new file mode 100644 (file)
index 0000000..de32a69
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2003-2005 The BISON Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+package peersim.dynamics;
+
+import peersim.graph.*;
+import peersim.core.*;
+import peersim.config.*;
+import java.lang.reflect.*;
+import java.util.ArrayList;
+
+/**
+ * Takes a {@link Linkable} protocol and adds connections using an arbitrary
+ * method.
+ * No connections are removed.
+ * The connections are added by an arbitrary method that can be specified
+ * in the configuration. 
+ * The properties the method has to fulfill are the following
+ <ul>
+ <li>It MUST be static</li>
+ <li>It MUST have a first argument that can be assigned from a class
+ that implements {@link Graph}.</li>
+ <li>It MAY contain zero or more arguments following the first one.</li>
+ <li>All the arguments after the first one MUST be of primitive type int,
+ long or double, except
+ the last one, which MAY be of type that can be assigned from
+ <code>java.util.Random</code></li>
+ </ul>
+ The arguments are initialized using the configuration as follows.
+ <ul>
+ <li>The first argument is the {@link Graph} that is passed to
+ {@link #wire}.</li>
+ <li>The arguments after the first one (indexed as 1,2,etc) are initialized
+ from configuration parameters of the form {@value #PAR_ARG}i, where i is the
+ index.
+ <li>If the last argument can be assigned from 
+ <code>java.util.Random</code> then it is initialized with
+ {@link CommonState#r}, the central source of randomness for the
+ simulator.</li>
+ </ul>
+ For example, the class {@link WireWS} can be emulated by configuring
+ <pre>
+ init.0 WireByMethod
+ init.0.class GraphFactory
+ init.0.method wireWS
+ init.0.arg1 10
+ init.0.arg2 0.1
+ ...
+ </pre>
+ Note that the {@value #PAR_CLASS} parameter defaults to {@link GraphFactory},
+ and {@value #PAR_METHOD} defaults to "wire".
+ */
+public class WireByMethod extends WireGraph {
+
+//--------------------------------------------------------------------------
+//Parameters
+//--------------------------------------------------------------------------
+
+/**
+ * The prefix for the configuration properties that describe parameters.
+ * @config
+ */
+private static final String PAR_ARG = "arg";
+
+/**
+* The class that has the method we want to use. Defaults to
+* {@link GraphFactory}.
+* @config
+*/
+private static final String PAR_CLASS = "class";
+
+/**
+* The name of the method for wiring the graph. Defaults to <code>wire</code>.
+* @config
+*/
+private static final String PAR_METHOD = "method";
+
+//--------------------------------------------------------------------------
+//Fields
+//--------------------------------------------------------------------------
+
+private final Object[] args;
+
+private final Method method;
+
+//--------------------------------------------------------------------------
+//Initialization
+//--------------------------------------------------------------------------
+
+/**
+ * Loads configuration. It verifies the constraints defined
+ * in {@link WireByMethod}.
+ * @param prefix the configuration prefix for this class
+ */
+public WireByMethod(String prefix)
+{
+       super(prefix);
+       
+       // get the method
+       try
+       {
+               final Class wire =
+                       Configuration.getClass(prefix + "." + PAR_CLASS,
+               Class.forName("peersim.graph.GraphFactory"));
+               method = WireByMethod.getMethod(
+                       wire,
+                       Configuration.getString(prefix+"."+PAR_METHOD,"wire"));
+       }
+       catch( Exception e )
+       {
+               throw new RuntimeException(e);
+       }
+       
+       // set the constant args (those other than 0th)
+       Class[] argt = method.getParameterTypes();
+       args = new Object[argt.length];
+       for(int i=1; i<args.length; ++i)
+       {
+               
+               if( argt[i]==int.class )
+                       args[i]=Configuration.getInt(prefix+"."+PAR_ARG+i);
+               else if( argt[i]==long.class )
+                       args[i]=Configuration.getLong(prefix+"."+PAR_ARG+i);
+               else if( argt[i]==double.class )
+                       args[i]=Configuration.getDouble(prefix+"."+PAR_ARG+i);
+               else if(i==args.length-1 && argt[i].isInstance(CommonState.r))
+                       args[i]=CommonState.r;
+               else
+               {
+                       // we should neve get here
+                       throw new RuntimeException("Unexpected error, please "+
+                       "report this problem to the peersim team");
+               }
+       }
+}
+
+//--------------------------------------------------------------------------
+
+/**
+ * Search a wiring method in the specified class.
+ * @param cl
+ *          the class where to find the method
+ * @param methodName
+ *          the method to be searched
+ * @return the requested method, if it fully conforms to the definition of
+ * the wiring methods.
+ */
+private static Method getMethod(Class cl, String methodName)
+               throws NoSuchMethodException, ClassNotFoundException {
+               
+       // Search methods
+       Method[] methods = cl.getMethods();
+       ArrayList<Method> list = new ArrayList<Method>();
+       for (Method m: methods) {
+               if (m.getName().equals(methodName)) {
+                       list.add(m);
+               }
+       }
+       
+       if (list.size() == 0) {
+               throw new NoSuchMethodException("No method "
+               + methodName + " in class " + cl.getSimpleName());
+       } else if (list.size() > 1) {
+               throw new NoSuchMethodException("Multiple methods called "
+               + methodName + " in class " + cl.getSimpleName());
+       }
+       
+       // Found a single method with the right name; check if
+       // it is a setter.
+       final Class graphClass = Class.forName("peersim.graph.Graph");
+       final Class randomClass = Class.forName("java.util.Random");
+       Method method = list.get(0);
+       Class[] pars = method.getParameterTypes();
+       if( pars.length < 1 || !pars[0].isAssignableFrom(graphClass) )
+               throw new NoSuchMethodException(method.getName() + " of class "
+               + cl.getSimpleName() + " is not a valid graph wiring method,"+
+               " it has to have peersim.graph.Graph as first argument type");
+       for(int i=1; i<pars.length; ++i)
+               if( !( pars[i]==int.class || pars[i]==long.class ||
+               pars[i]==double.class ||
+               (i==pars.length-1 && pars[i].isAssignableFrom(randomClass)) ) )
+                       throw new NoSuchMethodException(method.getName() +
+                       " of class "+ cl.getSimpleName()
+                       + " is not a valid graph wiring method");
+                       
+       if(method.toString().indexOf("static")<0)
+               throw new NoSuchMethodException(method.getName() +
+               " of class "+ cl.getSimpleName()
+               + " is not a valid graph wiring method; it is not static");
+       
+       return method;
+}
+
+
+//--------------------------------------------------------------------------
+//Methods
+//--------------------------------------------------------------------------
+
+/** Invokes the method passing g to it.*/
+public void wire(Graph g) {
+
+       args[0]=g;
+       try { method.invoke(null,args); }
+       catch( Exception e ) { throw new RuntimeException(e); }
+}
+
+}
+