All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.tsl2.nano.incubation.terminal.ItemAdministrator Maven / Gradle / Ivy

Go to download

TSL2 Framework Terminal (Console Application Framework named SIShell, providing Actions, Options, Commands, Inputs, lots of Selectors, PlatformManagement)

There is a newer version: 2.5.2
Show newest version
/*
 * File: $HeadURL$
 * Id  : $Id$
 * 
 * created by: Tom, Thomas Schneider
 * created on: 13.06.2015
 * 
 * Copyright: (c) Thomas Schneider 2015, all rights reserved
 */
package de.tsl2.nano.incubation.terminal;

import java.io.InputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import de.tsl2.nano.action.IConstraint;
import de.tsl2.nano.bean.def.Constraint;
import de.tsl2.nano.core.cls.BeanClass;
import de.tsl2.nano.core.cls.PrivateAccessor;
import de.tsl2.nano.core.execution.SystemUtil;
import de.tsl2.nano.core.util.FileUtil;
import de.tsl2.nano.core.util.StringUtil;
import de.tsl2.nano.core.util.Util;
import de.tsl2.nano.execution.AntRunner;
import de.tsl2.nano.format.RegExpFormat;
import de.tsl2.nano.incubation.terminal.item.AItem;
import de.tsl2.nano.incubation.terminal.item.Action;
import de.tsl2.nano.incubation.terminal.item.Command;
import de.tsl2.nano.incubation.terminal.item.Container;
import de.tsl2.nano.incubation.terminal.item.Input;
import de.tsl2.nano.incubation.terminal.item.MainAction;
import de.tsl2.nano.incubation.terminal.item.Option;
import de.tsl2.nano.incubation.terminal.item.selector.ActionSelector;
import de.tsl2.nano.incubation.terminal.item.selector.CSVSelector;
import de.tsl2.nano.incubation.terminal.item.selector.DirSelector;
import de.tsl2.nano.incubation.terminal.item.selector.FieldSelector;
import de.tsl2.nano.incubation.terminal.item.selector.FileSelector;
import de.tsl2.nano.incubation.terminal.item.selector.PropertySelector;
import de.tsl2.nano.incubation.terminal.item.selector.SQLSelector;
import de.tsl2.nano.incubation.terminal.item.selector.Sequence;
import de.tsl2.nano.incubation.terminal.item.selector.XPathSelector;
import de.tsl2.nano.incubation.vnet.workflow.Condition;

/**
 * item administration shell
 * 
 * @author Tom, Thomas Schneider
 * @version $Revision$
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class ItemAdministrator extends Container {
    private static final String NEWINDEX = "newindex";
    /** the items position in a container/tree */
    private static final String INDEX = "index";
    /** mostly needed to define an action */
    private static final String ARGS = "args[]";
    /** the items type (full class name) */
    private static final String TYPE = "type";

    private static final long serialVersionUID = 5127419882040627794L;

    transient IItem parent;
    transient SIShell terminal;
    /** item as descriptor for new items */
    transient Properties item;
    private Action addingAction;
    private Action removingAction;
    private Action changingAction;
    private Action constraintsAction;
    private Action terminalAction;
    private static int count = 0;

    static Map itemTypes;
    static {
        String file = "admin.properties";
        Properties adminProperties =
            FileUtil.hasResource(file) ? FileUtil.loadProperties(file, null) : new Properties();
        itemTypes = new HashMap();
        if (adminProperties.isEmpty()) {
            //add special parameter to available items
            itemTypes.put("container", new String[] { Container.class.getName(), "multiple", "sequential" });
            itemTypes.put("option", new String[] { Option.class.getName() });
            itemTypes.put("input", new String[] { Input.class.getName() });
            itemTypes.put("action", new String[] { Action.class.getName(), "mainClass", "method", ARGS });
            itemTypes.put("mainaction", new String[] { MainAction.class.getName(), "mainClass", ARGS });
            itemTypes.put("command", new String[] { Command.class.getName(), "cmd", ARGS });
            itemTypes.put("shell", new String[] { Action.class.getName(), "mainClass=" + SystemUtil.class.getName(),
                "method=execute", ARGS });
            itemTypes.put("ant", new String[] { Action.class.getName(), "mainClass=" + AntRunner.class.getName(),
                "method=runTask", ARGS /*"task", "properties", "fileset"*/});
            itemTypes.put("selector", new String[] { ActionSelector.class.getName(), "mainClass=", "method", ARGS });
            itemTypes.put("file", new String[] { FileSelector.class.getName(), "roots", "include" });
            itemTypes.put("dir", new String[] { DirSelector.class.getName(), "roots", "include" });
            itemTypes.put("csv", new String[] { CSVSelector.class.getName(), "csv", "pattern" });
            itemTypes.put("properties", new String[] { PropertySelector.class.getName() });
            itemTypes.put("field", new String[] { FieldSelector.class.getName(), "cls", "field"/*field-type*/});
            itemTypes.put("xpath", new String[] { XPathSelector.class.getName(), "xml", "xpath"});
            itemTypes.put("sql", new String[] { SQLSelector.class.getName(), "driver", "url", "user", "password", "sql"});
            itemTypes.put("sequence", new String[] { Sequence.class.getName(), "action", "selector"});

            Properties p = new Properties();
            for (String k : itemTypes.keySet()) {
                p.put(k, StringUtil.concat(", ".toCharArray(), (Object[]) itemTypes.get(k)));
            }
            FileUtil.saveProperties(file, p);
        } else {
            String k, v;
            for (Object key : adminProperties.keySet()) {
                k = (String) key;
                v = adminProperties.getProperty(k);
                itemTypes.put(k, v.split("\\,\\s*"));
            }
        }
    }

    /**
     * constructor
     */
    public ItemAdministrator(SIShell terminal, Container toAdmin) {
        init(terminal, toAdmin);
    }

    protected void init(final SIShell terminal, Container toAdmin) {
        this.terminal = terminal;
        this.parent = toAdmin;
        this.nodes = (List>) new PrivateAccessor(toAdmin).member("nodes");
        item = new Properties();
        name = "Admin: " + toAdmin.getName();
        setDescription("Provides administration of item " + toAdmin.getName());

        //action to add items
        addingAction = new Action(this, "addItem") {
            @Override
            public IItem react(IItem caller, String input, InputStream in, PrintStream out, Properties env) {
                askItem(in, out, env, this, item, TYPE, INDEX, "name", "value", "description", "condition", "style");
                return super.react(caller, input, in, out, env);
            }

        };
        addingAction.setParent(this);
        nodes.add(addingAction);

        //action to change items
        changingAction = new Action(this, "changeItem") {
            @Override
            public IItem react(IItem caller, String input, InputStream in, PrintStream out, Properties env) {
                //which item - show some infos
                out.print("select item to change: ");
                item.put(INDEX, nextLine(in, out));
                out.println(StringUtil.toFormattedString(new PrivateAccessor(nodes.get(getSelectedIndex())).members(),
                    -1));

                askItem(in, out, env, this, item, NEWINDEX, "name", "value", "description", "condition", "style");
                return super.react(caller, input, in, out, env);
            }

        };
        changingAction.setParent(this);
        nodes.add(changingAction);

        //action to change items constraints
        constraintsAction = new Action(this, "changeConstraints") {
            @Override
            public IItem react(IItem caller, String input, InputStream in, PrintStream out, Properties env) {
                //which item - show some infos
                out.print("select item to change constraints: ");
                item.put(INDEX, nextLine(in, out));
                IConstraint c = nodes.get(getSelectedIndex()).getConstraints();
                if (c != null)
                    out.println(StringUtil.toFormattedString(new PrivateAccessor(c).members(), -1));

                askItem(in, out, env, this, item, "type", "format", "nullable", "length", "scale", "precision", "min",
                    "max", "defaultValue");
                return super.react(caller, input, in, out, env);
            }

        };
        constraintsAction.setParent(this);
        nodes.add(constraintsAction);

        //action to remove items
        removingAction = new Action(this, "removeItem") {
            @Override
            public IItem react(IItem caller, String input, InputStream in, PrintStream out, Properties env) {
                out.print("select item to remove: ");
                item.put(INDEX, nextLine(in, out));
                env.put("instance", this);
                return super.react(caller, input, in, out, env);
            }
        };
        removingAction.setParent(this);
        nodes.add(removingAction);

        //action to change the terminal
        terminalAction = new Action(this, "changeTerminal") {
            @Override
            public IItem react(IItem caller, String input, InputStream in, PrintStream out, Properties env) {
                out.println("\nchanging terminal:\n" + terminal);
                askItem(in, out, env, this, item, SIShell.presentalMembers());
                return super.react(caller, input, in, out, env);
            }

        };
        terminalAction.setParent(this);
        nodes.add(terminalAction);

        setDescription("the type should be one of: [container, input, option] or:\n"
            + StringUtil.toFormattedString(itemTypes, -1, true));
    }

    /**
     * asks for the given item attributes like name, value, description etc.
     * 
     * @param in user input stream
     * @param out user information print stream
     * @param env action context to add this instance to.
     */
    public static void askItem(InputStream in,
            PrintStream out,
            Properties env,
            Object instance,
            Properties item,
            String... itemAttributes) {
        //first, the standard attributes
        for (int i = 0; i < itemAttributes.length; i++) {
            out.print(itemAttributes[i] + ": ");
            item.put(itemAttributes[i], SIShell.nextLine(in, out));
        }

        //some defaults and instances
        boolean hasType = item.containsKey(TYPE);
        if (!Util.isEmpty(item.get("condition")))
            item.put("condition", new Condition(item.getProperty("condition")));
        if (!Util.isEmpty(item.get("condition")))
            item.put("condition", new Condition(item.getProperty("condition")));
        //now, the type specific attributes
        if (hasType) {
            String type = item.getProperty(TYPE);
            if (Util.isEmpty(type))
                type = "input";
            if (Util.isEmpty(item.get("name")))
                item.put("name", type + "-" + ++count);

            String description[] = itemTypes.get(type.toLowerCase());
            if (description != null) {
                item.put(TYPE, description[0]);
                for (int i = 1; i < description.length; i++) {
                    if (!description[i].equals(ARGS)) {
                        if (!description[i].contains("=")) {
                            out.print(description[i] + ": ");
                            item.put(description[i], SIShell.nextLine(in, out));
                        } else {
                            String kv[] = description[i].split("=");
                            item.put(kv[0], kv[1]);
                        }
                    } else {
                        //method arguments
                        List argNames = new LinkedList();
                        String arg;
                        while (true) {
                            out.print("argument name " + argNames.size() + ": ");
                            if (Util.isEmpty(arg = SIShell.nextLine(in, out)))
                                break;
                            argNames.add(arg);
                        }
                        item.put("argNames", argNames.toArray(new String[0]));
                    }
                }
            } else if (hasType) {
                out.println("The type should be one of:\n" + StringUtil.toString(itemTypes.keySet(), -1));
                type = StringUtil.toFirstUpper(type);
                String cls = type.contains(".") ? type : AItem.class.getPackage().getName() + "." + type;
                out.println("\nTrying type: " + cls);
                out.println("<<>>");
                SIShell.nextLine(in, out);
                item.put(TYPE, cls);
            }
        }
        env.put("instance", instance);
    }

    /**
     * clean, to be called, if administration will be left.
     */
    public void clean() {
        nodes.remove(addingAction);
        nodes.remove(removingAction);
        nodes.remove(changingAction);
        nodes.remove(constraintsAction);
        nodes.remove(terminalAction);
    }

    /**
     * adds a new item
     */
    public void addItem() {
        item.put("parent", parent);
        add(nodes, item);
    }

    int getSelectedIndex() {
        return Integer.valueOf(item.getProperty(INDEX)) - 1;
    }

    /**
     * add a new item
     * 
     * @param nodes node list to add the new item to
     * @param item to be added
     */
    public static  void add(List> nodes, Properties item) {
        try {
            AItem instance = BeanClass.createInstance(item.getProperty(TYPE));
            int index = !Util.isEmpty(item.get(INDEX)) ? Integer.valueOf((String) item.get(INDEX)) : nodes.size();
            item.remove(TYPE);
            item.remove(INDEX);
            nodes.add(index, PrivateAccessor.assign(instance, item, false));
        } finally {
            item.clear();
        }
    }

    public void removeItem() {
        try {
            nodes.remove(getSelectedIndex());
        } finally {
            item.clear();
        }
    }

    public void changeItem() {
        try {
            AItem selectedItem = nodes.get(getSelectedIndex());
            int index = !Util.isEmpty(item.get(NEWINDEX)) ? Integer.valueOf((String) item.get(NEWINDEX)) : -1;
            item.remove(TYPE);
            item.remove(INDEX);
            item.remove(NEWINDEX);
            PrivateAccessor.assign(selectedItem, item, false);

            if (index != -1) {
                nodes.remove(selectedItem);
                nodes.add(index - 1, selectedItem);
            }
        } finally {
            item.clear();
        }
    }

    public void changeConstraints() {
        try {
            IItem selectedItem = nodes.get(getSelectedIndex());
            String pattern = item.getProperty("format");
            if (!Util.isEmpty(pattern)) {
                String slen = item.getProperty("length");
                if (!Util.isEmpty(slen))
                    item.put("format", new RegExpFormat(pattern, Integer.valueOf(slen)));
                else
                    item.put("format", new RegExpFormat(pattern, null));
            }
            item.remove("name");
            item.remove(INDEX);
            IConstraint c = selectedItem.getConstraints() != null ? selectedItem.getConstraints() : new Constraint();
            PrivateAccessor.assign(c, item, false);
        } finally {
            item.clear();
        }
    }

    public void changeTerminal() {
        try {
            PrivateAccessor.assign(terminal, item, false);
        } finally {
            item.clear();
        }
    }

    @Override
    public String getDescription(Properties env, boolean full) {
        if (full)
            return "Provides administration of item " + parent.getName() + "\n"
                + StringUtil.toFormattedString(itemTypes, -1, true);
        return super.getDescription(env, full);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy