blob: bb2074beb80d6ea321762905de63a4d3e85fb671 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.scxml2;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.scxml2.env.groovy.GroovyEvaluator;
import org.apache.commons.scxml2.env.javascript.JSEvaluator;
import org.apache.commons.scxml2.env.jexl.JexlEvaluator;
import org.apache.commons.scxml2.env.minimal.MinimalEvaluator;
import org.apache.commons.scxml2.model.ModelException;
import org.apache.commons.scxml2.model.SCXML;
import static org.apache.commons.scxml2.Evaluator.DEFAULT_DATA_MODEL;
/**
* A static singleton factory for {@link EvaluatorProvider}s by supported SCXML datamodel type.
* <p>
* The EvaluatorFactory is used to automatically create an {@link Evaluator} instance for an SCXML
* statemachine when none has been pre-defined and configured for the {@link SCXMLExecutor}.
* </p>
* <p>
* The builtin supported providers are:
* </p>
* <ul>
* <li>no or empty datamodel (default) or datamodel="jexl": {@link JexlEvaluator.JexlEvaluatorProvider}</li>
* <li>datamodel="ecmascript": {@link JSEvaluator.JSEvaluatorProvider}</li>
* <li>datamodel="groovy": {@link GroovyEvaluator.GroovyEvaluatorProvider}</li>
* <li>datamodel="null": {@link MinimalEvaluator.MinimalEvaluatorProvider}</li>
* </ul>
* <p>
* For adding additional or overriding the builtin Evaluator implementations use
* {@link #registerEvaluatorProvider(EvaluatorProvider)} or {@link #unregisterEvaluatorProvider(String)}.
* </p>
* <p>
* The default provider can be overridden using the {@link #setDefaultProvider(EvaluatorProvider)} which will
* register the provider under the {@link Evaluator#DEFAULT_DATA_MODEL} ("") value for the datamodel.<br>
* Note: this is <em>not</em> the same as datamodel="null"!
* </p>
*/
public class EvaluatorFactory {
private static EvaluatorFactory INSTANCE = new EvaluatorFactory();
private final Map<String, EvaluatorProvider> providers = new ConcurrentHashMap<>();
private EvaluatorFactory() {
providers.put(JSEvaluator.SUPPORTED_DATA_MODEL, new JSEvaluator.JSEvaluatorProvider());
providers.put(GroovyEvaluator.SUPPORTED_DATA_MODEL, new GroovyEvaluator.GroovyEvaluatorProvider());
providers.put(JexlEvaluator.SUPPORTED_DATA_MODEL, new JexlEvaluator.JexlEvaluatorProvider());
providers.put(MinimalEvaluator.SUPPORTED_DATA_MODEL, new MinimalEvaluator.MinimalEvaluatorProvider());
providers.put(DEFAULT_DATA_MODEL, providers.get(JexlEvaluator.SUPPORTED_DATA_MODEL));
}
public static void setDefaultProvider(EvaluatorProvider defaultProvider) {
INSTANCE.providers.put(DEFAULT_DATA_MODEL, defaultProvider);
}
@SuppressWarnings("unused")
public static EvaluatorProvider getDefaultProvider() {
return INSTANCE.providers.get(DEFAULT_DATA_MODEL);
}
@SuppressWarnings("unused")
public static EvaluatorProvider getEvaluatorProvider(String datamodelName) {
return INSTANCE.providers.get(datamodelName == null ? DEFAULT_DATA_MODEL : datamodelName);
}
@SuppressWarnings("unused")
public static void registerEvaluatorProvider(EvaluatorProvider provider) {
INSTANCE.providers.put(provider.getSupportedDatamodel(), provider);
}
@SuppressWarnings("unused")
public static void unregisterEvaluatorProvider(String datamodelName) {
INSTANCE.providers.remove(datamodelName == null ? DEFAULT_DATA_MODEL : datamodelName);
}
/**
* Returns a dedicated Evaluator instance for a specific SCXML document its documentmodel.
* <p>If no SCXML document is provided a default Evaluator will be returned.</p>
* @param document The document to return a dedicated Evaluator for. May be null to retrieve the default Evaluator.
* @return a new and not sharable Evaluator instance for the provided document, or a default Evaluator otherwise
* @throws ModelException If the SCXML document datamodel is not supported.
*/
public static Evaluator getEvaluator(SCXML document) throws ModelException {
String datamodelName = document != null ? document.getDatamodelName() : null;
EvaluatorProvider provider = INSTANCE.providers.get(datamodelName == null ? DEFAULT_DATA_MODEL : datamodelName);
if (provider == null) {
throw new ModelException("Unsupported SCXML document datamodel \""+(datamodelName)+"\"");
}
return document != null ? provider.getEvaluator(document) : provider.getEvaluator();
}
}