package com.applang;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.event.EventCartridge;
import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
import org.apache.velocity.runtime.parser.node.Node;
//import org.apache.velocity.tools.generic.MathTool;
import com.applang.Util.Function;
import com.applang.Util.Job;
import com.applang.Util.ValMap;
import com.applang.VelocityUtil.Visitor;
import com.applang.berichtsheft.R;
import static com.applang.Util.*;
import static com.applang.Util1.*;
import static com.applang.Util2.*;
import static com.applang.VelocityUtil.*;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
public class UserContext extends CustomContext implements Serializable
{
private static final long serialVersionUID = 1704932233683596747L;
// protected void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
// }
//
// protected void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
// }
public static String toPlainText(String script, Object...params) {
UserContext context = param(new UserContext(), 0, params);
return evaluate(context, script, TAG);
}
public UserContext() {
this(vmap());
}
public UserContext(ValMap map) {
super(map);
if (map != null) {
// map.put(MATH_TOOL.substring(1), new MathTool());
}
}
@Override
public String toString() {
return map.toString();
}
List<Object> allReferences() {
return asList(getKeys());
}
public ValList suggestions() {
ValList list = vlist();
for (Object item : allReferences()) {
String listItem = VRI + item.toString();
list.add(listItem);
}
return list;
}
public Collection<Object> suggestions(Predicate<Object> isIncluded, boolean negate) {
return filter(suggestions(), negate, isIncluded);
}
public static final String[] USER_DIRECTIVE_CLASSES = {
"com.applang.PromptDirective",
"com.applang.SpinnerDirective",
"com.applang.CursorDirective",
};
public static void setupVelocity(Activity activity, boolean force, Object... params) {
String logClassname = "com.applang.VelocityLogger";
if (!force && logClassname.equals(Velocity.getProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS)))
return;
if (activity != null && activity.getIntent() != null) {
String packageName = param(getPackageNameByClass(R.class), 0, params);
Velocity.setProperty("packageName", packageName);
Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
logClassname);
Velocity.setProperty(Velocity.RESOURCE_LOADER, "android");
Velocity.setProperty("android.resource.loader.class",
"com.applang.VelocityResourceLoader");
Velocity.setProperty("android.content.res.Resources",
activity.getResources());
}
Velocity.setProperty("userdirective", join(",", USER_DIRECTIVE_CLASSES));
Velocity.init();
};
public static Map<String,String> directives(Object...params) {
Map<String,String> direct = signatures();
ValMap map = param(null, 0, params);
if (map != null) {
Object[] elses = new Object[] { "else", "elseif" };
boolean endToken = hasEndToken(map);
Node node = (Node) map.get(NODE);
int partOfIF = Visitor.partOfIfStatement(node);
String tokens = Visitor.tokens(node);
switch (partOfIF) {
case 1:
if (endToken) {
boolean hasElse = findFirstIn(tokens, directivePattern(elses[0] + "(?!if)")) != null;
if (!hasElse)
break;
}
for (Object key : elses)
direct.remove(key);
break;
case 2:
case 3:
direct.remove(elses[0]);
break;
default:
if (endToken) {
String key = firstIdentifierFrom(tokens);
if (!direct.containsKey(key))
direct.clear();
}
else
for (Object key : elses)
direct.remove(key);
break;
}
}
for (String userClass : USER_DIRECTIVE_CLASSES)
try {
Class<?> c = Class.forName(userClass);
Object inst = c.newInstance();
String name = (String) c.getMethod("getName").invoke(inst);
Method m = c.getMethod("signature", Boolean.TYPE);
String value = (String) m.invoke(inst, true);
direct.put(name, value);
} catch (Exception e) {
log.error(TAG, e);
}
return direct;
}
public Object buildTerm(String image) {
String identifier = firstIdentifierFrom(image);
if (notNullOrEmpty(identifier))
try {
String baseClass = "com.applang.BaseDirective";
for (String userClass : arrayappend(USER_DIRECTIVE_CLASSES, baseClass)) {
Class<?> c = Class.forName(userClass);
Object inst = c.newInstance();
Method method = c.getMethod("construct", String.class, UserContext.class);
if (baseClass.equals(userClass)) {
return method.invoke(inst, image, this);
}
else {
String name = (String) c.getMethod("getName").invoke(inst);
if (identifier.equals(name)) {
Object o = c.getMethod("signature", Boolean.TYPE).invoke(inst, true);
return method.invoke(inst, o, this);
}
}
}
} catch (Exception e) {
log.error(TAG, e);
}
return image;
}
public static boolean isHidden(String key) {
return isOptionalArgument(key);
}
public static String hidden(String key) {
return optionalize(key);
}
public Node modify(Node node) {
this.put(hidden(NODE), node);
switch (Visitor.nodeGroup(node)) {
case DIRECTIVE:
String image = Visitor.tokens(node, VDI);
String name = firstIdentifierFrom(image);
String signature = directives().get(name);
buildTerm(signature);
break;
default:
break;
}
return node;
}
static ValMap nonNullMap(ValMap m) {
return (m != null) ? m : vmap();
}
public UserContext(ValMap map, EvaluationTask evaluationTask) {
this(nonNullMap(map));
this.evaluationTask = evaluationTask;
}
transient private EvaluationTask evaluationTask;
public EvaluationTask getEvaluationTask() {
return evaluationTask;
}
public static class EvaluationTask extends Task<Object>
{
public EvaluationTask(Activity activity, ValMap refMap,
Handler progressHandler, Job<Void> progressJob,
Job<Object> followUp, Object... params)
{
super(activity, followUp, params);
setupVelocity(activity, true);
this.progressHandler = progressHandler;
this.progressJob = progressJob;
this.userContext = new UserContext(refMap, this);
for (Object authority : contentAuthorities(providerPackages)) {
String auth = String.valueOf(authority);
String key = split(auth, DOT_REGEX).get(-1) + "Uri";
userContext.put(key, contentUri(auth, null).toString());
}
}
private Handler progressHandler;
private Job<Void> progressJob;
private UserContext userContext = null;
private List<String> refs = null;
private int size = 0;
@Override
protected void onPreExecute() {
super.onPreExecute();
if (progressHandler != null) {
EventCartridge ec = new EventCartridge();
ec.addEventHandler(new ReferenceInsertionEventHandler() {
@Override
public Object referenceInsert(final String reference, Object data) {
if (refs != null) {
int pos = refs.indexOf(reference);
if (pos > -1)
refs.remove(pos);
if (size > 0) {
final float percent = 100 * Float.valueOf(size - refs.size()) / size;
progressHandler.post(new Runnable() {
public void run() {
try {
progressJob.perform(null, new Object[]{(int)percent, reference});
} catch (Exception e) {
log.error(TAG, e);
}
}
});
}
}
return data;
}
});
ec.attachToContext(userContext);
}
}
@Override
protected Object doInBackground(Object... params) {
if (isAvailable(0, params)) {
Object param = params[0];
if (param instanceof String) {
String template = (String) param;
refs = referencesIn(template);
size = refs.size();
try {
return evaluate(userContext, template, TAG);
} catch (Exception e) {
publishProgress(
new Intent(Dialogs.PROMPT_ACTION)
.putExtra(BaseDirective.PROMPT, param_String("", 1, params))
.putExtra(BaseDirective.VALUES, strings(e.getMessage()))
.putExtra(BaseDirective.TYPE, Dialogs.DIALOG_TEXT_INFO));
}
}
else if (param instanceof Function<?>) {
params[0] = userContext;
return ((Function<?>)param).apply(params);
}
}
return null;
}
public void doInForeground(Intent intent) {
publishProgress(intent);
}
}
public static void buildDirective(final String key,
Activity activity, ValMap refMap,
Job<Object> followUp, Object...params)
{
new EvaluationTask(activity, refMap, null, null, followUp, params)
.execute(new Function<Object>() {
public Object apply(Object... params) {
UserContext userContext = (UserContext) params[0];
return userContext.buildTerm(key);
}
});
}
public static void modifyNode(final Node node,
Activity activity, ValMap refMap,
Job<Object> followUp, Object...params) {
new EvaluationTask(activity, refMap, null, null, followUp, params)
.execute(new Function<Node>() {
public Node apply(Object... params) {
UserContext userContext = (UserContext) params[0];
return userContext.modify(node);
}
});
}
}