/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Markus Kraetzig

 This library is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as
 published by the Free Software Foundation; either version 2.1 of the
 License, or (at your option) any later version.

 This library 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 library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA
 */

package com.jstatcom.engine;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.jstatcom.engine.gauss.GaussEngineType;
import com.jstatcom.engine.grte.GRTEType;
import com.jstatcom.engine.matlab.MatlabEngineType;
import com.jstatcom.engine.mlab.StubMlabEngineType;
import com.jstatcom.engine.ox.OxEngineType;
import com.jstatcom.engine.stub.StubEngineType;
import com.jstatcom.model.JSCConstants;

/**
 * This class is a Mediator  that binds the various classes and resources
 * together that belong to an engine implementation. It also contains an
 * enumeration of engine types that are implemented for convenience.
 * 

* Every Engine implementation define its corresponding concrete * engine type. The name of an engine type must be unique. If it already exists * for a different instance of EngineTypes, the constructor will * throw an exception. *

* Engine types should always be implemented as Singletons. *

* The name of an engine type also defines the resource directory to be used for * everything related to that engine. Therefore the conventions for variable * names defined in com.jstatcom.model.JSCConstants are enforced * for engine type names as well. *

* This class implements the typesave enum pattern (Joshua Bloch, * "Effective Java", Item 21) . If you compare EngineTypes, * always use the == operator. * * @author Markus Kraetzig */ public abstract class EngineTypes { private static final Map typeMap = new HashMap(); /** * The name of this runtype. */ public final String name; public final String DIR_NAME; private final String cfgFile; private AbstractConfigPanel configPanel = null; private static final String cfg_filename = "engine_config.xml"; /** * Reference to the GAUSS engine type. This used to manage communication * with the GAUSS software by Aptech. The software has to be installed on * the machine. */ public static final EngineTypes GAUSS = GaussEngineType.INSTANCE; /** * Reference to the Gauss Runtime Engine type. This can be used to execute * GAUSS code that has been compiled with the matching Gauss Engine. */ public static final EngineTypes GRTE = GRTEType.INSTANCE; /** * Reference to the Stub Engine type. This can be used to execute methods in * arbitrary system libraries without the need for a distinguished JNI * wrapper. */ public static final EngineTypes STUB = StubEngineType.INSTANCE; /** * Reference to the newer Matlab Engine type. This can be used to execute * methods in system libraries that have been generated from Matlab .m files * with Matlab Compiler versions release 4 and later. */ public static final EngineTypes MATLAB = MatlabEngineType.INSTANCE; /** * Reference to the older Matlab Engine type. This can be used to execute * methods in system libraries that have been generated from Matlab .m files * with Matlab Compiler versions prior to release 4. */ public static final EngineTypes MLAB = StubMlabEngineType.INSTANCE; /** * Reference to the Ox Engine type. This can be used to execute methods in * .ox or .oxo modules. */ public static final EngineTypes OX = OxEngineType.INSTANCE; private static List loadedEngines = new ArrayList(); /** * Creates an engine type with name. * * @param name * the unique name of this type * @throws IllegalArgumentException * if (name == null) or if name is * not valid according to JSCConstants * @throws IllegalStateException * if another engine type with name already * exists * * @see com.jstatcom.model.JSCConstants#isValidName */ protected EngineTypes(String name) { if (name == null) throw new IllegalArgumentException("Argument was null."); JSCConstants.checkNameThrowEx(name); this.name = name; this.DIR_NAME = "j" + name.toLowerCase(); this.cfgFile = DIR_NAME + "/" + cfg_filename; if (valueOf(name) != null) throw new IllegalStateException("Engine type \"" + name + "\" already exists."); typeMap.put(name.toUpperCase(), this); } /** * Checks all configuration data for validity. This method performs a * general check that should be true for all engines: *

* One can add further tests by overriding the method: *

* * public String checkSettings() * *

* It is called from this method after all other checks succeeded and can be * used to validate conditions between engine settings. * * @param configHolder * the config settings to check * @return null if ok, error string otherwise * @throws IllegalArgumentException * if (configHolder == null) */ public final String checkConfig(ConfigHolder configHolder) { if (configHolder == null) throw new IllegalArgumentException("Argument was null."); // Check whether all necessary keys are there. Set keySet = configHolder.getConfigKeys(); if (keySet == null) return null; if (!keySet.containsAll(getConfigKeys().values())) return "Some information is missing to run engine of type " + this + "."; // Check whether the self tests of all ConfigKeys are ok. for (Iterator iter = keySet.iterator(); iter.hasNext();) { ConfigKeys currentKey = (ConfigKeys) iter.next(); String value = configHolder.getConfig(currentKey); String error = currentKey.isValid(value); if (error != null) return error; } return checkSettings(configHolder); } /** * This method should be overwritten by clients, if further checks of the * settings have to be specified. * * @param configHolder * the config settings to check * @return null if ok, error string otherwise */ public abstract String checkSettings(ConfigHolder configHolder); /** * Override prevention method to enforce a.equals(b) if and * only if a==b. * * @param o * object to compare with * @return true if equal, false otherwise */ public final boolean equals(Object o) { return super.equals(o); } /** * Returns the config file location for the respective engine. The filename * is constructed as: *

* "j" + name.toLowerCase() + "/" + CONFIG_FILE; *

* If the directory "j" + name.toLowerCase() does not exist * yet in the resource path, it will be created by this method. *

* Subclasses can overwrite this method if this is not the desired * behaviour. * * @return the relative location of the XML config file to the resource * directory */ public String getConfigFile() { File dir = new File(DIR_NAME); if (!dir.isDirectory()) dir.mkdir(); return cfgFile; } /** * Gets a map with all config keys for that specific engine. *

* Example:
* Implementations of a Foo engine this class could use: *

* return ConfigKeys.getAllKeys(FooConfigKeys.class); *

* where Foo stands for the name of the engine and * FooConfigKeys is the engine specific implementation of * ConfigKeys. * * @return Map containing the ConfigKeys with * the respective names as keys */ public abstract Map getConfigKeys(); /** * Gets the configuration panel for the respective engine. This default * implementation creates an edit dialog for the XML file. It works for all * settings. This can be overwritten to provide a costumized settings * dialogs for a specific engine. * * @return the user panel containing the user input mask for configuration */ public AbstractConfigPanel getConfigPanel() { if (configPanel == null) configPanel = new DefaultConfigPanel(); return configPanel; } /** * Gets a concrete implementation of the Engine interface. * * @return engine that is initialized and ready to run */ public abstract Engine getEngine(); /** * Override prevention method invokes super method. * * @return hash code */ public final int hashCode() { return super.hashCode(); } /** * Returns a string that represents the value of this object. * * @return a string representation of this */ public final String toString() { return this.name; } /** * Gets the type for the given name. The case of name makes * no difference. * * @param name * the name of the type * @return reference to an instance of EngineTypes with * name or null if it does not exist * @throws IllegalArgumentException * if (name == null) */ public static EngineTypes valueOf(String name) { if (name == null) throw new IllegalArgumentException("Argument was null"); Object o = typeMap.get(name.toUpperCase()); if (o instanceof EngineTypes) return (EngineTypes) o; return null; } /** * Gets an iterator over all loaded engines. * * @return iterator */ public static Iterator engineIterator() { return loadedEngines.iterator(); } /** * Adds engine to the list of loaded engines if it was not * contained yet. * * @param engine * the instance to add * @throws IllegalArgumentException * if (engine == null) */ protected static void addLoadedEngine(Engine engine) { if (engine == null) throw new IllegalArgumentException("Argument was null"); if (!loadedEngines.contains(engine)) loadedEngines.add(engine); } }

Ads help maintain this website.