001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.q2;
020
021import org.jline.reader.LineReader;
022import org.jpos.util.Loggeable;
023
024import java.io.*;
025import java.util.LinkedHashMap;
026import java.util.Map;
027
028public class CLIContext {
029    private boolean stopped = false;
030    private OutputStream out;
031    private OutputStream err;
032    private InputStream in;
033    private LineReader reader;
034    private Map<Object, Object> userData;
035    private CLI cli;
036    private String activeSubSystem = null;
037
038    @SuppressWarnings("unused")
039    private CLIContext() { }
040
041    private CLIContext(CLI cli, OutputStream out, OutputStream err, InputStream in, LineReader reader, Map<Object, Object> userData) {
042        this.cli = cli;
043        this.out = out;
044        this.err = err;
045        this.in = in;
046        this.reader = reader;
047        this.userData = userData;
048    }
049
050    public String getActiveSubSystem() {
051        return activeSubSystem;
052    }
053
054    public void setActiveSubSystem(String subSystem) {
055        String activeSubSystem = getActiveSubSystem();
056        if (subSystem == null && activeSubSystem != null) {
057            getUserData().remove(activeSubSystem);
058        }
059        this.activeSubSystem = subSystem;
060    }
061
062    public boolean isStopped() {
063        return stopped;
064    }
065
066    public void setStopped(boolean stopped) {
067        this.stopped = stopped;
068    }
069
070    public LineReader getReader() {
071        return reader;
072    }
073
074    public void setReader(LineReader reader) {
075        this.reader = reader;
076    }
077
078    public OutputStream getOutputStream() {
079        return out;
080    }
081
082    public OutputStream getErrorStream() {
083        return err;
084    }
085
086    public InputStream getInputStream() {
087        return in;
088    }
089
090    public Map<Object,Object> getUserData() {
091        return userData;
092    }
093
094    public boolean isInteractive() {
095        return cli.isInteractive();
096    }
097
098    public CLI getCLI() {
099        return cli;
100    }
101
102    public void printUserData() {
103        getUserData().forEach((k,v) -> {
104            println("Key: " + k.toString());
105            println("Value: " + v.toString());
106        });
107    }
108
109    public void printThrowable(Throwable t) {
110        ByteArrayOutputStream baos = new ByteArrayOutputStream();
111        t.printStackTrace(new PrintStream(baos));
112        println (baos.toString());
113    }
114
115    public void printLoggeable(Loggeable l, String indent) {
116        ByteArrayOutputStream baos = new ByteArrayOutputStream();
117        l.dump (new PrintStream(baos), indent);
118        println (baos.toString());
119    }
120
121    public void print(String s) {
122        if (isInteractive()) {
123            PrintWriter writer = getReader().getTerminal().writer();
124            writer.print(s);
125            writer.flush();
126        }
127        else {
128            try {
129                out.write(s.getBytes());
130                out.flush();
131            } catch (IOException ignored) {
132                ignored.printStackTrace();
133            }
134        }
135    }
136
137    public void println(String s)  {
138        print (s + System.getProperty("line.separator"));
139    }
140
141    public boolean confirm(String prompt) {
142        return "yes".equalsIgnoreCase(getReader().readLine(prompt));
143    }
144
145    public String readSecurely(String prompt) {
146        return getReader().readLine(prompt, '*');
147    }
148
149    public static Builder builder() {
150        return new Builder();
151    }
152
153    public static class Builder {
154        OutputStream out;
155        OutputStream err;
156        InputStream in;
157        LineReader reader;
158        CLI cli;
159        private Builder () { }
160
161        public Builder out (OutputStream out) {
162            this.out = out;
163            return this;
164        }
165
166        public Builder err (OutputStream err) {
167            this.err = err;
168            return this;
169        }
170
171        public Builder in (InputStream in) {
172            this.in = in;
173            return this;
174        }
175
176        public Builder reader (LineReader reader) {
177            this.reader = reader;
178            return this;
179        }
180
181        public Builder cli (CLI cli) {
182            this.cli = cli;
183            return this;
184        }
185
186        public CLIContext build() {
187            if (reader != null) {
188                if (out == null)
189                    out = reader.getTerminal().output();
190                if (err == null)
191                    err = out;
192            }
193            return new CLIContext(cli, out, err, in, reader, new LinkedHashMap());
194        }
195    }
196}