/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* Licensed 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 com.qualogy.qafe.core.datastore;
import java.util.logging.Logger;
import org.apache.commons.lang.StringUtils;
import com.qualogy.qafe.bind.commons.type.Parameter;
import com.qualogy.qafe.bind.commons.type.Reference;
import com.qualogy.qafe.bind.commons.type.Value;
import com.qualogy.qafe.bind.core.application.ApplicationContext;
import com.qualogy.qafe.bind.core.application.ApplicationIdentifier;
import com.qualogy.qafe.bind.core.messages.Bundle;
import com.qualogy.qafe.bind.core.messages.PlaceHolder;
import com.qualogy.qafe.core.application.ApplicationCluster;
import com.qualogy.qafe.core.i18n.LocaleResolver;
import com.qualogy.qafe.core.placeholder.PlaceHolderResolver;
import com.qualogy.qafe.core.script.Script;
import com.qualogy.qafe.core.script.ScriptBuilder;
import com.qualogy.qafe.core.script.ScriptEngineManager;
/**
* Helper class for retrieving data for a given key
* @author
*
*/
public class ParameterValueHandler {
public final static Logger logger = Logger.getLogger(ParameterValueHandler.class.getName());
public static Object get(ApplicationContext context, DataIdentifier dataId, Reference reference){
return get(context, null, dataId, reference);
}
public static Object get(ApplicationContext context, ApplicationStoreIdentifier storeId, DataIdentifier dataId, Reference reference){
return get( context,storeId, dataId, reference,null);
}
/**
* Method gets a value for given reference. This method uses the references source
* to retrieve the value from the assigned source. In case of storeId, when not null
* or source set to local store reference, localstore always goes first.
* @param context
* @param appStoreId
* @param dataId
* @param reference
* @return
*/
public static Object get(ApplicationContext context, ApplicationStoreIdentifier appStoreId, DataIdentifier dataId, Reference reference,String storeId){
if(context==null)
throw new IllegalArgumentException("context may not be null");
Object value = null;
if(reference != null){ //if ref is set try to retrieve a value
String ref = reference.stringValueOf();
if(ref.contains("[${")) {
String varName = ref.substring(ref.indexOf("{")+1, ref.lastIndexOf("}"));
Reference varRef = new Reference();
varRef.setRef(varName);
varRef.setSource(reference.getSource());
Object obj = get(context, appStoreId, dataId, varRef, storeId);
if(obj != null) {
ref = ref.replace("${"+varName+"}", obj.toString());
}
}
if(reference.isLocalStoreReference() || reference.isGlobalStoreReference()){
if(storeId == null) {
throw new IllegalArgumentException("store id cannot be null when using src=" + Reference.SOURCE_APP_LOCAL_STORE_ID);
}
value = getFromLocalStore(storeId, ref);
} else if (reference.isMessageReference()){ //message resource
String bundleId = (reference.hasRootRef())?reference.getRootRef():Bundle.DEFAULT_BUNDLE_ID;
value = context.getMessages()!=null ? context.getMessages().get(bundleId, reference.getRefWithoutRoot(), LocaleResolver.resolve(dataId)) : null;
} else if (reference.isDataStoreReference()){ //datastore value
value = DataStore.findValue(dataId, ref);
}
}
return value;
}
public static Object get(ApplicationContext context, DataIdentifier dataId, Parameter parameter){
return get(context, null, dataId, parameter);
}
public static Object get(ApplicationContext context, ApplicationStoreIdentifier storeId, DataIdentifier dataId, Parameter parameter){
return get( context, storeId,dataId, parameter,null);
}
/**
* Method to get a value based on an in. This method
* - first checks the ref (specified in the parameter), saying
* it'll check either system or datastore.
* - second it'll use the staticvalue of the object, or if the ref/ name ends up with a null
* value, the static(default)value (if set is used).
* - when no ref is set and no default value is supplied, null will be returned when nullable is true
* (otherwise an exception is thrown)
*
* NOTE: if ref or name is set that value will be retrieved, BUT
* if the result of retrieving the value is null and default value is set to overwrite,
* that value will be used!!!
*
* @param userDefinedId
* @param parameter
* @return
*/
public static Object get(ApplicationContext context, ApplicationStoreIdentifier storeId, DataIdentifier dataId, Parameter parameter,String localStoreId){
if (parameter == null) {
throw new IllegalArgumentException("parameter cannot be null");
}
Object value = null;
if (parameter.getExpression() != null) {
String expression = parameter.getExpression();
if (!StringUtils.isBlank(expression)) {
Script script = ScriptBuilder.build(context, storeId, dataId, expression, parameter, localStoreId);
value = ScriptEngineManager.getEngine(context).process(script);
}
} else {
Reference objectOfReference = parameter.getRef();
Value objectOfValue = parameter.getValue();
if (objectOfReference != null) {
// newlocalStoreId will be based on the objectOfReference, like placeholders, and not the passing in localStoreId
String newLocalStoreId = generateLocalStoreId(context, objectOfReference, localStoreId);
value = get(context,storeId, dataId, objectOfReference, newLocalStoreId);
if (value == null) {
if (objectOfReference.isComponentReference() || (parameter instanceof PlaceHolder)) {
// This is a fallback, all parameters with the reference (src="component") or placeholders
// are stored in the datastore using the name of the parameter
value = DataStore.findValue(dataId, parameter.getName());
}
}
} else if (objectOfValue != null) {
String staticValue = objectOfValue.getStaticValue();
if (staticValue != null) {
value = new String(staticValue);
}
} else {
// When the @ref is not specified explicitly, the default will be ref=@name and src="pipe"
// e.g. : <in name="myVar"/> <=> <in name="myVar" ref="myVar" src="pipe"/>
value = DataStore.findValue(dataId, parameter.getName());
}
value = PlaceHolderResolver.resolve(context, storeId, dataId, value, parameter, localStoreId);
}
return value;
}
/**
* This method uses internal method to get context based upon identifier
* @see get(ApplicationContext context, DataIdentifier dataId, Parameter parameter)
* @param applicationId
* @param dataId
* @param reference
* @return
*/
public static Object get(ApplicationIdentifier applicationId, DataIdentifier dataId, Reference reference){
return get(getContext(applicationId), dataId, reference);
}
/**
* @see ParameterValueHandler.get(ApplicationContext context, DataIdentifier dataId, Parameter parameter)
*/
public static Object get(ApplicationIdentifier applicationId, DataIdentifier dataId, Parameter parameter){
return get(getContext(applicationId), dataId, parameter);
}
/**
* This method uses internal method to get context based upon identifier
* @see get(ApplicationContext context, DataIdentifier dataId, Parameter parameter)
* @param applicationId
* @param dataId
* @param reference
* @return
*/
public static Object get(ApplicationIdentifier applicationId, ApplicationStoreIdentifier storeId, DataIdentifier dataId, Reference reference){
return get(getContext(applicationId), storeId, dataId, reference);
}
/**
* @see ParameterValueHandler.get(ApplicationContext context, DataIdentifier dataId, Parameter parameter)
*/
public static Object get(ApplicationIdentifier applicationId, ApplicationStoreIdentifier storeId, DataIdentifier dataId, Parameter parameter){
return get(getContext(applicationId), storeId, dataId, parameter);
}
/**
* Convinience method to store a parameter and value in the datastore.
* - if name is set it'll be used for storage
* - if name not set reference will be used
* - if both not set the value will be stored under null key (check datastore
* impl if possible)
* @param id
* @param parameter
* @param value
*/
public static void store(DataIdentifier id, Parameter parameter, Object value){
String key = null;
if(parameter.getName()!=null){
key = parameter.getName();
}else if(parameter.getRef()!=null && parameter.getRef().toString()!=null){
key = parameter.getRef().toString();
}
DataStore.store(id, key, value);
}
public static String generateLocalStoreId(ApplicationContext context, Reference reference, String localStoreId) {
if (localStoreId == null) {
return null;
}
if ((reference != null) && reference.isGlobalStoreReference()) {
// localStoreId contains <sessionId>.<contextId>|<windowId>
int indexOfObjectDelim = localStoreId.indexOf(ApplicationLocalStore.OBJECT_DELIMITER);
if (indexOfObjectDelim > -1) {
String sessionId = localStoreId.substring(0, indexOfObjectDelim);
localStoreId = generateLocalStoreId(sessionId, context, null);
}
}
return localStoreId;
}
public static String generateLocalStoreId(String sessionId, ApplicationContext context, String windowId) {
String localStoreId = sessionId + ApplicationLocalStore.OBJECT_DELIMITER + context.getId().stringValueOf();
if (windowId != null) {
localStoreId += ApplicationLocalStore.CONTEXT_DELIMITER + windowId;
}
return localStoreId;
}
private static ApplicationContext getContext(ApplicationIdentifier applicationId){
if(applicationId==null)
throw new IllegalArgumentException("appid may not be null");
return ApplicationCluster.getInstance().get(applicationId);
}
private static Object getFromLocalStore(String uuid, String key){
return ApplicationLocalStore.getInstance().retrieve(uuid, key);
}
}