package org.jibeframework.core.app.config;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jibeframework.core.service.ConfigService;
import org.jibeframework.core.service.impl.ConfigFile;
import org.jibeframework.core.service.impl.ConfigParser;
import sun.org.mozilla.javascript.internal.NativeArray;
import sun.org.mozilla.javascript.internal.NativeObject;
/**
*
* @author dhalupa
*
*/
public class JavaScriptConfigParser implements ConfigParser {
private static final Log logger = LogFactory.getLog(JavaScriptConfigParser.class);
private ConfigService configService;
public void parseConfig(ConfigFile configFile) {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
String content = configFile.getContent();
engine.put("config", this);
try {
engine.eval(content);
} catch (ScriptException e) {
throw new IllegalStateException("There was an arror evaluating config script: " + configFile.getPath(), e);
}
}
/**
* This method is invoked from configuration file in order to inject config
* information
*/
public void add(Object o) {
ConfigElement ce = createConfigElement(convert(o));
configService.register(ce);
}
public void add(String id, Object o) {
ConfigElement ce = createConfigElement(convert(o));
ce.setId(id);
configService.register(ce);
}
public void add(String id, String condition, Object o) {
ConfigElement ce = createConfigElement(convert(o));
ce.setId(id);
ce.setCondition(condition);
configService.register(ce);
}
public void add(String id, String condition, boolean replace, Object o) {
ConfigElement ce = createConfigElement(convert(o));
ce.setId(id);
ce.setCondition(condition);
ce.setReplace(replace);
configService.register(ce);
}
/**
* Converts instance of NativeObject or NativeArray to standard java list
* and map
*
* @param o
* @return
*/
private Object convert(Object o) {
if (o instanceof NativeObject) {
return parseNativeObject((NativeObject) o);
} else if (o instanceof NativeArray) {
return parseNativeArray((NativeArray) o);
}
return o;
}
private Map<String, Object> parseNativeObject(NativeObject no) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Object[] propIds = NativeObject.getPropertyIds(no);
for (Object propId : propIds) {
String key = propId.toString();
map.put(key, convert(NativeObject.getProperty(no, key)));
}
return map;
}
private List<Object> parseNativeArray(NativeArray na) {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < na.getLength(); i++) {
list.add(convert(NativeArray.getProperty(na, i)));
}
return list;
}
@SuppressWarnings("unchecked")
private ConfigElement createConfigElement(Object o) {
if (o instanceof List) {
return createArray((List<Object>) o);
} else {
return createObject((Map<String, Object>) o);
}
}
private ConfigMap createObject(Map<String, Object> data) {
ConfigMap o = new ConfigMap();
if (data.containsKey("id")) {
o.setId(data.get("id").toString());
}
if (data.containsKey("jcondition")) {
o.setCondition(data.get("jcondition").toString());
}
data.remove("jcondition");
data.remove("jtype");
Map<String, Object> elements = new LinkedHashMap<String, Object>();
for (String key : data.keySet()) {
elements.put(key, data.get(key));
}
o.setElements(elements);
return o;
}
private ConfigList createArray(List<Object> data) {
ConfigList array = new ConfigList();
List<Object> elements = new ArrayList<Object>();
for (Object d : data) {
elements.add(d);
}
array.setElements(elements);
return array;
}
public void setConfigService(ConfigService configService) {
this.configService = configService;
}
}