All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oms3.util.Components Maven / Gradle / Ivy

There is a newer version: 0.8.1
Show newest version
/*
 * $Id:$
 * 
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 
 *  1. The origin of this software must not be misrepresented; you must not
 *     claim that you wrote the original software. If you use this software
 *     in a product, an acknowledgment in the product documentation would be
 *     appreciated but is not required.
 * 
 *  2. Altered source versions must be plainly marked as such, and must not be
 *     misrepresented as being the original software.
 * 
 *  3. This notice may not be removed or altered from any source
 *     distribution.
 */
package oms3.util;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import oms3.Access;
import oms3.ComponentAccess;
import oms3.annotations.Bound;
import oms3.annotations.Description;
import oms3.annotations.Documentation;
import oms3.annotations.Execute;
import oms3.annotations.In;
import oms3.annotations.Out;
import oms3.annotations.Role;

/**
 * Basic component utility methods.
 * 
 * @author Olaf David
 */
public class Components {

    private Components() {
    }

    public static List parameter(Class comp) {
        List f = new ArrayList();
        for (Field field : comp.getFields()) {
            Role r = field.getAnnotation(Role.class);
            if (r != null && Annotations.plays(r, Role.PARAMETER)) {
                f.add(field);
            }
        }
        return f;
    }

    public static List inVars(Class comp) {
        List f = new ArrayList();
        for (Field field : comp.getFields()) {
            In in = field.getAnnotation(In.class);
            if (in != null) {
                Role r = field.getAnnotation(Role.class);
                if (r != null && Annotations.plays(r, Role.PARAMETER)) {
                    continue;
                }
                f.add(field);
            }
        }
        return f;
    }

    public static List outVars(Class comp) {
        List f = new ArrayList();
        for (Field field : comp.getFields()) {
            Out out = field.getAnnotation(Out.class);
            if (out != null) {
                f.add(field);
            }
        }
        return f;
    }

    static boolean isComponentClass(Class c) {
        Method[] m = c.getMethods();
        for (Method method : m) {
            if (method.getAnnotation(Execute.class) != null) {
                return true;
            }
        }
        return false;
    }

    public static Collection> internalComponents(Class model) {
        Collection> comps = new ArrayList>();
        comps.add(model);
        internalComponents0(comps, model);
        return comps;
    }

    public static void internalComponents0(Collection> comps, Class model) {
        for (Field f : model.getDeclaredFields()) {
            f.setAccessible(true);
            Class fc = f.getType();
            if (!fc.isPrimitive() && !fc.getName().startsWith("java.") && isComponentClass(fc)) {
                if (!comps.contains(fc)) {
                    comps.add(fc);
                    internalComponents0(comps, fc);
                }
            }
        }
    }

    public static void explore(Object comp) {
        explore(comp, System.out);
    }

    public static void explore(Object comp, PrintStream w) {
        Field[] fi = comp.getClass().getDeclaredFields();
        for (Field f : fi) {
            Role r = f.getAnnotation(Role.class);
            if (Annotations.plays(r, Role.PARAMETER)) {
                w.println("    field2in(model, \"" + f.getName() + "\", comp, \"" + f.getName() + "\");");
            } else if (Annotations.isInOut(f)) {
                w.println("    field2inout(hru, \"" + f.getName() + "\", comp, \"" + f.getName() + "\");");
            } else if (Annotations.isIn(f)) {
                w.println("    field2in(hru, \"" + f.getName() + "\", comp, \"" + f.getName() + "\");");
            } else if (Annotations.isOut(f)) {
                w.println("    out2field(comp, \"" + f.getName() + "\", hru, \"" + f.getName() + "\");");
            }
        }
    }

    /**
     * Figure out connectivity and generate Java statements.
     * @param comps
     */
    public static void figureOutConnect(PrintStream w, Object... comps) {
        // add all the components via Proxy.
        List l = new ArrayList();
        for (Object c : comps) {
            l.add(new ComponentAccess(c));
        }

        // find all out slots
        for (ComponentAccess cp_out : l) {
            w.println("// connect " + objName(cp_out));
            // over all input slots.
            for (Access fout : cp_out.outputs()) {
                String s = "   out2in(" + objName(cp_out) + ", \"" + fout.getField().getName() + "\"";
                for (ComponentAccess cp_in : l) {
                    // skip if it is the same component.
                    if (cp_in == cp_out) {
                        continue;
                    }
                    // out points to in
                    for (Access fin : cp_in.inputs()) {
                        // name equivalence enought for now.
                        if (fout.getField().getName().equals(fin.getField().getName())) {
                            s = s + ", " + objName(cp_in);
                        }
                    }
                }
                w.println(s + ");");
            }
            w.println();
        }
    }

    public static void figureOutParamDeclarations(PrintStream w, Object... comps) {

        Map m = new HashMap();

        for (Object c : comps) {
            ComponentAccess cp = new ComponentAccess(c);
//            System.out.println("// Parameter from " + objName(cp));
            // over all input slots.
            for (Access fin : cp.inputs()) {
                Role role = fin.getField().getAnnotation(Role.class);
                if (role != null && Annotations.plays(role, Role.PARAMETER)) {
                    // make sure parameter is only there once.
                    m.put(fin.getField().getName(), fin);
                }
            }
        }

        List sl = new ArrayList(m.keySet());
        Collections.sort(sl, new Comparator() {

            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        for (String key : sl) {
            Access fin = m.get(key);
            Description d = fin.getField().getAnnotation(Description.class);
            if (d != null) {
                w.println("   @Description(\"" + d.value() + "\")");
            }
            Bound b = fin.getField().getAnnotation(Bound.class);
            if (b != null) {
                w.println("   @Bound(\"" + b.value() + "\")");
            }
            w.println("   @Role(\"" + fin.getField().getAnnotation(Role.class).value() + "\")");
            w.println("   @In public " + fin.getField().getType().getSimpleName() + " " + fin.getField().getName() + ";");
            w.println();
        }
    }

    public static void declare(PrintStream w, Object... comps) {
        w.println("// Declarartions");
        for (Object c : comps) {
            ComponentAccess cp = new ComponentAccess(c);
            w.println("    " + c.getClass().getName() + " " + objName(cp) + " = new " + c.getClass().getName() + "();");
        }
        w.println();
    }

    public static void figureOutMapIn(PrintStream w, Object... comps) {
        for (Object c : comps) {
            ComponentAccess cp = new ComponentAccess(c);
            w.println("// Input mapping to " + objName(cp));
            for (Access fin : cp.inputs()) {
                Role role = fin.getField().getAnnotation(Role.class);
                if (role != null && Annotations.plays(role, Role.PARAMETER)) {
                    w.println("   in2in(\"" + fin.getField().getName() + "\", " + objName(cp) + ");");
                }
            }
            w.println();
        }
    }

    public static void figureOutMapIn0(PrintStream w, Object... comps) {
        Map> maps = new HashMap>();

        for (Object c : comps) {
            ComponentAccess cp = new ComponentAccess(c);
            for (Access fin : cp.inputs()) {
                Role role = fin.getField().getAnnotation(Role.class);
                if (role != null && Annotations.plays(role, Role.PARAMETER)) {
                    List l = maps.get(fin.getField().getName());
                    if (l == null) {
                        maps.put(fin.getField().getName(), l = new ArrayList());
                    }
                    l.add(objName(cp));
                }
            }
        }

        List sl = new ArrayList(maps.keySet());
        Collections.sort(sl, new Comparator() {

            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });

        for (String string : sl) {
            w.print("     in2in(\"" + string + "\"");
            List l = maps.get(string);
            for (String string1 : l) {
                w.print(", " + string1);
            }
            w.println(");");
        }
    }

    static private String objName(ComponentAccess cp) {
        return cp.getComponent().getClass().getSimpleName().toLowerCase();
    }



    public static List> getComponentClasses(File jar) throws IOException {
        return getComponentClasses(jar.toURI().toURL());
    }

    /** Get all components from a jar file
     *
     * @param jar
     * @return the list of components from the jar. (Implement 'Execute' annotation)
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static List> getComponentClasses(URL jar) throws IOException {
        JarInputStream jarFile = new JarInputStream(jar.openStream());
        URLClassLoader cl = new URLClassLoader(new URL[]{jar}, Thread.currentThread().getContextClassLoader());
        List> idx = new ArrayList>();

        JarEntry jarEntry = jarFile.getNextJarEntry();
        while (jarEntry != null) {
            String classname = jarEntry.getName();
//            System.out.println(classname);
            if (classname.endsWith(".class")) {
                classname = classname.substring(0, classname.indexOf(".class")).replace('/', '.');
                try {
                    Class c = Class.forName(classname, false, cl);
                    for (Method method : c.getMethods()) {
                        if ((method.getAnnotation(Execute.class)) != null) {
                            idx.add(c);
                            break;
                        }
                    }
                } catch (ClassNotFoundException ex) {
                    ex.printStackTrace();
                }
            }
            jarEntry = jarFile.getNextJarEntry();
        }
        jarFile.close();
        return idx;
    }

    /**
     * Get all components from a set of jar files.
     * 
     * @param parent a parent {@link ClassLoader} to use. If null, the context 
     *              classloader will be used.
     * @param jars the {@link URL}s of the jar to browse for components.
     * @return the list of component classes in the jars.
     * @throws IOException
     */
    public static List> getComponentClasses( ClassLoader parent, URL... jars ) throws IOException {
        if (parent == null) {
            parent = Thread.currentThread().getContextClassLoader();
        }
        
        URLClassLoader cl = new URLClassLoader(jars, parent);
        List> idx = new ArrayList>();

        for( URL jar : jars ) {
            JarInputStream jarFile = new JarInputStream(jar.openStream());
            JarEntry jarEntry = jarFile.getNextJarEntry();
            while( jarEntry != null ) {
                String classname = jarEntry.getName();
                // System.out.println(classname);
                if (classname.endsWith(".class")) {
                    classname = classname.substring(0, classname.indexOf(".class")).replace('/', '.');
                    try {
                        Class< ? > c = Class.forName(classname, false, cl);
                        for( Method method : c.getMethods() ) {
                            if ((method.getAnnotation(Execute.class)) != null) {
                                idx.add(c);
                                break;
                            }
                        }
                    } catch (ClassNotFoundException ex) {
                        ex.printStackTrace();
                    }
                }
                jarEntry = jarFile.getNextJarEntry();
            }
            jarFile.close();
        }

        return idx;
    }
    
    /** Get the documentation with the default locale
     *
     * @param comp The component to get the documentation from.
     * @return the documentation URL or null if not available
     */
    public static URL getDocumentation(Class comp) {
        return getDocumentation(comp, Locale.getDefault());
    }

    /** Get the documentation as URL reference;
     *
     * @param comp The class to get the 'Documentation' tag from
     * @param loc  The locale
     * @return the URL of the documentation file, null if no documentation is available.
     */
    public static URL getDocumentation(Class comp, Locale loc) {
        Documentation doc = (Documentation) comp.getAnnotation(Documentation.class);
        if (doc != null) {
            String v = doc.value();
            try {
                // try full URL first (external reference)
                URL url = new URL(v);
                return url;
            } catch (MalformedURLException E) {
                // local resource bundled with the class
                String name = v.substring(0, v.lastIndexOf('.'));
                String ext = v.substring(v.lastIndexOf('.'));
                String lang = loc.getLanguage();

                URL f = comp.getResource(name + "_" + lang + ext);
                if (f != null) {
                    return f;
                }

                f = comp.getResource(v);
                if (f != null) {
                    return f;
                }
            }
        }
        return null;
    }

    public static String getDescription(Class comp) {
        return getDescription(comp, Locale.getDefault());
    }

    /** Get the Component Description
     *
     * @param comp the component class
     * @param loc the locale
     * @return the localized description
     */
    public static String getDescription(Class comp, Locale loc) {
        Description descr = (Description) comp.getAnnotation(Description.class);
        if (descr != null) {
            String lang = loc.getLanguage();
            Method[] m = descr.getClass().getMethods();
            for (Method method : m) {
//                System.out.println(method);
                if (method.getName().equals(lang)) {
                    try {
                        String d = (String) method.invoke(descr, (Object[]) null);
                        if (d != null && !d.isEmpty()) {
                            return d;
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }
            return descr.value();
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        double start = System.currentTimeMillis();
        System.out.println(getComponentClasses(new File("/od/projects/oms3.prj.prms2008/dist/oms3.prj.prms2008.jar")));
        double end = System.currentTimeMillis();
        System.out.println("time " + (end - start));

        List> comps = getComponentClasses(new File("/od/projects/oms3.prj.prms2008/dist/oms3.prj.prms2008.jar"));

        Class basin = null;
        for (Class c : comps) {
            if (c.getName().equals("prms2008.Basin")) {
                basin = c;
                break;
            }
        }

        System.out.println(getDocumentation(basin, Locale.getDefault()));

        System.out.println(getDescription(basin, Locale.getDefault()));

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy