org.kepler.ddp.Utilities.java Source code

Java tutorial

Introduction

Here is the source code for org.kepler.ddp.Utilities.java

Source

/*
 * Copyright (c) 2012 The Regents of the University of California.
 * All rights reserved.
 *
 * '$Author: crawl $'
 * '$Date: 2015-11-23 12:26:17 -0800 (Mon, 23 Nov 2015) $' 
 * '$Revision: 34244 $'
 * 
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the above
 * copyright notice and the following two paragraphs appear in all copies
 * of this software.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 * ENHANCEMENTS, OR MODIFICATIONS.
 *
 */

package org.kepler.ddp;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kepler.configuration.ConfigurationManager;
import org.kepler.configuration.ConfigurationProperty;
import org.kepler.ddp.actor.pattern.stub.StubBaseActor;
import org.kepler.ddp.director.DDPEngine;
import org.kepler.provenance.ProvenanceRecorder;
import org.kepler.reporting.ReportingListener;

import au.edu.jcu.kepler.hydrant.DisplayRedirectFilter;
import ptolemy.actor.CompositeActor;
import ptolemy.actor.Director;
import ptolemy.actor.ExecutionListener;
import ptolemy.actor.IORelation;
import ptolemy.actor.Manager;
import ptolemy.actor.TypedIOPort;
import ptolemy.actor.injection.ActorModuleInitializer;
import ptolemy.actor.injection.ActorModuleInitializer.Initializer;
import ptolemy.actor.injection.PtolemyInjector;
import ptolemy.actor.injection.PtolemyModule;
import ptolemy.data.DoubleToken;
import ptolemy.data.IntToken;
import ptolemy.data.LongToken;
import ptolemy.data.RecordToken;
import ptolemy.data.StringToken;
import ptolemy.data.Token;
import ptolemy.data.type.BaseType;
import ptolemy.data.type.RecordType;
import ptolemy.data.type.Type;
import ptolemy.domains.ddf.kernel.DDFDirector;
import ptolemy.domains.sdf.kernel.SDFDirector;
import ptolemy.kernel.util.Attribute;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.Nameable;
import ptolemy.kernel.util.Workspace;
import ptolemy.moml.MoMLParser;
import ptolemy.moml.filter.BackwardCompatibility;
import ptolemy.moml.filter.RemoveGraphicalClasses;

/** A collection of utilities for DDP classes. The methods and fields in this
 *  class are not specific to a DDP engine.
 * 
 * @author Daniel Crawl and Jianwu Wang
 * @version $Id: Utilities.java 34244 2015-11-23 20:26:17Z crawl $
 * 
 */

public class Utilities {

    /** Check the director and its iterations with the runWorkflowLifecyclePerInput value.
     *  If the director is SDF, this method changes the iterations based on the
     *  value in runWorkflowLifecyclePerInput. If the director is DDF, then
     *  runWorkflowLifecyclePerInput is changed to true.
     *  @param model the model to execute in the stub.
     *  @param  runWorkflowLifecyclePerInput if true, the full lifecycle of the
     *  model will be executed for each input. If false, only one iteration of the
     *  model will be execute for each input.
     *  @return the (possibly changed) runWorkflowLifecyclePerInput value.
     */
    public static boolean checkDirectorIterations(CompositeActor model, boolean runWorkflowLifecyclePerInput) {

        Director director = model.getDirector();
        if (director instanceof SDFDirector) {
            Token iterations;
            // change the iterations based on runWorkflowLifecyclePerInput
            if (runWorkflowLifecyclePerInput) {
                iterations = IntToken.ONE;
            } else {
                iterations = SDFDirector.UNBOUNDED_INTTOKEN;
            }
            try {
                ((SDFDirector) director).iterations.setToken(iterations);
            } catch (IllegalActionException e) {
                throw new RuntimeException("Error changing iterations for SDF director: " + e.getMessage());
            }
        } else if ((director instanceof DDFDirector) && !runWorkflowLifecyclePerInput) {
            runWorkflowLifecyclePerInput = true;
            String message = "Sub-workflow " + model.getName()
                    + " uses DDF director, but runWorkflowLifecyclePerInput is false;"
                    + " this is not supported so changing runWorkflowLifecyclePerInput to true.";
            System.out.println("WARNING: " + message);
            LOG.warn(message);
        } else {
            String message = "Unexpected director in sub-workflow " + model.getName() + ": "
                    + director.getClass().getName() + ". The sub-workflow may not execute correctly.";
            System.out.println("WARNING: " + message);
            LOG.warn(message);
        }

        return runWorkflowLifecyclePerInput;
    }

    /** Create a Manager for a model and optionally start execution.
     *  @param model the workflow
     *  @param listener an ExecutionListener to register with the Manager to
     *  receive error messages.
     *  @param stubSource the source actor in the model
     *  @param stubSink the sink actor in the model
     *  @param  runWorkflowLifecyclePerInput if true, execute the full lifecycle of the
     *  model for each input and the stub must tell the manager to execute the
     *  model. If false, this method starts execution.
     *  @param enablePrintTimeAndMemory if true, print an execution summary each time
     *  the model executes.  
     */
    public static Manager createManagerForModel(CompositeActor model, ExecutionListener listener,
            StubBaseActor stubSource, StubBaseActor stubSink, boolean runWorkflowLifecyclePerInput,
            boolean enablePrintTimeAndMemory) {

        Manager manager = null;

        // create manager and add model
        try {
            manager = new Manager(model.workspace(), "Manager");
        } catch (IllegalActionException e) {
            throw new RuntimeException("Error creating Manager: " + e.getMessage());
        }

        try {
            model.setManager(manager);
        } catch (IllegalActionException e) {
            throw new RuntimeException("Error setting Manager for sub-workflow: " + e.getMessage());
        }

        manager.enablePrintTimeAndMemory(enablePrintTimeAndMemory);
        manager.addExecutionListener(listener);

        if (runWorkflowLifecyclePerInput) {
            stubSource.setRunWorkflowLifecyclePerInput(runWorkflowLifecyclePerInput);
            stubSink.setRunWorkflowLifecyclePerInput(runWorkflowLifecyclePerInput);
        } else {
            try {
                manager.startRun();
            } catch (Exception e) {
                throw new RuntimeException("Error starting sub-workflow.", e);
            }
        }

        return manager;
    }

    /** Load the model for a stub from a Nephele Configuration. The 
     *  top-level ports and connected relations are removed.
     */
    public static synchronized CompositeActor getModel(String modelName, String modelString, String modelFile,
            boolean sameJVM, String redirectDir) {

        CompositeActor model = null;

        if (modelName == null) {
            throw new RuntimeException("Subworkflow name was not set in configuration.");
        }

        if (sameJVM) {

            CompositeActor originalModel = DDPEngine.getModel(modelName);
            try {
                model = (CompositeActor) originalModel.clone(new Workspace());
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException("Error cloning subworkflow: " + e.getMessage());
            }

            Utilities.removeModelPorts(model);

            // create an effigy for the model so that gui actors can open windows.
            DDPEngine.createEffigy(model);

        } else {

            List<?> filters = MoMLParser.getMoMLFilters();

            Workspace workspace = new Workspace();
            final MoMLParser parser = new MoMLParser(workspace);

            //parser.resetAll();

            MoMLParser.setMoMLFilters(null);
            MoMLParser.setMoMLFilters(BackwardCompatibility.allFilters(), workspace);

            if (redirectDir.isEmpty()) {
                MoMLParser.addMoMLFilter(new RemoveGraphicalClasses(), workspace);
            } else {
                //redirect display-related actors 
                final String pid = ManagementFactory.getRuntimeMXBean().getName();
                final String threadId = String.valueOf(Thread.currentThread().getId());
                final String displayPath = redirectDir + File.separator + pid + "_" + threadId;
                MoMLParser.addMoMLFilter(new DisplayRedirectFilter(displayPath), workspace);
                final ArrayList<PtolemyModule> actorModules = new ArrayList<PtolemyModule>();
                actorModules.add(new PtolemyModule(ResourceBundle.getBundle("org/kepler/ActorModuleBatch")));
                Initializer _defaultInitializer = new Initializer() {
                    @Override
                    public void initialize() {
                        PtolemyInjector.createInjector(actorModules);
                    }
                };
                ActorModuleInitializer.setInitializer(_defaultInitializer);
            }

            // get the model from the configuration

            // see if model is in the configuration.
            if (modelString != null) {

                try {
                    model = (CompositeActor) parser.parse(modelString);
                } catch (Exception e) {
                    throw new RuntimeException("Error parsing model " + modelName + ": " + e.getMessage());
                }

                //LOG.info("parsed model from " + modelString);

            } else {

                // the model was saved as a file.

                if (modelFile == null) {
                    throw new RuntimeException("No model for " + modelName + " in configuration.");
                }

                // load the model
                try {
                    model = (CompositeActor) parser.parseFile(modelFile);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(
                            "Error parsing model " + modelName + " in file " + modelFile + ": " + e.getMessage());
                }

                LOG.info("parsed model from " + modelFile);
            }

            // restore the moml filters
            MoMLParser.setMoMLFilters(null);
            MoMLParser.setMoMLFilters(filters);

            // remove provenance recorder and reporting listener
            final List<Attribute> toRemove = new LinkedList<Attribute>(
                    model.attributeList(ProvenanceRecorder.class));
            toRemove.addAll(model.attributeList(ReportingListener.class));
            for (Attribute attribute : toRemove) {
                try {
                    attribute.setContainer(null);
                } catch (Exception e) {
                    throw new RuntimeException("Error removing " + attribute.getName() + ": " + e.getMessage());
                }
            }

        }

        return model;
    }

    /** Remove top-level ports and relations from a composite actor. */
    public static void removeModelPorts(CompositeActor model) {

        // get a copy of the list since we modify the original when ports
        // are removed.
        final List<?> ports = new LinkedList<Object>(model.portList());
        for (Object object : ports) {
            final TypedIOPort port = (TypedIOPort) object;
            //final String name = port.getName();

            //LOG.info("going to replace port " + name + " in model.");

            // NOTE: do not remove ports connected to the top-level ports, since
            // their types are used to the the input/output types of the stub.
            /*
            final List<?> connectedPorts = new LinkedList<Object>(port.insidePortList());
            for(Object obj : connectedPorts) {
            try {
                ((IOPort)obj).setContainer(null);
            } catch (Exception e) {
                throw new RuntimeException("Error removing port " +
                    ((IOPort)obj).getFullName() + " from model: " +
                    e.getMessage());
            }
            }
            */

            /*
            // print types of connected ports
            final List<?> connectedPorts = new LinkedList<Object>(port.insidePortList());
            for(Object obj : connectedPorts) {
            LOG.info("type for " + obj + " is " + ((TypedIOPort)obj).getType());
            } 
            */

            // remove relations
            final List<?> connectedRelations = new LinkedList<Object>(port.insideRelationList());
            for (Object obj : connectedRelations) {
                try {
                    ((IORelation) obj).setContainer(null);
                } catch (Exception e) {
                    throw new RuntimeException("Error removing relation " + "from model: " + e.getMessage());
                }
            }

            // remove the top-level port
            try {
                port.setContainer(null);
            } catch (Exception e) {
                throw new RuntimeException(
                        "Error removing port " + port.getFullName() + " from model: " + e.getMessage());
            }
        }

    }

    /** Create a Token from a string based on the Ptolemy Type. */
    public static Token createTokenFromString(String tokenStr, Type type) {
        try {
            if (type == BaseType.STRING) {
                return new StringToken(tokenStr);
            } else if (type == BaseType.INT) {
                return new IntToken(tokenStr);
            } else if (type == BaseType.DOUBLE) {
                return new DoubleToken(tokenStr);
            } else if (type == BaseType.LONG) {
                return new LongToken(tokenStr);
            } else if (type == BaseType.NIL) {
                return Token.NIL;
            } else if (type instanceof RecordType) {
                return new RecordToken(tokenStr);
            } else {
                throw new RuntimeException("Unknown type of token: " + type);
            }
        } catch (IllegalActionException e) {
            throw new RuntimeException("Error creating token.", e);
        }
    }

    /** Create a Token from a string based on the TokenType enum. */
    public static Token createTokenFromString(String tokenStr, TokenType type) {

        try {
            switch (type) {
            case String:
                return new StringToken(tokenStr);
            case Int:
                return new IntToken(tokenStr);
            case Double:
                return new DoubleToken(tokenStr);
            case Long:
                return new LongToken(tokenStr);
            case Nil:
                return Token.NIL;
            case Record:
                return new RecordToken(tokenStr);
            default:
                throw new RuntimeException("Unknown type of token: " + type);
            }
        } catch (IllegalActionException e) {
            throw new RuntimeException("Error creating token.", e);
        }
    }

    /** Get the TokenType for a token. */
    public static TokenType getTokenTypeForSerialization(Token token) {

        Type type = token.getType();

        if (type == BaseType.STRING) {
            return TokenType.String;
        } else if (type == BaseType.INT) {
            return TokenType.Int;
        } else if (type == BaseType.DOUBLE) {
            return TokenType.Double;
        } else if (type == BaseType.LONG) {
            return TokenType.Long;
        } else if (type == BaseType.NIL) {
            return TokenType.Nil;
        } else if (type instanceof RecordType) {
            return TokenType.Record;
        } else {
            throw new RuntimeException("Serialization of Ptolemy type " + type.toString() + " is unsupported.");
        }

    }

    /** Get the ConfigurationProperty for an Engine on the configuration file.
     *  @param engineName The name of the ddp engine
     *  @param source The source object calling this method
     *  @return If found, returns the ConfigurationProperty. If not found,
     *  throws an exception.
     */
    public static ConfigurationProperty getEngineProperty(String engineName, Nameable source)
            throws IllegalActionException {

        List<ConfigurationProperty> engineProperties = ConfigurationManager.getInstance()
                .getProperty(ConfigurationManager.getModule("ddp-common")).getProperties("Engines.Engine");

        if (engineProperties == null || engineProperties.isEmpty()) {
            throw new IllegalActionException(source, "No DDP engines found.");
        }

        for (ConfigurationProperty engineProperty : engineProperties) {
            ConfigurationProperty nameProperty = engineProperty.getProperty("Name");
            if (nameProperty == null) {
                throw new IllegalActionException(source,
                        "DDP Engine does not have a name. Try deleting\n"
                                + "$HOME/KeplerData/modules/ddp-common/configuration/configuration.xml\n"
                                + "and restarting Kepler.");
            }

            if (nameProperty.getValue().equalsIgnoreCase(engineName)) {
                return engineProperty;
            }
        }

        // not found
        throw new IllegalActionException(source, "No " + engineName + " Engine on configuration file.");
    }

    /** Get a list of available execution language names. */
    public static String[] getExecutionLanguageNames() throws IllegalActionException {

        List<String> names = new ArrayList<String>();

        final List<ConfigurationProperty> languageList = ConfigurationManager.getInstance()
                .getProperty(ConfigurationManager.getModule("ddp-common"))
                .getProperties("ExecutionLanguages.Language");

        for (ConfigurationProperty property : languageList) {
            ConfigurationProperty nameProperty = property.getProperty("Name");
            if (nameProperty == null) {
                throw new IllegalActionException("Missing name for execution language in configuration file.");
            }
            names.add(nameProperty.getValue());
        }

        String[] array = names.toArray(new String[names.size()]);
        Arrays.sort(array);
        return array;
    }

    /** Get the jars for a language. Returns an empty list if there are non jars. */
    public static List<String> getJarsForLanguage(String languageName) throws IllegalActionException {

        final List<ConfigurationProperty> languageList = ConfigurationManager.getInstance()
                .getProperty(ConfigurationManager.getModule("ddp-common"))
                .getProperties("ExecutionLanguages.Language");

        for (ConfigurationProperty property : languageList) {
            ConfigurationProperty nameProperty = property.getProperty("Name");
            if (nameProperty == null) {
                throw new IllegalActionException("Missing name for execution language in configuration file.");
            }
            if (nameProperty.getValue().equals(languageName)) {
                ConfigurationProperty jarsProperty = property.getProperty("Jars");
                if (jarsProperty != null) {
                    String jarsStr = jarsProperty.getValue();
                    if (jarsStr != null) {
                        String[] jars = jarsStr.split(",");
                        return Arrays.asList(jars);
                    }
                }
            }
        }

        return new LinkedList<String>();

    }

    /** Get the script engine name for a language. Returns null if the language
     *  is not found in the configuration, or is not supported by a script engine.
     */
    public static String getScriptEngineName(String languageName) throws IllegalActionException {

        final List<ConfigurationProperty> languageList = ConfigurationManager.getInstance()
                .getProperty(ConfigurationManager.getModule("ddp-common"))
                .getProperties("ExecutionLanguages.Language");

        for (ConfigurationProperty property : languageList) {
            ConfigurationProperty nameProperty = property.getProperty("Name");
            if (nameProperty == null) {
                throw new IllegalActionException("Missing name for execution language in configuration file.");
            }
            if (nameProperty.getValue().equals(languageName)) {
                ConfigurationProperty typeProperty = property.getProperty("Type");
                if (typeProperty == null) {
                    throw new IllegalActionException(
                            "Missing type for execution language " + languageName + " in configuration file.");
                }
                if (typeProperty.getValue().equals("ScriptEngine")) {
                    ConfigurationProperty scriptEngineNameProperty = property.getProperty("ScriptEngineName");
                    if (scriptEngineNameProperty == null) {
                        throw new IllegalActionException("Missing script engine name for execution language "
                                + languageName + " in configuration file.");
                    }
                    return scriptEngineNameProperty.getValue();
                }
            }
        }
        // not found
        return null;
    }

    /** Get the script engine factory name for a language. Returns null if the language
     *  is not found in the configuration, or is not supported by a script engine.
     */
    public static String getScriptEngineFactoryName(String languageName) throws IllegalActionException {

        final List<ConfigurationProperty> languageList = ConfigurationManager.getInstance()
                .getProperty(ConfigurationManager.getModule("ddp-common"))
                .getProperties("ExecutionLanguages.Language");

        for (ConfigurationProperty property : languageList) {
            ConfigurationProperty nameProperty = property.getProperty("Name");
            if (nameProperty == null) {
                throw new IllegalActionException("Missing name for execution language in configuration file.");
            }
            if (nameProperty.getValue().equals(languageName)) {
                ConfigurationProperty typeProperty = property.getProperty("Type");
                if (typeProperty == null) {
                    throw new IllegalActionException(
                            "Missing type for execution language " + languageName + " in configuration file.");
                }
                if (typeProperty.getValue().equals("ScriptEngine")) {
                    ConfigurationProperty scriptEngineFactoryNameProperty = property
                            .getProperty("ScriptEngineFactoryName");
                    if (scriptEngineFactoryNameProperty == null) {
                        throw new IllegalActionException(
                                "Missing script engine factory name for execution language " + languageName
                                        + " in configuration file.");
                    }
                    return scriptEngineFactoryNameProperty.getValue();
                }
            }
        }
        // not found
        return null;
    }

    /** Returns true if an environment variable is set when
     *  executing under a resource manager such as PBS or SLURM.
     */
    public static boolean isExecutingUnderResourceManager() {
        // check PBS
        return System.getenv("PBS_JOBID") != null ||
        // check SGE
                System.getenv("PE_NODEFILE") != null ||
                // check SLURM
                System.getenv("SLURM_JOBID") != null;
    }

    public static final String CONFIGURATION_KEPLER_PARA_PREFIX = "KEPLER::parameter";

    public static final String CONFIGURATION_KEPLER_PRINT_EXE_INFO = CONFIGURATION_KEPLER_PARA_PREFIX
            + "::printExeSummary";

    public static final String CONFIGURATION_KEPLER_TAG = "KEPLER::tagging";

    public static final String CONFIGURATION_KEPLER_PARA_PARALLEL = "KEPLER::parameter::ParallelNumber";

    public static final String CONFIGURATION_KEPLER_DISTRIBUTED_CACHE_PATH = "KEPLER::distributedcache::path";

    public static final String CONFIGURATION_KEPLER_JOB_KEY_CLASS = "KEPLER::job::key::class";

    public static final String CONFIGURATION_KEPLER_JOB_VALUE_CLASS = "KEPLER::job::value::class";

    /** The name of the configuration parameter for the MoML of the sub-workflow. */
    public static final String CONFIGURATION_KEPLER_MODEL = "KEPLER::model";

    /** The name of the configuration parameter for the name of the sub-workflow. */
    public static final String CONFIGURATION_KEPLER_MODEL_NAME = "KEPLER::modelName";

    /** The name of the configuration parameter for the path of the sub-worflow MoML. */
    public static final String CONFIGURATION_KEPLER_MODEL_PATH = "KEPLER::modelPath";

    /** The name of the configuration parameter for the path of the Kepler installation. */
    public static final String CONFIGURATION_KEPLER_MODULES_DIR = "KEPLER::modulesDir";

    /** The name of the configuration parameter for the path to redirect display actors. */
    public static final String CONFIGURATION_KEPLER_REDIRECT_DIR = "KEPLER::redirectDir";

    /** The name of the configuration parameter to specify running in the same JVM as Kepler. */
    public static final String CONFIGURATION_KEPLER_SAME_JVM = "KEPLER::sameJVM";

    /** The name of the configuration parameter specifying the name of a DDPDataSource actor. */
    public static final String CONFIGURATION_KEPLER_SOURCE_ACTOR_NAME = "KEPLER::sourceActorName";

    /** The name of the configuration parameter specifying the name of a DDPDataSink actor. */
    public static final String CONFIGURATION_KEPLER_SINK_ACTOR_NAME = "KEPLER::sinkActorName";

    /** The name of the configuration parameter specifying the name of the input token. */
    public static final String CONFIGURATION_KEPLER_INPUT_TOKEN = "Kepler::inputToken";

    /** The name of the configuration parameter specifying if the full lifecycle of the
     *  sub-workflow should be executed for each input.
     */
    public static final String CONFIGURATION_KEPLER_RUN_WORKFLOW_LIFECYCLE_PER_INPUT = "Kepler::runWorkflowLifeCyclePerInput";

    /** The name of the configuration parameter specifying the code to execute in the stub. */
    public static final String CONFIGURATION_KEPLER_STUB_CODE = "Kepler::code";

    /** The name of the configuration parameter specifying the input key type of the stub. */
    public static final String CONFIGURATION_KEPLER_INPUT_KEY_TYPE = "Kepler::inputKeyType";

    /** The name of the configuration parameter specifying the input value type of the stub. */
    public static final String CONFIGURATION_KEPLER_INPUT_VALUE_TYPE = "Kepler::inputValueType";

    /** The name of the configuration parameter specifying the name of the script engine factory. */
    public static final String CONFIGURATION_KEPLER_SCRIPT_ENGINE_FACTORY_NAME = "Kepler::scriptEngineFactoryName";

    /** Enumeration of types of token that can be serialized to/from strings. */
    public enum TokenType {
        String, Int, Double, Long, Nil, Record;

        public static TokenType getInstance(int value) {
            // FIXME add error checking
            return values()[value];
        }

        public int getValue() {
            return ordinal();
        }
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private fields                    ////

    /** Logging. */
    private static final Log LOG = LogFactory.getLog(Utilities.class);

}