You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
9.5 KiB
368 lines
9.5 KiB
package de.srsoftware.web4rail; |
|
|
|
import java.security.MessageDigest; |
|
import java.security.NoSuchAlgorithmException; |
|
import java.util.AbstractMap; |
|
import java.util.ArrayList; |
|
import java.util.Date; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Random; |
|
|
|
import org.json.JSONObject; |
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
|
|
import de.keawe.tools.translations.Translation; |
|
import de.srsoftware.tools.Tag; |
|
import de.srsoftware.web4rail.actions.Action; |
|
import de.srsoftware.web4rail.conditions.Condition; |
|
import de.srsoftware.web4rail.moving.Car; |
|
import de.srsoftware.web4rail.moving.Locomotive; |
|
import de.srsoftware.web4rail.moving.Train; |
|
import de.srsoftware.web4rail.tags.Button; |
|
import de.srsoftware.web4rail.tags.Fieldset; |
|
import de.srsoftware.web4rail.tags.Form; |
|
import de.srsoftware.web4rail.tags.Input; |
|
import de.srsoftware.web4rail.tags.Table; |
|
import de.srsoftware.web4rail.tags.TextArea; |
|
import de.srsoftware.web4rail.tiles.Block; |
|
import de.srsoftware.web4rail.tiles.Contact; |
|
import de.srsoftware.web4rail.tiles.Tile; |
|
|
|
public abstract class BaseClass implements Constants{ |
|
protected static Plan plan; // the track layout in use |
|
public static final Random random = new Random(); |
|
public static String speedUnit = DEFAULT_SPEED_UNIT; |
|
public static String lengthUnit = DEFAULT_LENGTH_UNIT; |
|
private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); |
|
protected Id id = null; |
|
protected String notes; |
|
|
|
public static final Logger LOG = LoggerFactory.getLogger(BaseClass.class); |
|
private BaseClass parent; |
|
|
|
public static class Context { |
|
|
|
private BaseClass main = null; |
|
private Tile tile; |
|
private Block block; |
|
private Train train; |
|
private Route route; |
|
private Action action; |
|
private Condition condition; |
|
private Car car; |
|
private Contact contact; |
|
|
|
public Context(BaseClass object) { |
|
main = object; |
|
if (main instanceof Tile) this.tile = (Tile) main; |
|
if (main instanceof Contact) this.contact = (Contact) main; |
|
if (main instanceof Block) this.block = (Block) main; |
|
if (main instanceof Train) this.train = (Train) main; |
|
if (main instanceof Route) this.route = (Route) main; |
|
if (main instanceof Action) this.action = (Action) main; |
|
if (main instanceof Condition) this.condition = (Condition) main; |
|
if (main instanceof Car) this.car = (Car) main; |
|
} |
|
|
|
public Action action() { |
|
return action; |
|
} |
|
|
|
public Block block() { |
|
return block; |
|
} |
|
|
|
public Context block(Block newBlock) { |
|
block = newBlock; |
|
return this; |
|
} |
|
|
|
public Car car() { |
|
return car; |
|
} |
|
|
|
public Context clone() { |
|
return new Context(main); |
|
} |
|
|
|
public Condition condition() { |
|
return condition; |
|
} |
|
|
|
public Contact contact() { |
|
return contact; |
|
} |
|
|
|
public Route route() { |
|
return route; |
|
} |
|
|
|
public Context route(Route newRoute) { |
|
route = newRoute; |
|
return this; |
|
} |
|
|
|
public Tile tile() { |
|
return tile; |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
StringBuffer sb = new StringBuffer(getClass().getSimpleName()); |
|
sb.append("("); |
|
sb.append(t("Train: {}",train)); |
|
if (isSet(route)) sb.append(", "+t("Route: {}",route)); |
|
if (isSet(contact)) sb.append(", "+t("Contact: {}",contact)); |
|
sb.append(")"); |
|
return sb.toString(); |
|
} |
|
|
|
public Train train() { |
|
return train; |
|
} |
|
|
|
public Context train(Train newTrain) { |
|
train = newTrain; |
|
return this; |
|
} |
|
} |
|
|
|
public class FormInput extends ArrayList<Map.Entry<String, Tag>>{ |
|
|
|
private static final long serialVersionUID = -2371203388908395216L; |
|
|
|
public FormInput add(String caption,Tag tag) { |
|
add(new AbstractMap.SimpleEntry<String,Tag>(caption,tag)); |
|
return this; |
|
} |
|
} |
|
|
|
public static class Id implements CharSequence, Comparable<Id>{ |
|
private String internalId; |
|
|
|
public Id() { |
|
try { |
|
Thread.sleep(1); |
|
} catch (InterruptedException e) { |
|
e.printStackTrace(); |
|
} |
|
internalId = ""+new Date().getTime(); |
|
} |
|
|
|
|
|
public Id(String id) { |
|
internalId = id; |
|
} |
|
|
|
@Override |
|
public int hashCode() { |
|
return internalId.hashCode(); |
|
} |
|
|
|
@Override |
|
public boolean equals(Object other) { |
|
if (other == null) return false; |
|
if (this == other) return true; |
|
return internalId.equals(other.toString()); |
|
} |
|
|
|
public static Id from(JSONObject json) { |
|
return Id.from(json,ID); |
|
} |
|
|
|
public static Id from(JSONObject json,String key) { |
|
return json.has(key) ? new Id(""+json.get(key)) : null; |
|
} |
|
|
|
public static Id from(Map<String,String> params) { |
|
return Id.from(params,ID); |
|
} |
|
|
|
|
|
public static Id from(Map<String, String> params, String key) { |
|
String sid = params.get(key); |
|
return sid == null ? null : new Id(sid); |
|
} |
|
|
|
@Override |
|
public char charAt(int index) { |
|
return internalId.charAt(index); |
|
} |
|
|
|
|
|
@Override |
|
public int length() { |
|
return internalId.length(); |
|
} |
|
|
|
|
|
@Override |
|
public CharSequence subSequence(int begin, int end) { |
|
return internalId.subSequence(begin, end); |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
return internalId; |
|
} |
|
|
|
|
|
@Override |
|
public int compareTo(Id other) { |
|
return internalId.compareTo(other.internalId); |
|
} |
|
} |
|
|
|
public Button button(String text,Map<String,String> additionalProps) { |
|
return new Button(text,props(additionalProps)); |
|
} |
|
|
|
public Button button(String text) { |
|
return button(text,null); |
|
} |
|
|
|
public String realm() { |
|
if (this instanceof Tile) return REALM_PLAN; |
|
if (this instanceof Contact) return REALM_CONTACT; |
|
|
|
if (this instanceof Car) return REALM_CAR; |
|
if (this instanceof Locomotive) return REALM_LOCO; |
|
|
|
if (this instanceof Action) return REALM_ACTIONS; |
|
if (this instanceof Condition) return REALM_CONDITION; |
|
if (this instanceof Route) return REALM_ROUTE; |
|
if (this instanceof Train) return REALM_TRAIN; |
|
return REALM_PLAN; |
|
} |
|
|
|
public Map<String,String> contextAction(String action){ |
|
return Map.of(ACTION,action,CONTEXT,realm()+":"+id()); |
|
} |
|
|
|
public Form form(String id,List<Map.Entry<String, Tag>> elements) { |
|
Form form = new Form(id); |
|
|
|
Table table = new Table(); |
|
for (Map.Entry<String, Tag>entry : elements) { |
|
String key = entry.getKey(); |
|
Tag val = entry.getValue(); |
|
if (isNull(key) && val instanceof Input) ((Input)val).hideIn(form); |
|
table.addRow(isSet(key)?key:"",entry.getValue()); |
|
} |
|
|
|
table.addTo(form); |
|
|
|
new Button(t("Apply"),form).addTo(form); |
|
return form; |
|
} |
|
|
|
public Id id() { |
|
if (isNull(id)) id = new Id(); |
|
return id; |
|
} |
|
|
|
public static boolean isNull(Object o) { |
|
return o==null; |
|
} |
|
|
|
public static boolean isSet(Object o) { |
|
return o != null; |
|
} |
|
|
|
public JSONObject json() { |
|
JSONObject json = new JSONObject(); |
|
if (isSet(id)) json.put(ID, id().toString()); |
|
if (isSet(notes) && !notes.isEmpty()) json.put(NOTES, notes); |
|
return json; |
|
} |
|
|
|
public Tag link(String tagClass,Object caption) { |
|
return link(tagClass,caption,null); |
|
} |
|
|
|
public Tag link(String tagClass,Object caption,Map<String,String> additionalProps) { |
|
String json = new JSONObject(props(additionalProps)).toString().replace("\"", "'"); |
|
return new Tag(tagClass).clazz("link").attr("onclick","request("+json+")").content(caption.toString()); |
|
} |
|
|
|
|
|
public static String md5sum(Object o) { |
|
try { |
|
MessageDigest digest = MessageDigest.getInstance("MD5"); |
|
digest.update(o.toString().getBytes(UTF8)); |
|
StringBuffer sb = new StringBuffer(); |
|
for (byte b : digest.digest()) { |
|
sb.append(HEX_CHARS[(b & 0xF0) >> 4]); |
|
sb.append(HEX_CHARS[b & 0x0F]); |
|
} |
|
return sb.toString(); |
|
} catch (NoSuchAlgorithmException e) { |
|
return null; |
|
} |
|
} |
|
|
|
public static HashMap<String, String> merged(Map<String, String> base, Map<String, String> overlay) { |
|
HashMap<String,String> merged = new HashMap<>(base); |
|
overlay.entrySet().stream().forEach(entry -> merged.put(entry.getKey(), entry.getValue())); |
|
return merged; |
|
} |
|
|
|
public BaseClass parent() { |
|
return parent; |
|
} |
|
|
|
public BaseClass parent(BaseClass parent) { |
|
this.parent = parent; |
|
return this; |
|
} |
|
|
|
public Window properties() { |
|
return properties(new ArrayList<>(), new FormInput(), new ArrayList<>()); |
|
} |
|
|
|
|
|
protected Window properties(List<Fieldset> preForm,FormInput formInputs,List<Fieldset> postForm) { |
|
Window win = new Window(getClass().getSimpleName()+"-properties", t("Properties of {}",this)); |
|
|
|
preForm.forEach(fieldset -> fieldset.addTo(win)); |
|
|
|
formInputs.add(new AbstractMap.SimpleEntry<String, Tag>(null,new Input(ACTION, ACTION_UPDATE))); |
|
formInputs.add(new AbstractMap.SimpleEntry<String, Tag>(null,new Input(REALM,realm()))); |
|
formInputs.add(new AbstractMap.SimpleEntry<String, Tag>(null,new Input(ID,id()))); |
|
|
|
formInputs.add(new AbstractMap.SimpleEntry<String, Tag>(t("Notes"),new TextArea(NOTES,notes))); |
|
|
|
form(getClass().getSimpleName()+"-prop-form",formInputs) |
|
.addTo(new Fieldset(t("Basic properties"))) |
|
.addTo(win); |
|
|
|
postForm.forEach(fieldset -> fieldset.addTo(win)); |
|
|
|
return win; |
|
} |
|
|
|
private Map<String,String> props(Map<String,String> additionalProps){ |
|
HashMap<String,String> props = new HashMap<String, String>(Map.of(REALM, realm(), ACTION, ACTION_PROPS, ID, id().toString())); |
|
if (isSet(additionalProps)) props.putAll(additionalProps); |
|
return props; |
|
} |
|
|
|
protected static String t(String txt, Object...fills) { |
|
return Translation.get(Application.class, txt, fills); |
|
} |
|
|
|
protected Object update(HashMap<String, String> params) { |
|
LOG.debug("update: {}",params); |
|
if (params.containsKey(NOTES)) notes = params.get(NOTES).trim(); |
|
return this; |
|
} |
|
|
|
public BaseClass load(JSONObject json) { |
|
if (json.has(ID)) id = Id.from(json); |
|
if (json.has(NOTES)) notes = json.getString(NOTES); |
|
return this; |
|
} |
|
}
|
|
|