From 6d761005eb1f2fedba92f6eb17e6781dcc47d7e8 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Thu, 17 Jun 2021 23:13:59 +0200 Subject: [PATCH] refactoring --- pom.xml | 2 +- .../translations/Application.de.translation | 1 + .../de/srsoftware/web4rail/Application.java | 3 + .../de/srsoftware/web4rail/BaseClass.java | 6 +- .../de/srsoftware/web4rail/Constants.java | 2 + .../srsoftware/web4rail/devices/Decoder.java | 42 +++++----- .../web4rail/functions/DirectedFunction.java | 54 +++++++++++++ .../web4rail/functions/Function.java | 81 +++++++++++++++---- .../web4rail/functions/FunctionList.java | 36 +++++++-- .../web4rail/functions/HeadLight.java | 29 +------ .../web4rail/functions/TailLight.java | 2 +- .../web4rail/moving/Locomotive.java | 74 ++++++++--------- 12 files changed, 213 insertions(+), 119 deletions(-) create mode 100644 src/main/java/de/srsoftware/web4rail/functions/DirectedFunction.java diff --git a/pom.xml b/pom.xml index 1bbaa0d..70b1264 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.4.45 + 1.4.46 Web4Rail jar Java Model Railway Control diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation index dbf9b46..e3f3287 100644 --- a/resources/translations/Application.de.translation +++ b/resources/translations/Application.de.translation @@ -119,6 +119,7 @@ custom fields : benutzerdefinierte Felder CustomFunction : benutzerdefinierte Funktion Date/Time : Datum/Zeit Decoder address : Decoder-Adresse +Decoder function : Decoder-Funktion decouple : Abkuppeln decoupler : decoupler Decoupler : Entkuppler diff --git a/src/main/java/de/srsoftware/web4rail/Application.java b/src/main/java/de/srsoftware/web4rail/Application.java index 2ebe68a..637ed0b 100644 --- a/src/main/java/de/srsoftware/web4rail/Application.java +++ b/src/main/java/de/srsoftware/web4rail/Application.java @@ -25,6 +25,7 @@ import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.actions.ActionList; import de.srsoftware.web4rail.conditions.Condition; import de.srsoftware.web4rail.devices.Decoder; +import de.srsoftware.web4rail.functions.Function; import de.srsoftware.web4rail.moving.Car; import de.srsoftware.web4rail.moving.Locomotive; import de.srsoftware.web4rail.moving.Train; @@ -128,6 +129,8 @@ public class Application extends BaseClass{ return plan.controlUnit().process(params); case REALM_DECODER: return Decoder.action(params); + case REALM_FUNCTION: + return Function.action(params); case REALM_HISTORY: return History.action(params); case REALM_LOCO: diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java index b32ef4e..1bc5f17 100644 --- a/src/main/java/de/srsoftware/web4rail/BaseClass.java +++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java @@ -25,6 +25,7 @@ import de.srsoftware.web4rail.Plan.Direction; import de.srsoftware.web4rail.actions.Action; import de.srsoftware.web4rail.conditions.Condition; import de.srsoftware.web4rail.devices.Decoder; +import de.srsoftware.web4rail.functions.Function; import de.srsoftware.web4rail.moving.Car; import de.srsoftware.web4rail.moving.Locomotive; import de.srsoftware.web4rail.moving.Train; @@ -569,10 +570,9 @@ public abstract class BaseClass implements Constants{ if (this instanceof Contact) return REALM_CONTACT; if (this instanceof Decoder) return REALM_DECODER; if (this instanceof Tile) return REALM_PLAN; - + if (this instanceof Function) return REALM_FUNCTION; if (this instanceof Locomotive) return REALM_LOCO; - if (this instanceof Car) return REALM_CAR; - + if (this instanceof Car) return REALM_CAR; if (this instanceof Action) return REALM_ACTIONS; if (this instanceof Condition) return REALM_CONDITION; if (this instanceof Route) return REALM_ROUTE; diff --git a/src/main/java/de/srsoftware/web4rail/Constants.java b/src/main/java/de/srsoftware/web4rail/Constants.java index b6477c0..a1cf2cd 100644 --- a/src/main/java/de/srsoftware/web4rail/Constants.java +++ b/src/main/java/de/srsoftware/web4rail/Constants.java @@ -46,6 +46,7 @@ public interface Constants { public static final String REALM_CONTACT = "contact"; public static final String REALM_CU = "cu"; public static final String REALM_DECODER = "decoder"; + public static final String REALM_FUNCTION = "function"; public static final String REALM_HISTORY = "history"; public static final String REALM_LOCO = "loco"; public static final String REALM_MAINTENANCE = "maintenance"; @@ -64,6 +65,7 @@ public interface Constants { public static final String DISABLED = "disabled"; public static final String DIRECTION = "direction"; public static final String FUNCTION = "function"; + public static final String FUNCTIONS = "functions"; public static final String GITHUB_URL = "https://github.com/srsoftware-de/Web4Rail"; public static final String ID = "id"; public static final String LOCKED = "locked"; diff --git a/src/main/java/de/srsoftware/web4rail/devices/Decoder.java b/src/main/java/de/srsoftware/web4rail/devices/Decoder.java index d6f9955..8bb1c65 100644 --- a/src/main/java/de/srsoftware/web4rail/devices/Decoder.java +++ b/src/main/java/de/srsoftware/web4rail/devices/Decoder.java @@ -17,6 +17,7 @@ import de.srsoftware.web4rail.Command.Reply; import de.srsoftware.web4rail.Constants; import de.srsoftware.web4rail.Params; import de.srsoftware.web4rail.Protocol; +import de.srsoftware.web4rail.functions.Function; import de.srsoftware.web4rail.moving.Locomotive; import de.srsoftware.web4rail.tags.Button; import de.srsoftware.web4rail.tags.Fieldset; @@ -46,7 +47,6 @@ public class Decoder extends BaseClass implements Constants, Device { private String type; private Locomotive loco; private int numFunctions = 2; - private HashSet enabledFunctions = new HashSet<>(); private int step; private boolean reverse; @@ -87,8 +87,13 @@ public class Decoder extends BaseClass implements Constants, Device { } public StringBuilder functions() { + HashSet enabledFunctions = new HashSet<>(); + for (Function fun : loco.functions()) { + if (fun.enabled(this)) enabledFunctions.add(fun.index()); + } + StringBuilder sb = new StringBuilder(); - for (int i=1; i<=numFunctions; i++) sb.append(" ").append(isEnabled(i)?1:0); + for (int i=1; i<=numFunctions; i++) sb.append(" ").append(enabledFunctions.contains(i)?1:0); return sb; } @@ -125,17 +130,13 @@ public class Decoder extends BaseClass implements Constants, Device { init = true; } - public boolean isEnabled(int function) { - return enabledFunctions.contains(function); - } - - @Override public JSONObject json() { JSONObject json = super.json(); json.put(CVS, cvs); json.put(PROTOCOL, proto); json.put(TYPE, type); + json.put(FUNCTIONS, numFunctions); return json; } @@ -154,6 +155,7 @@ public class Decoder extends BaseClass implements Constants, Device { for (String key : jCvs.keySet()) cvs.put(Integer.parseInt(key),jCvs.getInt(key)); } if (json.has(TYPE)) type = json.getString(TYPE); + if (json.has(FUNCTIONS)) numFunctions = json.getInt(FUNCTIONS); return this; } @@ -258,12 +260,9 @@ public class Decoder extends BaseClass implements Constants, Device { }); } - public void queue(double speed, boolean reverse) { - step = (int)(speed*proto.steps); - this.reverse = reverse; - queue(); + public boolean reverse() { + return reverse; } - public static Select selector(boolean freeOnly) { Select selector = new Select(REALM_DECODER); @@ -276,13 +275,7 @@ public class Decoder extends BaseClass implements Constants, Device { } return selector; } - - public void setFunction(Integer function, boolean enabled) { - if (enabled) { - if (enabledFunctions.add(function)) queue(); - } else if (enabledFunctions.remove(function)) queue(); - } - + public Decoder setLoco(Locomotive locomotive, boolean log) { loco = locomotive; if (log) addLogEntry(t("Mounted into \"{}\".",loco)); @@ -294,6 +287,12 @@ public class Decoder extends BaseClass implements Constants, Device { this.proto = proto; } + public void setSpeed(double speed, boolean reverse) { + step = (int)(speed*proto.steps); + this.reverse = reverse; + queue(); + } + private Object setting(int cv) { switch (cv) { case 1: @@ -317,11 +316,6 @@ public class Decoder extends BaseClass implements Constants, Device { return ""; } - public void toggleFunction(Integer index) { - if (!enabledFunctions.remove(index)) enabledFunctions.add(index); - queue(); - } - @Override public String toString() { return type()+" ("+t("Address")+": "+address()+")"; diff --git a/src/main/java/de/srsoftware/web4rail/functions/DirectedFunction.java b/src/main/java/de/srsoftware/web4rail/functions/DirectedFunction.java new file mode 100644 index 0000000..1a2f48f --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/functions/DirectedFunction.java @@ -0,0 +1,54 @@ +package de.srsoftware.web4rail.functions; + +import org.json.JSONObject; + +import de.srsoftware.web4rail.Params; +import de.srsoftware.web4rail.devices.Decoder; +import de.srsoftware.web4rail.tags.Checkbox; +import de.srsoftware.web4rail.tags.Fieldset; + +public class DirectedFunction extends Function { + + private boolean forward,reverse; + + @Override + public boolean enabled(Decoder decoder) { + if (!super.enabled(decoder)) return false; + if (decoder.reverse()) { + return reverse; + } else return forward; + } + + @Override + public Fieldset form(Decoder decoder) { + Fieldset fieldset = super.form(decoder); + String prefix = "functions/"+id()+"/"; + new Checkbox(prefix+FORWARD, t(FORWARD), forward, true).addTo(fieldset); + new Checkbox(prefix+REVERSE, t(REVERSE), reverse, true).addTo(fieldset); + return fieldset; + } + + @Override + public JSONObject json() { + JSONObject json = super.json(); + if (forward) json.put(FORWARD, true); + if (reverse) json.put(REVERSE, true); + return json; + } + + @Override + public DirectedFunction load(JSONObject json) { + super.load(json); + if (json.has(FORWARD)) forward = true; + if (json.has(REVERSE)) reverse = true; + return this; + } + + @Override + public Object update(Params params) { + if (params.containsKey(FORWARD)) forward = "on".equals(params.get(FORWARD)); + if (params.containsKey(REVERSE)) reverse = "on".equals(params.get(REVERSE)); + return super.update(params); + + } +} diff --git a/src/main/java/de/srsoftware/web4rail/functions/Function.java b/src/main/java/de/srsoftware/web4rail/functions/Function.java index 7b00fe6..01ef4e3 100644 --- a/src/main/java/de/srsoftware/web4rail/functions/Function.java +++ b/src/main/java/de/srsoftware/web4rail/functions/Function.java @@ -2,8 +2,11 @@ package de.srsoftware.web4rail.functions; import java.util.List; +import org.json.JSONObject; + import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.Constants; import de.srsoftware.web4rail.Params; import de.srsoftware.web4rail.devices.Decoder; import de.srsoftware.web4rail.tags.Fieldset; @@ -18,23 +21,25 @@ public abstract class Function extends BaseClass{ static final String FORWARD = "forward"; static final String REVERSE = "reverse"; - private int decoderFunction = 1; + private int decoderFunction = 1; + private boolean enabled; - public static Tag selector() { - Select selector = new Select(NEW); - selector.addOption("", t("Select function")); - - for (Class fun : List.of(HeadLight.class,TailLight.class,InteriorLight.class,Coupler.class,CustomFunction.class)) { - String className = fun.getSimpleName(); - selector.addOption(className,t(className)); + public static Object action(Params params) { + String action = params.getString(ACTION); + Function function = BaseClass.get(Id.from(params)); + BaseClass parent = isSet(function) ? function.parent() : null; + switch (action) { + case ACTION_DROP: + if (isSet(function)) { + function.remove(); + return parent.properties(); + } } - - return selector; + String message = t("Unknown action: {}",params.get(Constants.ACTION)); + return isSet(parent) ? parent.properties(message) : message; } public static Function create(String className) { - - if (isNull(className)) return null; try { return (Function) Class.forName(PACKAGE+"."+className).getDeclaredConstructor().newInstance(); @@ -43,6 +48,10 @@ public abstract class Function extends BaseClass{ } return null; } + + public boolean enabled(Decoder decoder) { + return enabled; + } public Fieldset form(Decoder decoder) { Fieldset fieldset = new Fieldset(name()); @@ -56,9 +65,53 @@ public abstract class Function extends BaseClass{ return fieldset; } + + public int index() { + return decoderFunction; + } + + @Override + public JSONObject json() { + JSONObject json = super.json(); + json.put(TYPE, type()); + json.put(INDEX, decoderFunction); + return json; + } + + @Override + public Function load(JSONObject json) { + super.load(json); + if (json.has(INDEX)) decoderFunction = json.getInt(INDEX); + return this; + } + + public String name() { + return t(type()); + } + + public static Tag selector() { + Select selector = new Select(NEW); + selector.addOption("", t("Select function")); + + for (Class fun : List.of(HeadLight.class,TailLight.class,InteriorLight.class,Coupler.class,CustomFunction.class)) { + String className = fun.getSimpleName(); + selector.addOption(className,t(className)); + } + + return selector; + } - private String name() { - return t(getClass().getSimpleName()); + public void setState(boolean enabled) { + this.enabled = enabled; + } + + @Override + public String toString() { + return name()+"("+decoderFunction+"="+enabled+")"; + } + + private String type() { + return getClass().getSimpleName(); } @Override diff --git a/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java b/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java index a3d62c4..9f62821 100644 --- a/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java +++ b/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java @@ -2,24 +2,46 @@ package de.srsoftware.web4rail.functions; import java.util.HashSet; +import org.json.JSONArray; import org.json.JSONObject; +import de.srsoftware.web4rail.Constants; +import de.srsoftware.web4rail.moving.Locomotive; + /** * @author Stephan Richter * */ -public class FunctionList extends HashSet{ +public class FunctionList extends HashSet implements Constants{ private static final long serialVersionUID = 8013610745085726979L; + private HashSet enabledFunctions = new HashSet<>(); + + public boolean enabled(String name) { + return enabledFunctions.contains(name); + } + - public JSONObject json() { - // TODO Auto-generated method stub - return null; + public JSONArray json() { + JSONArray json = new JSONArray(); + for (Function fun : this) json.put(fun.json()); + return json; } - public void load(JSONObject jsonObject) { - // TODO Auto-generated method stub - + public void load(JSONArray arr, Locomotive loco) { + arr.forEach(o -> { + if (o instanceof JSONObject) load((JSONObject)o,loco); + }); } + private void load(JSONObject json, Locomotive loco) { + if (json.has(TYPE)) add(Function.create(json.getString(TYPE)).load(json).parent(loco)); + } + + public FunctionList toggle(String name) { + boolean enabled = !enabledFunctions.remove(name); + if (enabled) enabledFunctions.add(name); + stream().filter(fun -> name.equals(fun.name())).forEach(fun -> fun.setState(enabled)); + return this; + } } diff --git a/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java b/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java index f7c6265..0080048 100644 --- a/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java +++ b/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java @@ -1,32 +1,5 @@ package de.srsoftware.web4rail.functions; -import de.srsoftware.web4rail.Params; -import de.srsoftware.web4rail.devices.Decoder; -import de.srsoftware.web4rail.tags.Checkbox; -import de.srsoftware.web4rail.tags.Fieldset; +public class HeadLight extends DirectedFunction { -public class HeadLight extends Function { - - private boolean forward,reverse; - - public HeadLight() { - // TODO Auto-generated constructor stub - } - - @Override - public Fieldset form(Decoder decoder) { - Fieldset fieldset = super.form(decoder); - String prefix = "functions/"+id()+"/"; - new Checkbox(prefix+FORWARD, t(FORWARD), forward).addTo(fieldset); - new Checkbox(prefix+REVERSE, t(REVERSE), reverse).addTo(fieldset); - return fieldset; - } - - @Override - public Object update(Params params) { - if (params.containsKey(FORWARD)) forward = "on".equals(params.get(FORWARD)); - if (params.containsKey(REVERSE)) reverse = "on".equals(params.get(REVERSE)); - return super.update(params); - - } } diff --git a/src/main/java/de/srsoftware/web4rail/functions/TailLight.java b/src/main/java/de/srsoftware/web4rail/functions/TailLight.java index f0844ee..4fc926a 100644 --- a/src/main/java/de/srsoftware/web4rail/functions/TailLight.java +++ b/src/main/java/de/srsoftware/web4rail/functions/TailLight.java @@ -1,5 +1,5 @@ package de.srsoftware.web4rail.functions; -public class TailLight extends Function { +public class TailLight extends DirectedFunction { } diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java index 2d4c3ad..5821f1d 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; +import java.util.stream.Stream; import org.json.JSONObject; @@ -28,14 +29,8 @@ import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tiles.Block; public class Locomotive extends Car implements Constants{ - private static final String HEADLIGHT = "headlight"; - private static final String TAILLIGHT = "taillight"; - private static final String INTERIOR_LIGHT = "interior"; - private static final String COUPLER = "coupler"; - public static final String LOCOMOTIVE = "locomotive"; private static final String ACTION_MAPPING = "mapping"; - private static final String FUNCTIONS = "functions"; private FunctionList functions = new FunctionList(); private int speed = 0; //private TreeMap cvs = new TreeMap(); @@ -106,7 +101,7 @@ public class Locomotive extends Car implements Constants{ int speed = 0; String realm = null; Train train = null; - Locomotive loco = null; + final Locomotive loco; int maxSpeed = 0; String id = null; if (locoOrTrain instanceof Locomotive) { @@ -121,6 +116,7 @@ public class Locomotive extends Car implements Constants{ speed = train.speed; maxSpeed = train.maxSpeed(); id = "train_"+train.id(); + loco = null; } else return null; HashMap params = new HashMap(Map.of(REALM,realm,ID,locoOrTrain.id())); @@ -173,15 +169,12 @@ public class Locomotive extends Car implements Constants{ Tag functions = new Tag("p"); - if (isSet(loco) && isSet(loco.decoder)) { - - for (int i = 1; i<=loco.decoder.numFunctions(); i++) { - params.put(ACTION, ACTION_TOGGLE_FUNCTION); - params.put(FUNCTION,i); - Button btn = new Button(loco.functionName(i),params); - if (loco.decoder.isEnabled(i)) btn.clazz("active"); - btn.addTo(functions); - } + if (isSet(loco)) { + loco.functionNames().forEach(name -> { + Button btn = loco.button(name, Map.of(ACTION,ACTION_TOGGLE_FUNCTION,FUNCTION,name)); + if (loco.functions.enabled(name)) btn.clazz("active"); + btn.addTo(functions); + }); } if (isSet(train)) { @@ -200,6 +193,10 @@ public class Locomotive extends Car implements Constants{ return fieldset; } + public Decoder decoder() { + return decoder; + } + private String detail() { return getClass().getSimpleName()+"("+name()+", "+decoder.protocol()+", "+decoder.address()+")"; } @@ -216,27 +213,21 @@ public class Locomotive extends Car implements Constants{ new Input(ACTION, ACTION_MAPPING).hideIn(form); new Input(ID,id()).hideIn(form); - for (Function fun : functions) { - fun.form(decoder).addTo(form); - } + functions.stream() + .sorted((a,b) -> a.index() - b.index()) + .forEach(fun -> fun.button(t("delete"), Map.of(ACTION,ACTION_DROP)).addTo(fun.form(decoder)).addTo(form)); Fieldset newFun = new Fieldset(t("Add function")); Function.selector().addTo(newFun).addTo(form); return new Button(t("Save"), form).addTo(form).addTo(fieldset); } - - - private Tag functionMapping(int index) { - Fieldset mapping = new Fieldset(t("Function {}",index)); - return mapping; - } + private Stream functionNames() { + return functions.stream().map(Function::name).sorted().distinct(); + } - - private static String functionName(Object...parts) { - StringBuilder sb = new StringBuilder(FUNCTIONS); - for (Object part : parts) sb.append("/"+part); - return sb.toString(); + public FunctionList functions() { + return functions; } @Override @@ -267,7 +258,7 @@ public class Locomotive extends Car implements Constants{ } if (isSet(decoder)) decoder.setLoco(this,false); - if (loco.has(FUNCTIONS)) functions.load(loco.getJSONObject(FUNCTIONS)); + if (loco.has(FUNCTIONS)) functions.load(loco.getJSONArray(FUNCTIONS),this); } return this; @@ -308,9 +299,6 @@ public class Locomotive extends Car implements Constants{ return win; } - - - @Override protected Window properties(List
preForm, FormInput formInputs, List
postForm,String...errors) { @@ -321,6 +309,12 @@ public class Locomotive extends Car implements Constants{ return props; } + @Override + protected void removeChild(BaseClass child) { + functions.remove(child); + super.removeChild(child); + } + public void removeDecoder(Decoder decoder) { if (this.decoder == decoder) { addLogEntry(t("Removed decoder \"{}\".",decoder)); @@ -346,7 +340,7 @@ public class Locomotive extends Car implements Constants{ if (speed < 0) speed = 0; double step = 1.0 * speed / (maxSpeedForward == 0 ? 100 : maxSpeedForward); - decoder.queue(step,orientation != FORWARD); + decoder.setSpeed(step,orientation != FORWARD); } return properties(); @@ -360,12 +354,9 @@ public class Locomotive extends Car implements Constants{ } private Window toggleFunction(Params params) { - Integer index = params.getInt(FUNCTION); - Vector errors = new Vector(); - if (isNull(index)) errors.add(t("No function number provided!")); - if (isNull(decoder)) errors.add(t("{} has no decoder!",this)); - if (errors.isEmpty()) decoder.toggleFunction(index); - return properties(errors.toArray(new String[errors.size()])); + functions.toggle(params.getString(FUNCTION)); + if (isSet(decoder)) decoder.queue(); + return properties(); } public Object turn() { @@ -410,6 +401,7 @@ public class Locomotive extends Car implements Constants{ if (isSet(function)) function.update(funs.getParams(id)); } } + if (isSet(decoder)) decoder.queue(); return properties(); } }