/*
* Copyright (C) 2010 Medo <smaxein@googlemail.com>
* Copyright (C) 2008, 2009 IsmAvatar <IsmAvatar@gmail.com>
*
* This file is part of GmkSplitter.
* GmkSplitter is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package com.ganggarrison.gmdec.xml;
import java.util.ArrayList;
import java.util.List;
import org.lateralgm.file.GmFile;
import org.lateralgm.resources.GmObject;
import org.lateralgm.resources.InstantiableResource;
import org.lateralgm.resources.Resource;
import org.lateralgm.resources.ResourceReference;
import org.lateralgm.resources.library.LibAction;
import org.lateralgm.resources.library.LibManager;
import org.lateralgm.resources.sub.Action;
import org.lateralgm.resources.sub.Argument;
import com.ganggarrison.easyxml.XmlReader;
import com.ganggarrison.easyxml.XmlWriter;
import com.ganggarrison.gmdec.DeferredReferenceCreator;
import com.ganggarrison.gmdec.DeferredReferenceCreatorNotifier;
import com.ganggarrison.gmdec.GmkSplitter;
import com.ganggarrison.gmdec.LgmConst;
import com.ganggarrison.gmdec.Tools;
public class ActionXmlFormat extends XmlFormat<Action> {
@Override
public void write(Action act, XmlWriter out) {
out.startElement("action");
{
LibAction la = act.getLibAction();
out.putAttribute("library", la.parent != null ? la.parent.id : la.parentId);
out.putAttribute("id", la.id);
if (la.name != null && !la.name.trim().isEmpty()) {
out.putComment("action name: " + la.name);
}
out.putElement("kind", LgmConst.toString(la.actionKind, ActionKind.class));
out.putElement("allowRelative", la.allowRelative);
out.putElement("question", la.question);
out.putElement("canApplyTo", la.canApplyTo);
out.putElement("actionType", LgmConst.toString(la.execType, ExecType.class));
out.putElement("functionName", la.execInfo);
out.putElement("relative", act.isRelative());
out.putElement("not", act.isNot());
ResourceReference<GmObject> at = act.getAppliesTo();
if (at == GmObject.OBJECT_OTHER) {
out.putElement("appliesTo", ".other");
} else if (at == GmObject.OBJECT_SELF) {
out.putElement("appliesTo", ".self");
} else {
writeResourceRef(out, "appliesTo", at);
}
out.startElement("arguments");
List<Argument> args = act.getArguments();
for (Argument arg : args) {
out.startElement("argument");
out.putAttribute("kind", LgmConst.toString(arg.kind, ArgumentKind.class));
if (Argument.getResourceKind(arg.kind) != null) {
ResourceReference<? extends Resource<?, ?>> ref = arg.getRes();
out.putText(getRefStr(ref));
} else if (GmkSplitter.convertLineEndings && la.execType == Action.EXEC_CODE && arg.kind == Argument.ARG_STRING) {
out.putText(Tools.toLf(arg.getVal()));
} else {
out.putText(arg.getVal());
}
out.endElement();
}
out.endElement();
}
out.endElement();
}
@Override
public Action read(XmlReader reader, DeferredReferenceCreatorNotifier notifier) {
reader.enterElement("action");
int library = reader.getIntAttribute("library");
int id = reader.getIntAttribute("id");
LibAction la = LibManager.getLibAction(library, id);
if (la == null) {
la = new LibAction();
}
la.id = id;
la.parentId = library;
la.actionKind = LgmConst.fromString(reader.getStringElement("kind"), ActionKind.class);
la.allowRelative = reader.getBoolElement("allowRelative");
la.question = reader.getBoolElement("question");
la.canApplyTo = reader.getBoolElement("canApplyTo");
la.execType = LgmConst.fromString(reader.getStringElement("actionType"), ExecType.class);
la.execInfo = reader.getStringElement("functionName");
boolean relative = reader.getBoolElement("relative");
boolean not = reader.getBoolElement("not");
String appliesTo = reader.getStringElement("appliesTo");
reader.enterElement("arguments");
List<Argument> args = new ArrayList<Argument>();
while (reader.hasNextElement()) {
reader.enterElement("argument");
byte kind = LgmConst.fromString(reader.getStringAttribute("kind"), ArgumentKind.class);
Argument arg = new Argument(kind);
if (Argument.getResourceKind(kind) != null) {
String ref = reader.getTextContent();
if (!ref.isEmpty()) {
ArgumentReferenceCreator arc = new ArgumentReferenceCreator(arg);
arc.setReference(ref, Argument.getResourceKind(kind));
notifier.addDeferredReferenceCreator(arc);
}
} else if (GmkSplitter.convertLineEndings && la.execType == Action.EXEC_CODE && arg.kind == Argument.ARG_STRING) {
arg.setVal(Tools.toCrlf(reader.getTextContent()));
} else {
arg.setVal(reader.getTextContent());
}
args.add(arg);
reader.leaveElement();
}
reader.leaveElement();
reader.leaveElement();
Action act = new Action(la, args.toArray(new Argument[args.size()]));
act.setRelative(relative);
act.setNot(not);
if (".self".equals(appliesTo.toLowerCase())) {
act.setAppliesTo(GmObject.OBJECT_SELF);
} else if (".other".equals(appliesTo.toLowerCase())) {
act.setAppliesTo(GmObject.OBJECT_OTHER);
} else {
ActionReferenceCreator rc = new ActionReferenceCreator(act);
rc.setReference(appliesTo);
notifier.addDeferredReferenceCreator(rc);
}
return act;
}
private static enum ArgumentKind implements LgmConst.Provider {
EXPRESSION(Argument.ARG_EXPRESSION),
STRING(Argument.ARG_STRING),
BOTH(Argument.ARG_BOTH),
BOOLEAN(Argument.ARG_BOOLEAN),
MENU(Argument.ARG_MENU),
SPRITE(Argument.ARG_SPRITE),
SOUND(Argument.ARG_SOUND),
BACKGROUND(Argument.ARG_BACKGROUND),
PATH(Argument.ARG_PATH),
SCRIPT(Argument.ARG_SCRIPT),
GMOBJECT(Argument.ARG_GMOBJECT),
ROOM(Argument.ARG_ROOM),
FONT(Argument.ARG_FONT),
COLOR(Argument.ARG_COLOR),
TIMELINE(Argument.ARG_TIMELINE),
FONTSTRING(Argument.ARG_FONTSTRING);
public final byte lgmconst;
private ArgumentKind(byte lgmconst) {
this.lgmconst = lgmconst;
}
@Override
public byte getLgmConst() {
return lgmconst;
}
}
private static enum ExecType implements LgmConst.Provider {
NONE(Action.EXEC_NONE),
FUNCTION(Action.EXEC_FUNCTION),
CODE(Action.EXEC_CODE);
public final byte lgmconst;
private ExecType(byte lgmconst) {
this.lgmconst = lgmconst;
}
@Override
public byte getLgmConst() {
return lgmconst;
}
}
private static enum ActionKind implements LgmConst.Provider {
NORMAL(Action.ACT_NORMAL),
BEGIN(Action.ACT_BEGIN),
END(Action.ACT_END),
ELSE(Action.ACT_ELSE),
EXIT(Action.ACT_EXIT),
REPEAT(Action.ACT_REPEAT),
VARIABLE(Action.ACT_VARIABLE),
CODE(Action.ACT_CODE),
PLACEHOLDER(Action.ACT_PLACEHOLDER),
SEPARATOR(Action.ACT_SEPARATOR),
LABEL(Action.ACT_LABEL);
public final byte lgmconst;
private ActionKind(byte lgmconst) {
this.lgmconst = lgmconst;
}
@Override
public byte getLgmConst() {
return lgmconst;
}
}
private static class ActionReferenceCreator implements DeferredReferenceCreator {
private Action action;
private String name;
public ActionReferenceCreator(Action action) {
this.action = action;
}
public void setReference(String name) {
this.name = name;
}
@Override
public void createReferences(GmFile gmf) {
if (name != null && !name.isEmpty()) {
GmObject refObj = gmf.resMap.getList(GmObject.class).get(name);
if (refObj != null) {
action.setAppliesTo(refObj.reference);
} else {
System.err.println("Warning: Action references unknown "
+ "object " + name);
}
}
}
}
private static class ArgumentReferenceCreator implements
DeferredReferenceCreator {
private Argument arg;
private String name;
private Class reskind;
public ArgumentReferenceCreator(Argument arg) {
this.arg = arg;
}
public void setReference(String ref, Class reskind) {
this.name = ref;
this.reskind = reskind;
}
@Override
public void createReferences(GmFile gmf) {
if (name != null && !name.isEmpty()) {
Resource<?, ?> refObj = gmf.resMap.getList((Class) reskind).get(name);
if (refObj != null) {
arg.setRes(refObj.reference);
} else {
System.err.println("Warning: Argument references unknown "
+ reskind + " " + name);
}
}
}
}
}