@@ -0,0 +1,107 @@
package vn.locdt.jats.bundle.question;

import jline.console.ConsoleReader;
import vn.locdt.jats.bundle.question.answer.Answer;
import vn.locdt.jats.bundle.question.element.question.Question;
import vn.locdt.jats.bundle.question.element.question.SingleChoiceQuestion;
import vn.locdt.jats.bundle.question.exception.ConsoleNotInitializeException;
import vn.locdt.jats.bundle.question.element.question.InputQuestion;

import java.io.IOException;
import java.util.*;

public class JQuestion {
private static ConsoleReader console;
private static QuestionGroup questionGroup;

static {
try {
console = new ConsoleReader();
} catch (IOException e) {
e.printStackTrace();
}
}

public static QuestionGroup createQuestionGroup() {
questionGroup = new QuestionGroup();
return questionGroup;
}

public static Answer input(String title, String name) {
try {
return new InputQuestion(title, name).prompt();
} catch (IOException e) {
e.printStackTrace();
} catch (ConsoleNotInitializeException e) {
e.printStackTrace();
}
return null;
}

public static Answer select(String title, String name, String[] selection) {
try {
return new SingleChoiceQuestion(title, name, selection).prompt();
} catch (IOException e) {
e.printStackTrace();
} catch (ConsoleNotInitializeException e) {
e.printStackTrace();
}
return null;
}

public static Answer select(String title, String name, List<String> selection) {
try {
return new SingleChoiceQuestion(title, name, selection).prompt();
} catch (IOException e) {
e.printStackTrace();
} catch (ConsoleNotInitializeException e) {
e.printStackTrace();
}
return null;
}

public static ConsoleReader getConsole() throws ConsoleNotInitializeException {
if (console == null) throw new ConsoleNotInitializeException("Console is not initialized.");
return console;
}

public static class QuestionGroup {
private Map<String, String> resultMap;
private List<Question> questions;

public QuestionGroup() {
this.questions = new ArrayList<>();
this.resultMap = new LinkedHashMap<>();
}

public QuestionGroup addInputQuestion(String title, String name) {
this.questions.add(new InputQuestion(title, name));
return this;
}

public QuestionGroup addInputQuestion(InputQuestion inputQuestion) {
this.questions.add(inputQuestion);
return this;
}

public QuestionGroup addSingleChoiceQuestion(SingleChoiceQuestion singleChoiceQuestion) {
this.questions.add(singleChoiceQuestion);
return this;
}

public Map<String, String> prompt() throws IOException, ConsoleNotInitializeException {
resultMap.clear();

if (questions.size() == 0)
return resultMap;

for (Question q : questions) {
Answer answer = q.prompt();
resultMap.put(answer.getName(), answer.getValue());
// System.out.println(answer);
}

return resultMap;
}
}
}
@@ -0,0 +1,56 @@
package vn.locdt.jats.bundle.question;

import java.util.Arrays;



public class Main {
public enum DBType {
MYSQL("MySQL"),
ORACLE("Oracle");
private String type;
DBType(String type) {
this.type = type;
}
public String getType() {return this.type;}
}

public static String[] getDatabaseTypes() {
return Arrays.stream(DBType.values()).map(DBType::getType).toArray(String[]::new);
}

public static void main(String[] args) {
// try {
String value = JQuestion.select("What do you want?", "want", getDatabaseTypes()).getValue();
// Map<String, String> resultMap = jQuestion.createQuestionGroup()
// .addInputQuestion("What is your grade?", "group")
// .addSingleChoiceQuestion(new SingleChoiceQuestion("What do you want?", "want")
// .addSelectors("Candy", "Apple", "Nothing"))
// .prompt();

// Gson gson = new Gson();
// System.out.println(gson.toJson(resultMap));

// } catch (IOException e) {
// e.printStackTrace();
// } catch (ConsoleNotInitializeException e) {
// e.printStackTrace();
// }
}
}
//// public static void main(String[] args) {
//// try {
//// System.out.println("Test Console Reader");
//// ConsoleReader console = new ConsoleReader();
//// int key = 0;
//// while(key != 3) {
//// key = console.readCharacter();
//// //key = cr.readVirtualKey();
//// System.out.println(key);
//// }
////
//// } catch(IOException e) {
//// e.printStackTrace();
//// }
//// }
//}
@@ -0,0 +1,41 @@
package vn.locdt.jats.bundle.question.answer;

import vn.locdt.jats.bundle.question.exception.UndefinedQuestionException;
import vn.locdt.jats.bundle.question.element.item.Item;

public class Answer {
private Item sourceItem;
private String value;

public Answer(Item sourceItem) throws UndefinedQuestionException {
if (sourceItem == null)
throw new UndefinedQuestionException("Can't determine answer for undefined question.");
this.sourceItem = sourceItem;
this.value = "";
}

public Answer(Item sourceItem, String value) throws UndefinedQuestionException {
if (sourceItem == null)
throw new UndefinedQuestionException("Can't determine answer for undefined question.");

this.sourceItem = sourceItem;
this.value = value;
}

public String getName() {
return sourceItem.getName();
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

@Override
public String toString() {
return "{\""+ sourceItem.getName() + ":" + "\"" + value + "\"}";
}
}
@@ -0,0 +1,25 @@
package vn.locdt.jats.bundle.question.constant;

public final class VKConstants {
public static final int VK_CTRL_C = 3;
public static final int VK_CTRL_D = 4;
public static final int VK_CTRL_Z = 26;
public static final int VK_ENTER = 13;

public static final int VK_BACK_SPACE = '\b';
public static final int VK_TAB = '\t';

public enum ArrowKey {
VK_UP,
VK_DOWN,
VK_LEFT,
VK_RIGHT
}

public final class WindowOS {
public static final int VK_UP = 57416;
public static final int VK_DOWN = 57424;
public static final int VK_LEFT = 57419;
public static final int VK_RIGHT = 57421;
}
}
@@ -0,0 +1,18 @@
package vn.locdt.jats.bundle.question.element;

/**
* Created by locdt on 1/10/2018.
*/
public abstract class RenderElement {
protected int renderHeight;

public int getRenderHeight() {
return renderHeight;
}

public void setRenderHeight(int renderHeight) {
this.renderHeight = renderHeight;
}

public abstract void updateRenderHeight();
}
@@ -0,0 +1,68 @@
package vn.locdt.jats.bundle.question.element.item;

import java.util.ArrayList;
import java.util.List;

public abstract class Choice extends Item {
public static String activedPrefix = "> ";
public static String deactivedPrefix = " ";
protected List<Selector> selectors;

public Choice(String title, String name) {
super(title, name, "");
this.selectors = new ArrayList<>();
}

public Choice(String title, String name, String[] selectors) {
super(title, name, "");
this.selectors = new ArrayList<>();
for (String s : selectors) {
this.selectors.add(new Selector(s));
}
updateRenderHeight();
}

public List<Selector> getSelectors() {
return this.selectors;
}

public void setSelectors(List<Selector> selectors) {
this.selectors = selectors;
for (Selector selector : this.selectors) {
selector.setPrefix(deactivedPrefix);
}
}

public void addSelector(Selector selector) {
if (selector != null) {
selector.setPrefix(deactivedPrefix);
this.selectors.add(selector);
updateRenderHeight();
}
}

public void addSelector(String selector) {
if (selector != null) {
Selector newSelector = new Selector(selector);
newSelector.setPrefix(deactivedPrefix);
this.selectors.add(newSelector);
updateRenderHeight();
}
}

public void addSelectors(List<Selector> selectors) {
this.selectors.addAll(selectors);
updateRenderHeight();
}

public void addSelectors(String[] selectors) {
for (String s : selectors)
addSelector(s);
updateRenderHeight();
}

@Override
public void updateRenderHeight() {
setRenderHeight(this.selectors.size());
}
}
@@ -0,0 +1,38 @@
package vn.locdt.jats.bundle.question.element.item;

/**
* Created by locdt on 1/10/2018.
*/
public class Confirm extends Item {
private String yesLabel;
private String noLabel;
private boolean confirmed;

public Confirm(String title, String name, String value) {
super(title, name, value);
}

public Confirm(String title, String name) {
super(title, name);
}

public boolean isConfirmed() {
return confirmed;
}
public void yesLabel(String yes) {
yesLabel = yes;
}

public void noLabel(String no) {
noLabel = no;
}

public void setConfirmed(boolean confirmed) {
this.confirmed = confirmed;
}

@Override
public void updateRenderHeight() {
setRenderHeight(1);
}
}
@@ -0,0 +1,17 @@
package vn.locdt.jats.bundle.question.element.item;

public class Input extends Item {
public Input(String title, String name, String value) {
super(title, name, value);
setRenderHeight(1);
}

public Input(String title, String name) {
this(title, name, "");
}

@Override
public void updateRenderHeight() {
setRenderHeight(1);
}
}
@@ -0,0 +1,45 @@
package vn.locdt.jats.bundle.question.element.item;

import vn.locdt.jats.bundle.question.element.RenderElement;

public abstract class Item extends RenderElement {
protected String name;
protected String value;
protected String title;

public Item(String title, String name, String value) {
this.title = title;
this.name = name;
this.value = value;
}

public Item(String title, String name) {
this.title = title;
this.name = name;
this.value = "";
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}
}
@@ -0,0 +1,10 @@
package vn.locdt.jats.bundle.question.element.item;

import java.util.List;

public class MultipleChoice extends Choice {
private List<Selector> activedSelector;
public MultipleChoice(String title, String name) {
super(title, name);
}
}
@@ -0,0 +1,27 @@
package vn.locdt.jats.bundle.question.element.item;

public class Selector {
private String prefix;
private String value;

public Selector(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public String getPrefix() {
return prefix;
}

public void setPrefix(String prefix) {
this.prefix = prefix;
}

@Override
public String toString() {
return this.prefix + this.value;
}
}
@@ -0,0 +1,28 @@
package vn.locdt.jats.bundle.question.element.item;

public class SingleChoice extends Choice {
private Selector activedSelector;

public SingleChoice(String title, String name) {
super(title, name);
}

public Selector getActivedSelector() {
return activedSelector;
}

public void setActivedSelector(Selector actived) {
if (activedSelector != null)
activedSelector.setPrefix(deactivedPrefix);

activedSelector = actived;
actived.setPrefix(activedPrefix);
}

public int indexOfActivedSelector() {
if (activedSelector == null || this.selectors.size() == 0)
return -1;

return this.selectors.indexOf(activedSelector);
}
}
@@ -0,0 +1,43 @@
package vn.locdt.jats.bundle.question.element.question;

import vn.locdt.jats.bundle.question.answer.Answer;
import vn.locdt.jats.bundle.question.event.NonBlockInputEvent;
import vn.locdt.jats.bundle.question.exception.ConsoleNotInitializeException;
import vn.locdt.jats.bundle.question.listener.NonBlockInputListener;
import vn.locdt.jats.bundle.question.JQuestion;
import vn.locdt.jats.bundle.question.util.ConsoleUtils;

import java.io.IOException;

/**
* Created by locdt on 1/10/2018.
*/
public class ConfirmQuestion extends Question implements NonBlockInputListener {

@Override
public Answer prompt() throws IOException, ConsoleNotInitializeException {
ConsoleUtils.renderQuestion(this);

// read input
int input;
boolean finished;
while (true) {
input = JQuestion.getConsole().readCharacter();
finished = onInput(new NonBlockInputEvent(input));
if (finished) break;
}

return this.answer;
}

private boolean handleInput(int charCode, NonBlockInputEvent e) {
return false;
}

@Override
public boolean onInput(NonBlockInputEvent e) {
int charCode = e.getAddedChar();
// System.out.println(charCode);
return handleInput(charCode, e);
}
}
@@ -0,0 +1,50 @@
package vn.locdt.jats.bundle.question.element.question;

import vn.locdt.jats.bundle.question.JQuestion;
import vn.locdt.jats.bundle.question.answer.Answer;
import vn.locdt.jats.bundle.question.event.InputEvent;
import vn.locdt.jats.bundle.question.exception.ConsoleNotInitializeException;
import vn.locdt.jats.bundle.question.exception.UndefinedQuestionException;
import jline.console.ConsoleReader;
import vn.locdt.jats.bundle.question.listener.InputListener;
import vn.locdt.jats.bundle.question.element.item.Input;
import vn.locdt.jats.bundle.question.util.ConsoleUtils;

import java.io.IOException;

public class InputQuestion extends Question implements InputListener {

public InputQuestion(String title, String name, boolean isPrintedResult) throws IOException {
super(isPrintedResult);
this.item = new Input(title, name);
try {
this.answer = new Answer(item);
} catch (UndefinedQuestionException e) {
e.printStackTrace();
}
}

public InputQuestion(String title, String name) {
super();
this.item = new Input(title, name);
try {
this.answer = new Answer(item);
} catch (UndefinedQuestionException e) {
e.printStackTrace();
}
}

@Override
public Answer prompt() throws IOException, ConsoleNotInitializeException {
ConsoleReader console = JQuestion.getConsole();
String result = console.readLine(item.getTitle() + " ");
return onInput(new InputEvent(result));
}

@Override
public Answer onInput(InputEvent e) {
setAnswer(e.getInputValue());
if (this.isPrintedResult) ConsoleUtils.printResult(this);
return getAnswer();
}
}
@@ -0,0 +1,15 @@
package vn.locdt.jats.bundle.question.element.question;

import vn.locdt.jats.bundle.question.element.item.Choice;

import java.util.ArrayList;
import java.util.List;

public class MultipleChoiceQuestion extends Choice {
private List<Integer> activedIndexes;

public MultipleChoiceQuestion(String title, String name) {
super(title, name);
this.activedIndexes = new ArrayList<>();
}
}
@@ -0,0 +1,55 @@
package vn.locdt.jats.bundle.question.element.question;

import vn.locdt.jats.bundle.question.answer.Answer;
import vn.locdt.jats.bundle.question.element.RenderElement;
import vn.locdt.jats.bundle.question.exception.ConsoleNotInitializeException;
import vn.locdt.jats.bundle.question.element.item.Item;

import java.io.IOException;

public abstract class Question<T extends Item> extends RenderElement {
protected T item;
protected boolean isPrintedResult = true;
protected Answer answer;

public Question() {}

public Question(boolean isPrintedResult) {
this.isPrintedResult = isPrintedResult;
}

public T getItem() {
return item;
}

public boolean isPrintedResult() {
return isPrintedResult;
}

public abstract Answer prompt() throws IOException, ConsoleNotInitializeException;

public Answer getAnswer() {
return this.answer;
}

public String getAnswerAsJson() {
return answer.getName() + ":" + answer.getValue();
}

public String getAnswerValue() {
return answer.getValue();
}

public void setAnswer(Answer answer) {
this.answer = answer;
}

public void setAnswer(String value) {
this.answer.setValue(value);
}

@Override
public void updateRenderHeight() {
setRenderHeight(getItem().getRenderHeight());
}
}
@@ -0,0 +1,208 @@
package vn.locdt.jats.bundle.question.element.question;

import vn.locdt.jats.bundle.question.answer.Answer;
import vn.locdt.jats.bundle.question.constant.VKConstants;
import vn.locdt.jats.bundle.question.event.ChangeSelectorEvent;
import vn.locdt.jats.bundle.question.event.ChooseSelectorEvent;
import vn.locdt.jats.bundle.question.event.NonBlockInputEvent;
import vn.locdt.jats.bundle.question.exception.ConsoleNotInitializeException;
import vn.locdt.jats.bundle.question.exception.UndefinedQuestionException;
import vn.locdt.jats.bundle.question.listener.ChoiceListener;
import vn.locdt.jats.bundle.question.listener.NonBlockInputListener;
import vn.locdt.jats.bundle.question.element.item.SingleChoice;
import vn.locdt.jats.bundle.question.util.DetectArrowKey;
import vn.locdt.jats.bundle.question.JQuestion;
import vn.locdt.jats.bundle.question.util.ConsoleUtils;
import vn.locdt.jats.bundle.question.element.item.Selector;

import java.io.IOException;
import java.util.List;

import static org.fusesource.jansi.Ansi.ansi;

public class SingleChoiceQuestion extends Question<SingleChoice> implements NonBlockInputListener, ChoiceListener {

public SingleChoiceQuestion(String title, String name) {
super();
this.item = new SingleChoice(title, name);
try {
this.answer = new Answer(item);
} catch (UndefinedQuestionException e) {
e.printStackTrace();
}
}

public SingleChoiceQuestion(String title, String name, boolean isPrintedResult) {
this(title, name);
this.isPrintedResult = isPrintedResult;
updateRenderHeight();
}

public SingleChoiceQuestion(String title, String name, List<Selector> selectors, boolean isPrintedResult) throws IOException {
this(title, name, isPrintedResult);
this.item.setSelectors(selectors);
updateRenderHeight();
}

public SingleChoiceQuestion(String title, String name, String[] selections) {
this(title, name);
for (Object select : selections) {
this.item.addSelector(new Selector(select.toString()));
}
updateRenderHeight();
}

public SingleChoiceQuestion(String title, String name, List<String> selections) {
this(title, name);
for (Object select : selections) {
this.item.addSelector(new Selector(select.toString()));
}
updateRenderHeight();
}

public SingleChoiceQuestion addSelector(String value) {
item.addSelector(new Selector(value));
updateRenderHeight();
return this;
}

public SingleChoiceQuestion addSelector(String value, boolean isActive) {
Selector selector = new Selector(value);
item.addSelector(selector);
if (isActive)
item.setActivedSelector(selector);

updateRenderHeight();
return this;
}

public SingleChoiceQuestion addSelectors(List<Selector> selectors) {
item.addSelectors(selectors);
updateRenderHeight();
return this;
}

public SingleChoiceQuestion addSelectors(String... values) {
item.addSelectors(values);
updateRenderHeight();
return this;
}

@Override
public Answer prompt() throws IOException, ConsoleNotInitializeException {
ConsoleUtils.renderQuestion(this);

if (item.getSelectors().size() == 0)
this.setAnswer("");

// read input
int input;
boolean finished;
while (true) {
input = JQuestion.getConsole().readCharacter();
finished = onInput(new NonBlockInputEvent(input));
if (finished) break;
}
return this.answer;
}

private void changeActiveSelector(VKConstants.ArrowKey arrowKey) {
int cursor = item.indexOfActivedSelector();
Selector lastSelector = item.getActivedSelector();
Selector nextSelector;

List<Selector> selectors = item.getSelectors();
switch (arrowKey) {
case VK_UP:
if (cursor > 0) cursor--;
break;
case VK_DOWN:
if (cursor < selectors.size() - 1) cursor++;
break;
}

nextSelector = selectors.get(cursor);
if (nextSelector != lastSelector) {
item.setActivedSelector(nextSelector);
onChanged(new ChangeSelectorEvent(lastSelector, nextSelector));
}
}

private boolean handleInput(int charCode, NonBlockInputEvent e) {
if (charCode == VKConstants.VK_ENTER) {
onChosen(new ChooseSelectorEvent(item.getActivedSelector()));
e.stop();
} else if (charCode == 27 && !DetectArrowKey.detecting) {
DetectArrowKey.detect();
} else if (DetectArrowKey.detecting) {
VKConstants.ArrowKey arrowKey = DetectArrowKey.update(charCode);
if (arrowKey != null)
changeActiveSelector(arrowKey);
} else if (e.getAddedChar() == VKConstants.VK_CTRL_D) {
e.stop();
}
else if (ConsoleUtils.isWindowOS()) {
handleWindowInput(charCode, e);
}

return e.isStop();
}

private void handleWindowInput(int charCode, NonBlockInputEvent e) {
VKConstants.ArrowKey arrowKey = null;
switch (charCode) {
case VKConstants.WindowOS.VK_DOWN:
arrowKey = VKConstants.ArrowKey.VK_DOWN;
break;
case VKConstants.WindowOS.VK_UP:
arrowKey = VKConstants.ArrowKey.VK_UP;
break;
case VKConstants.WindowOS.VK_LEFT:
arrowKey = VKConstants.ArrowKey.VK_LEFT;
break;
case VKConstants.WindowOS.VK_RIGHT:
arrowKey = VKConstants.ArrowKey.VK_RIGHT;
break;
}

if (arrowKey != null)
changeActiveSelector(arrowKey);
}

@Override
public String toString() {
String str = item.getTitle() + "\n";
List<Selector> selectors = item.getSelectors();
if (selectors.size() == 0)
return str;

if (item.getActivedSelector() == null)
item.setActivedSelector(item.getSelectors().get(0));

for (Selector selector : selectors) {
str += ConsoleUtils.printSelector(selector);
if (selectors.indexOf(selector) < selectors.size() - 1)
str += "\n";
}

return str;
}

@Override
public boolean onInput(NonBlockInputEvent e) {
int charCode = e.getAddedChar();
// System.out.println(charCode);
return handleInput(charCode, e);
}

@Override
public void onChanged(ChangeSelectorEvent e) {
ConsoleUtils.renderChoiceQuestion(this);
}

@Override
public void onChosen(ChooseSelectorEvent e) {
setAnswer(e.getSelector().getValue());
if (this.isPrintedResult()) ConsoleUtils.printResult(this);
}
}
@@ -0,0 +1,29 @@
package vn.locdt.jats.bundle.question.event;

import vn.locdt.jats.bundle.question.element.item.Selector;

public class ChangeSelectorEvent {
private Selector previousSelector;
private Selector chosenSelector;

public ChangeSelectorEvent(Selector previousSelector, Selector chosenSelector) {
this.previousSelector = previousSelector;
this.chosenSelector = chosenSelector;
}

public Selector getPreviousSelector() {
return previousSelector;
}

public void setPreviousSelector(Selector previousSelector) {
this.previousSelector = previousSelector;
}

public Selector getChosenSelector() {
return chosenSelector;
}

public void setChosenSelector(Selector chosenSelector) {
this.chosenSelector = chosenSelector;
}
}
@@ -0,0 +1,19 @@
package vn.locdt.jats.bundle.question.event;

import vn.locdt.jats.bundle.question.element.item.Selector;

public class ChooseSelectorEvent {
private Selector selector;

public ChooseSelectorEvent(Selector selector) {
this.selector = selector;
}

public Selector getSelector() {
return selector;
}

public void setSelector(Selector selector) {
this.selector = selector;
}
}
@@ -0,0 +1,16 @@
package vn.locdt.jats.bundle.question.event;

import vn.locdt.jats.bundle.question.element.question.Question;

public abstract class ConsoleEvent {
protected String value;
protected Question firedQuestion;

public String getValue() {
return value;
}

public Question getFiredQuestion() {
return firedQuestion;
}
}
@@ -0,0 +1,17 @@
package vn.locdt.jats.bundle.question.event;

public class InputEvent {
private String inputValue;

public InputEvent(String inputValue) {
this.inputValue = inputValue;
}

public String getInputValue() {
return inputValue;
}

public void setInputValue(String inputValue) {
this.inputValue = inputValue;
}
}
@@ -0,0 +1,23 @@
package vn.locdt.jats.bundle.question.event;

public class NonBlockInputEvent {
protected final int addedChar;

protected boolean stop;

public NonBlockInputEvent(int addedChar) {
this.addedChar = addedChar;
}

public int getAddedChar() {
return addedChar;
}

public void stop() {
stop = true;
}

public boolean isStop() {
return stop;
}
}
@@ -0,0 +1,10 @@
package vn.locdt.jats.bundle.question.exception;

/**
* Created by locdt on 1/10/2018.
*/
public class ConsoleNotInitializeException extends Exception {
public ConsoleNotInitializeException(String message) {
super(message);
}
}
@@ -0,0 +1,7 @@
package vn.locdt.jats.bundle.question.exception;

public class EmptySelectorListException extends Exception {
public EmptySelectorListException(String message) {
super(message);
}
}
@@ -0,0 +1,7 @@
package vn.locdt.jats.bundle.question.exception;

public class UndefinedQuestionException extends Exception {
public UndefinedQuestionException(String message) {
super(message);
}
}
@@ -0,0 +1,9 @@
package vn.locdt.jats.bundle.question.listener;

import vn.locdt.jats.bundle.question.event.ChooseSelectorEvent;
import vn.locdt.jats.bundle.question.event.ChangeSelectorEvent;

public interface ChoiceListener extends Listener{
void onChanged(ChangeSelectorEvent e);
void onChosen(ChooseSelectorEvent e);
}
@@ -0,0 +1,9 @@
package vn.locdt.jats.bundle.question.listener;

import vn.locdt.jats.bundle.question.answer.Answer;
import vn.locdt.jats.bundle.question.event.InputEvent;

@FunctionalInterface
public interface InputListener extends Listener {
Answer onInput(InputEvent e);
}
@@ -0,0 +1,4 @@
package vn.locdt.jats.bundle.question.listener;

public interface Listener {
}
@@ -0,0 +1,8 @@
package vn.locdt.jats.bundle.question.listener;

import vn.locdt.jats.bundle.question.event.NonBlockInputEvent;

@FunctionalInterface
public interface NonBlockInputListener extends Listener {
boolean onInput(NonBlockInputEvent e);
}
@@ -0,0 +1,41 @@
package vn.locdt.jats.bundle.question.util;

import vn.locdt.jats.bundle.question.element.question.SingleChoiceQuestion;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import vn.locdt.jats.bundle.question.element.question.Question;
import vn.locdt.jats.bundle.question.element.item.Item;
import vn.locdt.jats.bundle.question.element.item.Choice;
import vn.locdt.jats.bundle.question.element.item.Selector;

import static org.fusesource.jansi.Ansi.ansi;

public class ConsoleUtils {
private final static String OS_NAME = System.getProperty("os.name");

public static void renderChoiceQuestion(SingleChoiceQuestion singleChoiceQuestion) {
AnsiConsole.out.print(ansi().cursorUp(singleChoiceQuestion.getRenderHeight()).a("\r").eraseScreen(Ansi.Erase.FORWARD).fg(Ansi.Color.DEFAULT).a(singleChoiceQuestion.toString()).eraseScreen(Ansi.Erase.FORWARD).reset());
}

public static void renderQuestion(Question q) {
AnsiConsole.out.print(ansi().fg(Ansi.Color.DEFAULT).a(q));
}

public static String printSelector(Selector selector) {
Ansi.Color color = selector.getPrefix().equals(Choice.activedPrefix) ? Ansi.Color.CYAN : Ansi.Color.DEFAULT;
return selector.getPrefix() +
ansi().eraseScreen(Ansi.Erase.FORWARD).fg(color).a(selector.getValue()).reset().toString();
}

public static void printResult(Question inputQuestion) {
Item item = inputQuestion.getItem();
AnsiConsole.out.println(ansi().cursorUp(item.getRenderHeight()).a("\r").eraseScreen(Ansi.Erase.FORWARD)
.fg(Ansi.Color.DEFAULT).a(item.getTitle())
.fg(Ansi.Color.GREEN).a(" ("+inputQuestion.getAnswerValue()+")")
.eraseScreen(Ansi.Erase.FORWARD).reset());
}

public static boolean isWindowOS() {
return OS_NAME.startsWith("Windows");
}
}
@@ -0,0 +1,42 @@
package vn.locdt.jats.bundle.question.util;

import vn.locdt.jats.bundle.question.constant.VKConstants;

public class DetectArrowKey {
public static boolean detecting = false; //1: Up, 2: Down, 3: Left, 4: Right
private static int step = -1;
private static int[] arrowProcess = new int[]{27, 91};

public static void detect() {
DetectArrowKey.detecting = true;
DetectArrowKey.step = 0;
}

public static void reset() {
DetectArrowKey.detecting = false;
DetectArrowKey.step = -1;
}

public static VKConstants.ArrowKey update(int data) {
DetectArrowKey.step++;

if (DetectArrowKey.step == 2) {
reset();
switch (data) {
case 65:
return VKConstants.ArrowKey.VK_UP;
case 66:
return VKConstants.ArrowKey.VK_DOWN;
case 68:
return VKConstants.ArrowKey.VK_LEFT;
case 67:
return VKConstants.ArrowKey.VK_RIGHT;
}
}

if (arrowProcess[DetectArrowKey.step] != data)
reset();

return null;
}
}
@@ -0,0 +1,306 @@
// Copyright 2015 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
// www.source-code.biz, www.inventec.ch/chdh
//
// This module is multi-licensed and may be used under the terms of any of the following licenses:
//
// LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html
// EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal
//
// Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind.
//
// Home page: http://www.source-code.biz/snippets/java/RawConsoleInput

package vn.locdt.jats.bundle.question.util;

import com.sun.jna.*;
import com.sun.jna.ptr.IntByReference;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
import java.util.List;

/**
* A JNA based driver for reading single characters from the console.
*
* <p>This class is used for console mode programs.
* It supports non-blocking reads of single key strokes without echo.
*/
public class RawConsoleInput {

private static final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
private static final int invalidKey = 0xFFFE;
private static final String invalidKeyStr = String.valueOf((char)invalidKey);

private static boolean initDone;
private static boolean stdinIsConsole;
private static boolean consoleModeAltered;

/**
* Reads a character from the console without echo.
*
* @param wait
* <code>true</code> to wait until an input character is available,
* <code>false</code> to return immediately if no character is available.
* @return
* -2 if <code>wait</code> is <code>false</code> and no character is available.
* -1 on EOF.
* Otherwise an Unicode character code within the range 0 to 0xFFFF.
*/
public static int read (boolean wait) throws IOException {
if (isWindows) {
return readWindows(wait); }
else {
return readUnix(wait); }}

/**
* Resets console mode to normal line mode with echo.
*
* <p>On Windows this method re-enables Ctrl-C processing.
*
* <p>On Unix this method switches the console back to echo mode.
* read() leaves the console in non-echo mode.
*/
public static void resetConsoleMode() throws IOException {
if (isWindows) {
resetConsoleModeWindows(); }
else {
resetConsoleModeUnix(); }}

private static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
shutdownHook(); }}); }

private static void shutdownHook() {
try {
resetConsoleMode(); }
catch (Exception e) {}}

//--- Windows ------------------------------------------------------------------

// The Windows version uses _kbhit() and _getwch() from msvcrt.dll.

private static Msvcrt msvcrt;
private static Kernel32 kernel32;
private static Pointer consoleHandle;
private static int originalConsoleMode;

private static int readWindows (boolean wait) throws IOException {
initWindows();
if (!stdinIsConsole) {
int c = msvcrt.getwchar();
if (c == 0xFFFF) {
c = -1; }
return c; }
consoleModeAltered = true;
setConsoleMode(consoleHandle, originalConsoleMode & ~Kernel32Defs.ENABLE_PROCESSED_INPUT);
// ENABLE_PROCESSED_INPUT must remain off to prevent Ctrl-C from beeing processed by the system
// while the program is not within getwch().
if (!wait && msvcrt._kbhit() == 0) {
return -2; } // no key available
return getwch(); }

private static int getwch() {
int c = msvcrt._getwch();
if (c == 0 || c == 0xE0) { // Function key or arrow key
c = msvcrt._getwch();
// System.out.println("Function key or arrow key: " + c);
if (c >= 0 && c <= 0x18FF) {
return 0xE000 + c; } // construct key code in private Unicode range
return invalidKey; }
if (c < 0 || c > 0xFFFF) {
return invalidKey; }
return c; } // normal key

private static synchronized void initWindows() throws IOException {
if (initDone) {
return; }
msvcrt = (Msvcrt) Native.loadLibrary("msvcrt", Msvcrt.class);
kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
try {
consoleHandle = getStdInputHandle();
originalConsoleMode = getConsoleMode(consoleHandle);
stdinIsConsole = true; }
catch (IOException e) {
stdinIsConsole = false; }
if (stdinIsConsole) {
registerShutdownHook(); }
initDone = true; }

private static Pointer getStdInputHandle() throws IOException {
Pointer handle = kernel32.GetStdHandle(Kernel32Defs.STD_INPUT_HANDLE);
if (Pointer.nativeValue(handle) == 0 || Pointer.nativeValue(handle) == Kernel32Defs.INVALID_HANDLE_VALUE) {
throw new IOException("GetStdHandle(STD_INPUT_HANDLE) failed."); }
return handle; }

private static int getConsoleMode (Pointer handle) throws IOException {
IntByReference mode = new IntByReference();
int rc = kernel32.GetConsoleMode(handle, mode);
if (rc == 0) {
throw new IOException("GetConsoleMode() failed."); }
return mode.getValue(); }

private static void setConsoleMode (Pointer handle, int mode) throws IOException {
int rc = kernel32.SetConsoleMode(handle, mode);
if (rc == 0) {
throw new IOException("SetConsoleMode() failed."); }}

private static void resetConsoleModeWindows() throws IOException {
if (!initDone || !stdinIsConsole || !consoleModeAltered) {
return; }
setConsoleMode(consoleHandle, originalConsoleMode);
consoleModeAltered = false; }

private static interface Msvcrt extends Library {
int _kbhit();
int _getwch();
int getwchar(); }

private static class Kernel32Defs {
static final int STD_INPUT_HANDLE = -10;
static final long INVALID_HANDLE_VALUE = (Pointer.SIZE == 8) ? -1 : 0xFFFFFFFFL;
static final int ENABLE_PROCESSED_INPUT = 0x0001;
static final int ENABLE_LINE_INPUT = 0x0002;
static final int ENABLE_ECHO_INPUT = 0x0004;
static final int ENABLE_WINDOW_INPUT = 0x0008; }

private static interface Kernel32 extends Library {
int GetConsoleMode(Pointer hConsoleHandle, IntByReference lpMode);
int SetConsoleMode(Pointer hConsoleHandle, int dwMode);
Pointer GetStdHandle(int nStdHandle); }

//--- Unix ---------------------------------------------------------------------

// The Unix version uses tcsetattr() to switch the console to non-canonical mode,
// System.in.available() to check whether data is available and System.in.read()
// to read bytes from the console.
// A CharsetDecoder is used to convert bytes to characters.

private static final int stdinFd = 0;
private static Libc libc;
private static CharsetDecoder charsetDecoder;
private static Termios originalTermios;
private static Termios rawTermios;
private static Termios intermediateTermios;

private static int readUnix (boolean wait) throws IOException {
initUnix();
if (!stdinIsConsole) { // STDIN is not a console
return readSingleCharFromByteStream(System.in); }
consoleModeAltered = true;
setTerminalAttrs(stdinFd, rawTermios); // switch off canonical mode, echo and signals
try {
if (!wait && System.in.available() == 0) {
return -2; } // no input available
return readSingleCharFromByteStream(System.in); }
finally {
setTerminalAttrs(stdinFd, intermediateTermios); }} // reset some console attributes

private static Termios getTerminalAttrs (int fd) throws IOException {
Termios termios = new Termios();
try {
int rc = libc.tcgetattr(fd, termios);
if (rc != 0) {
throw new RuntimeException("tcgetattr() failed."); }}
catch (LastErrorException e) {
throw new IOException("tcgetattr() failed.", e); }
return termios; }

private static void setTerminalAttrs (int fd, Termios termios) throws IOException {
try {
int rc = libc.tcsetattr(fd, LibcDefs.TCSANOW, termios);
if (rc != 0) {
throw new RuntimeException("tcsetattr() failed."); }}
catch (LastErrorException e) {
throw new IOException("tcsetattr() failed.", e); }}

private static int readSingleCharFromByteStream (InputStream inputStream) throws IOException {
byte[] inBuf = new byte[4];
int inLen = 0;
while (true) {
if (inLen >= inBuf.length) { // input buffer overflow
return invalidKey; }
int b = inputStream.read(); // read next byte
if (b == -1) { // EOF
return -1; }
inBuf[inLen++] = (byte)b;
int c = decodeCharFromBytes(inBuf, inLen);
if (c != -1) {
return c; }}}

// (This method is synchronized because the charsetDecoder must only be used by a single thread at once.)
private static synchronized int decodeCharFromBytes (byte[] inBytes, int inLen) {
charsetDecoder.reset();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE);
charsetDecoder.replaceWith(invalidKeyStr);
ByteBuffer in = ByteBuffer.wrap(inBytes, 0, inLen);
CharBuffer out = CharBuffer.allocate(1);
charsetDecoder.decode(in, out, false);
if (out.position() == 0) {
return -1; }
return out.get(0); }

private static synchronized void initUnix() throws IOException {
if (initDone) {
return; }
libc = (Libc) Native.loadLibrary("c", Libc.class);
stdinIsConsole = libc.isatty(stdinFd) == 1;
charsetDecoder = Charset.defaultCharset().newDecoder();
if (stdinIsConsole) {
originalTermios = getTerminalAttrs(stdinFd);
rawTermios = new Termios(originalTermios);
rawTermios.c_lflag &= ~(LibcDefs.ICANON | LibcDefs.ECHO | LibcDefs.ECHONL | LibcDefs.ISIG);
intermediateTermios = new Termios(rawTermios);
intermediateTermios.c_lflag |= LibcDefs.ICANON;
// Canonical mode can be switched off between the read() calls, but echo must remain disabled.
registerShutdownHook(); }
initDone = true; }

private static void resetConsoleModeUnix() throws IOException {
if (!initDone || !stdinIsConsole || !consoleModeAltered) {
return; }
setTerminalAttrs(stdinFd, originalTermios);
consoleModeAltered = false; }

protected static class Termios extends Structure { // termios.h
public int c_iflag;
public int c_oflag;
public int c_cflag;
public int c_lflag;
public byte c_line;
public byte[] filler = new byte[64]; // actual length is platform dependent
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("c_iflag", "c_oflag", "c_cflag", "c_lflag", "c_line", "filler"); }
Termios() {}
Termios (Termios t) {
c_iflag = t.c_iflag;
c_oflag = t.c_oflag;
c_cflag = t.c_cflag;
c_lflag = t.c_lflag;
c_line = t.c_line;
filler = t.filler.clone(); }}

private static class LibcDefs {
// termios.h
static final int ISIG = 0000001;
static final int ICANON = 0000002;
static final int ECHO = 0000010;
static final int ECHONL = 0000100;
static final int TCSANOW = 0; }

private static interface Libc extends Library {
// termios.h
int tcgetattr(int fd, Termios termios) throws LastErrorException;
int tcsetattr(int fd, int opt, Termios termios) throws LastErrorException;
// unistd.h
int isatty(int fd); }

}
File renamed without changes.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

@@ -7,7 +7,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>core</artifactId>
<name>JATS-Addon: Core Module</name>
<name>JATS-Core: Core Module</name>
<build>
<finalName>jats</finalName>
<plugins>
@@ -47,7 +47,7 @@
<transformer>
<manifestEntries>
<Implementation-Version>${app.version}</Implementation-Version>
<Main-Class>vn.locdt.jats.core.shell.MainShell</Main-Class>
<Main-Class>vn.locdt.jats.core.Main</Main-Class>
</manifestEntries>
</transformer>
</transformers>
File renamed without changes.
Empty file.
@@ -9,7 +9,7 @@
<version>1.0.0</version>
</parent>
<artifactId>core</artifactId>
<name>JATS-Core: Core Module</name>
<name>JATS-Core: Core</name>
<packaging>jar</packaging>

<properties>
@@ -30,29 +30,15 @@
<!--</repositories>-->

<dependencies>
<!--<dependency>-->
<!--<groupId>oracle</groupId>-->
<!--<artifactId>ojdbc7</artifactId>-->
<!--<version>12.1.0</version>-->
<!--</dependency>-->

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->

<dependency>
<groupId>vn.locdt.jats</groupId>
<artifactId>bundle.question</artifactId>
<version>1.0.0</version>
</dependency>

<dependency>
<groupId>vn.locdt.jats</groupId>
<artifactId>addon.entity.modeling</artifactId>
<artifactId>module.shell</artifactId>
<version>1.0.0</version>
</dependency>

<dependency>
<groupId>vn.locdt.jats</groupId>
<artifactId>addon.entity.generator</artifactId>
<artifactId>entity.addon</artifactId>
<version>1.0.0</version>
</dependency>

@@ -97,6 +83,8 @@
<goal>shade</goal>
</goals>
<configuration>
<finalName>jats-${project.version}</finalName>
<outputDirectory>../build</outputDirectory>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
@@ -108,7 +96,7 @@
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Implementation-Version>${app.version}</Implementation-Version>
<Main-Class>vn.locdt.jats.core.shell.MainShell</Main-Class>
<Main-Class>vn.locdt.jats.core.Main</Main-Class>
</manifestEntries>
</transformer>
</transformers>
@@ -1,15 +1,16 @@
package vn.locdt.jats.core.shell;
package vn.locdt.jats.core;

import org.springframework.shell.Bootstrap;
import org.springframework.shell.core.JLineShell;
import org.springframework.shell.event.AbstractShellStatusPublisher;
import vn.locdt.jats.core.shell.listener.AppShellStatusListener;
import vn.locdt.jats.module.shell.listener.AppShellStatusListener;

import java.util.logging.LogManager;

/**
* Created by locdt on 1/25/2018.
*/
public class MainShell {
public class Main {
/**
* Main entry-point of the application.
*
@@ -6,5 +6,5 @@
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="vn.locdt.jats.core" />
<context:component-scan base-package="vn.locdt.jats" />
</beans>
File renamed without changes.
File renamed without changes.
File renamed without changes.

This file was deleted.

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jats</artifactId>
<groupId>vn.locdt.jats</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>module.shell</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>vn.locdt.jats</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>vn.locdt.jats</groupId>
<artifactId>bundle.question</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,154 @@
package vn.locdt.jats.module.shell.command;

import org.springframework.shell.core.annotation.CliOption;
import vn.locdt.jats.module.shell.exception.CliOptionQuestionNotMapping;
import vn.locdt.jats.module.shell.exception.QuestionDeclareNotConsistent;
import vn.locdt.jats.module.shell.question.annotation.QuestionImports;
import vn.locdt.jats.module.shell.question.QuestionStatus;
import vn.locdt.jats.module.shell.question.QuestionCLI;
import vn.locdt.jats.module.shell.question.annotation.QuestionCliOption;
import vn.locdt.jats.module.shell.setting.SettingData;
import vn.locdt.jats.util.LogUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

/**
* Created by locdt on 1/22/2018.
*/
public abstract class QuestionCommand {
protected final static String SHELL_COMMAND_JAVA_METHOD = "runCommand";
private Map<QuestionCLI, CliOptionValue> questionOptsMap;

public QuestionCommand() {
this.questionOptsMap = new HashMap<>();
}

public QuestionStatus startQuestions() {
QuestionStatus status = QuestionStatus.FINISHED;
try {
List<QuestionCLI> questions = getImportedQuestionList();

if (questionOptsMap.size() > questions.size())
throw new QuestionDeclareNotConsistent("Found " + questionOptsMap.size() + " mapped but " + questions.size() + " imported.");

for (QuestionCLI q : questions) {
CliOptionValue optionValue = questionOptsMap.get(q);
if (optionValue != null && optionValue.getValue() != null) {
q.start();
LogUtils.printDebugLog("Class: " + q.getClass().getCanonicalName() + " | Status: " + status.name());
if (QuestionStatus.STOP.equals(status))
break;
}
else {
LogUtils.printDebugLog("Skipping " + q.getClass().getCanonicalName());
}
}
} catch (Exception e) {
LogUtils.printErrorLog("Error occurs when run questions", e);
status = QuestionStatus.STOP;
}

if (QuestionStatus.FINISHED.equals(status))
SettingData.save();

return status;
}

private List<QuestionCLI> getImportedQuestionList() {
List<QuestionCLI> qs = new ArrayList<>();
try {
Class[] classes = getImportedQuestionClasses();
LogUtils.printDebugLog(classes.length);
for (Class c : classes) {
Constructor constructor = c.getConstructor();
qs.add((QuestionCLI) constructor.newInstance());
}
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<>();
}
return qs;
}

private Class<?>[] getImportedQuestionClasses() throws Exception{
for (Annotation a: getClass().getAnnotations()) {
if (a.getClass().equals(QuestionImports.class))
return (Class<?>[]) a.getClass().getMethod("value").invoke(a);
}
return new Class<?>[]{};
}

protected void resolveOptionValues(String... values) throws CliOptionQuestionNotMapping {
try {
Method[] methods = getClass().getMethods();
Method runCommandMethod = Arrays.stream(methods)
.filter(m -> SHELL_COMMAND_JAVA_METHOD.equals(m.getName()))
.findFirst().orElse(null);

if (runCommandMethod == null)
return;

Parameter[] parameters = runCommandMethod.getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter p = parameters[i];
Class clazz = getQuestionOfParameter(p);
if (clazz == null)
throw new CliOptionQuestionNotMapping("Could not found any question mapped to " + p.getName());

QuestionCLI question = (QuestionCLI) clazz.getConstructor().newInstance();
String[] options = getCliOptionOfParameter(p);

CliOptionValue optionValue = new CliOptionValue(options, values[i]);
questionOptsMap.put(question, optionValue);
}
} catch (Exception e) {
e.printStackTrace();
}
}

private String[] getCliOptionOfParameter(Parameter p) {
CliOption option = p.getAnnotation(CliOption.class);
if (option != null) {
return option.key();
}
return null;
}

private Class getQuestionOfParameter(Parameter p) {
QuestionCliOption option = p.getAnnotation(QuestionCliOption.class);
if (option != null) {
return option.value();
}
return null;
}

public class CliOptionValue {
private String[] keys;
private String value;

public CliOptionValue(String[] keys, String value) {
this.keys = keys;
this.value = value;
}

public String[] getKeys() {
return keys;
}

public void setKeys(String[] keys) {
this.keys = keys;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}
}
@@ -0,0 +1,42 @@
package vn.locdt.jats.module.shell.constants;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
* Created by locdt on 1/21/2018.
*/
public class Constants {
public static final String SHELL_PROMPT = "jats";
public enum DBType {
MYSQL("MySQL", "com.mysql.jdbc.Driver"),
ORACLE("Oracle", "oracle.jdbc.driver.OracleDriver");
private String type;
private String driver;
DBType(String type, String driver) {
this.type = type;
this.driver = driver;
}
private static Map<String, DBType> lookup = new HashMap<>();
static {
for (DBType type : DBType.values()) lookup.put(type.getType(), type);
}

public String getType() {return this.type;}
public String getDriver() {return this.driver;}
public String toString() {
return this.type;
}

public static DBType enumOf(String type) {
return lookup.get(type);
}

public static String[] getTypes() {
return Arrays.stream(DBType.values()).map(DBType::getType).toArray(String[]::new);
}
}


}
@@ -0,0 +1,13 @@
package vn.locdt.jats.module.shell.constants;

/**
* Created by locdt on 1/23/2018.
*/
public class PropertiesConstants {
public static String ROOTPACKAGE = "rootPackage";
public static String DBTYPE = "dbType";
public static String DBURL = "dbUrl";
public static String DBUSER = "dbUser";
public static String DBPASS = "dbPass";

}
@@ -0,0 +1,11 @@
package vn.locdt.jats.module.shell.exception;

public class CliOptionQuestionNotMapping extends RuntimeException {
public CliOptionQuestionNotMapping(String message) {
super(message);
}

public CliOptionQuestionNotMapping(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,10 @@
package vn.locdt.jats.module.shell.exception;

/**
* Created by locdt on 1/21/2018.
*/
public class ConnectionNotInitilizeException extends Exception {
public ConnectionNotInitilizeException() {
super();
}
}
@@ -0,0 +1,11 @@
package vn.locdt.jats.module.shell.exception;

public class QuestionDeclareNotConsistent extends RuntimeException {
public QuestionDeclareNotConsistent(String message) {
super(message);
}

public QuestionDeclareNotConsistent(String message, Throwable cause) {
super(message, cause);
}
}
@@ -1,9 +1,9 @@
package vn.locdt.jats.core.shell.listener;
package vn.locdt.jats.module.shell.listener;

import org.springframework.shell.event.ShellStatus;
import org.springframework.shell.event.ShellStatusListener;
import org.springframework.stereotype.Component;
import vn.locdt.jats.core.setting.SettingData;
import vn.locdt.jats.module.shell.setting.SettingData;

/**
* Created by locdt on 1/27/2018.
@@ -14,7 +14,7 @@
* limitations under the License.
*/

package vn.locdt.jats.core.shell.provider;
package vn.locdt.jats.module.shell.provider;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
@@ -32,16 +32,24 @@ public class AppBannerProvider extends DefaultBannerProvider {

public String getBanner() {
StringBuffer buf = new StringBuffer();
buf.append( "\n" +
" ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n" +
" ░░ ██ ██████ ██████ ██████░░\n" +
" ░░ ██ ██ ██ ██ ██ ░░\n" +
" ░░ ██ ██████ ██ █████ ░░\n" +
" ░░██ ██ ██ ██ ██ ██░░\n" +
" ░░ █████ ██ ██ ██ ██████ ░░\n" +
" ░░ ░░\n" +
" ░░ -----* Welcome to JATS *----- ░░\n" +
" ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n");
// buf.append(OsUtils.LINE_SEPARATOR);
// buf.append("▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄").append(OsUtils.LINE_SEPARATOR);
// buf.append(" _ _ ____ _____").append(OsUtils.LINE_SEPARATOR);
// buf.append(" | | / \\ / ___|_ _|").append(OsUtils.LINE_SEPARATOR);
// buf.append(" _ | |/ _ \\ \\\\___ | |").append(OsUtils.LINE_SEPARATOR);
// buf.append(" | |_| / ___ \\ ___)| | |").append(OsUtils.LINE_SEPARATOR);
// buf.append(" \\___/_/ \\_|____/ |_|").append(OsUtils.LINE_SEPARATOR);
buf.append(OsUtils.LINE_SEPARATOR);
buf.append("▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄").append(OsUtils.LINE_SEPARATOR);
buf.append(" _ _ ____ _____").append(OsUtils.LINE_SEPARATOR);
buf.append(" | | / \\ / ___|_ _|").append(OsUtils.LINE_SEPARATOR);
buf.append(" _ | |/ _ \\ \\\\___ | |").append(OsUtils.LINE_SEPARATOR);
buf.append(" | |_| / ___ \\ ___)| | |").append(OsUtils.LINE_SEPARATOR);
buf.append(" \\___/_/ \\_|____/ |_|").append(OsUtils.LINE_SEPARATOR);
buf.append(OsUtils.LINE_SEPARATOR);
buf.append(" * Welcome to JATS - Java Assistant Tools *").append(OsUtils.LINE_SEPARATOR);
buf.append("▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀").append(OsUtils.LINE_SEPARATOR);
buf.append(" (For assistance type \"hint\" then hit ENTER)").append(OsUtils.LINE_SEPARATOR);
return buf.toString();

@@ -14,14 +14,16 @@
* limitations under the License.
*/

package vn.locdt.jats.core.shell.provider;
package vn.locdt.jats.module.shell.provider;

import org.fusesource.jansi.Ansi;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.shell.plugin.support.DefaultPromptProvider;
import org.springframework.stereotype.Component;
import vn.locdt.jats.module.shell.constants.Constants;

import static vn.locdt.jats.core.constants.Constants.SHELL_PROMPT;
import static org.fusesource.jansi.Ansi.ansi;

/**
* Provider responsible for defining the shell prompt.
@@ -32,7 +34,7 @@ public class AppPromptProvider extends DefaultPromptProvider {

@Override
public String getPrompt() {
return SHELL_PROMPT + "> ";
return ansi().fg(Ansi.Color.MAGENTA).a(Constants.SHELL_PROMPT + "> ").toString();
}

@Override
@@ -0,0 +1,22 @@
package vn.locdt.jats.module.shell.question;

/**
* Created by locdt on 1/21/2018.
*/
public abstract class QuestionCLI {
public QuestionCLI() {}

protected abstract QuestionStatus preQuestion();
protected abstract QuestionStatus postQuestion();
protected abstract QuestionStatus run();

public QuestionStatus start() {
QuestionStatus status = preQuestion();
if (status == QuestionStatus.CONTINUE) {
status = run();
if (status == QuestionStatus.CONTINUE)
status = postQuestion();
}
return status;
}
}
@@ -0,0 +1,10 @@
package vn.locdt.jats.module.shell.question;

/**
* Created by locdt on 1/27/2018.
*/
public enum QuestionStatus {
CONTINUE,
FINISHED,
STOP
}
@@ -0,0 +1,13 @@
package vn.locdt.jats.module.shell.question.annotation;

import org.springframework.shell.core.annotation.CliOption;

import java.lang.annotation.*;

@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface QuestionCliOption {
Class value();
}
@@ -0,0 +1,14 @@
package vn.locdt.jats.module.shell.question.annotation;

import java.lang.annotation.*;

/**
* Created by locdt on 1/27/2018.
*/

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface QuestionImports {
Class<?>[] value();
}
@@ -0,0 +1,32 @@
package vn.locdt.jats.module.shell.question.init;

import vn.locdt.jats.bundle.question.JQuestion;
import vn.locdt.jats.module.shell.question.QuestionCLI;
import vn.locdt.jats.module.shell.question.QuestionStatus;
import vn.locdt.jats.module.shell.setting.SettingData;

/**
* Created by locdt on 1/26/2018.
*/
public class RootPackageQuestion extends QuestionCLI {
@Override
protected QuestionStatus preQuestion() {
return QuestionStatus.CONTINUE;
}

@Override
protected QuestionStatus postQuestion() {
return QuestionStatus.FINISHED;
}

@Override
protected QuestionStatus run() {
askForRootPackage();
return QuestionStatus.CONTINUE;
}

private void askForRootPackage() {
String rootPackage = JQuestion.input("Your root package:", "rootPackage").getValue();
SettingData.getProjectSetting().setRootPackage(rootPackage);
}
}
@@ -1,8 +1,8 @@
package vn.locdt.jats.core.setting;
package vn.locdt.jats.module.shell.setting;

import vn.locdt.jats.core.constants.Constants;
import vn.locdt.jats.core.constants.PropertiesConstants;
import vn.locdt.jats.core.util.Utils;
import vn.locdt.jats.module.shell.constants.Constants;
import vn.locdt.jats.module.shell.constants.PropertiesConstants;
import vn.locdt.jats.util.LogUtils;

import java.sql.Connection;
import java.sql.DriverManager;
@@ -64,26 +64,26 @@ public boolean loadDriver(String type) {
try {
if (dbType.getType().equals(type)) {
Class.forName(dbType.getDriver());
Utils.printLog(dbType.getType() + " Driver Loaded...");
LogUtils.printLog(dbType.getType() + " Driver Loaded...");
this.setDbType(type);
return true;
}
} catch (ClassNotFoundException e) {
Utils.printErrorLog(dbType.getType() + " Driver Not Found...");
LogUtils.printErrorLog(dbType.getType() + " Driver Not Found...");
}
}
return false;
}

public boolean createConnection(){
try {
Utils.printLog("Establish connection...");
LogUtils.printLog("Establish connection...");
this.connection = DriverManager.getConnection(dbUrl, dbUser, dbPass);
Utils.printSuccessLog("Connecting successfully!");
LogUtils.printSuccessLog("Connecting successfully!");
return true;
} catch (Exception e) {
// e.printStackTrace();
Utils.printErrorLog("Connecting unsuccessfully", e.getMessage());
LogUtils.printErrorLog("Connecting unsuccessfully", e.getMessage());
}
return false;
}
@@ -1,6 +1,6 @@
package vn.locdt.jats.core.setting;
package vn.locdt.jats.module.shell.setting;

import vn.locdt.jats.core.constants.PropertiesConstants;
import vn.locdt.jats.module.shell.constants.PropertiesConstants;

import java.util.Properties;

@@ -1,4 +1,4 @@
package vn.locdt.jats.core.setting;
package vn.locdt.jats.module.shell.setting;

/**
* Created by locdt on 1/21/2018.
@@ -1,7 +1,8 @@
package vn.locdt.jats.core.setting;
package vn.locdt.jats.module.shell.setting;

import vn.locdt.jats.core.constants.PropertiesConstants;
import vn.locdt.jats.core.util.Utils;
import vn.locdt.jats.module.shell.constants.PropertiesConstants;
import vn.locdt.jats.util.FileUtils;
import vn.locdt.jats.util.LogUtils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -35,22 +36,23 @@ public static DatabaseSetting getDatabaseSetting() {

public static void loadConfiguration() {
Properties properties = getConfigProperties();
Utils.printDebugLog(properties);
LogUtils.printDebugLog(properties);
if (properties != null) {
Utils.printLog("Loading last run setting...");
LogUtils.printLog("Loading last run setting...");
dbSetting = new DatabaseSetting(properties);
projectSetting = new ProjectSetting(properties);

boolean loaded = dbSetting.loadDriver(dbSetting.getDbType());
if (!loaded) return;
dbSetting.createConnection();
LogUtils.printLog("Load successfully!");
}
}

private static Properties getConfigProperties() {
Properties properties = new Properties();
Utils.printDebugLog(Utils.getConfigurationPath());
try (InputStream input = new FileInputStream(Utils.getConfigurationPath())) {
LogUtils.printDebugLog(FileUtils.getConfigurationPath());
try (InputStream input = new FileInputStream(FileUtils.getConfigurationPath())) {
// load a properties file
properties.load(input);
return properties;
@@ -70,9 +72,9 @@ public static void save() {
setProperty(PropertiesConstants.DBUSER, dbSetting.getDbUser());
setProperty(PropertiesConstants.DBPASS, dbSetting.getDbPass());

properties.store(new FileOutputStream(Utils.getConfigurationPath()), null);
properties.store(new FileOutputStream(FileUtils.getConfigurationPath()), null);
} catch (IOException e) {
Utils.printErrorLog("Error when saving configuration setting.");
LogUtils.printErrorLog("Error when saving configuration setting.");
}
}

@@ -0,0 +1 @@
sdasdasdasd
@@ -0,0 +1,101 @@
package output.generator;

import javax.persistence.GeneratedValue;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Id;
import output.generator.Thesis;
import javax.persistence.GenerationType;

@Entity
@Table(name="thesis_revision")
public class ThesisRevision {
private Integer revisionId;
private Thesis thesis;
private String title;
private String description;
private Integer firstSupervisorId;
private Integer secondSupervisorId;
private Integer firstSupervisorAccepted;
private Integer secondSupervisorAccepted;


@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = "revision_id")
public Integer getInteger() {
return revisionId;
}

public void setInteger(Integer revisionId){
this.revisionId = revisionId;
}

@Column(name = "thesis_id")
public Integer getInteger() {
return thesisId;
}

public void setInteger(Integer thesisId){
this.thesisId = thesisId;
}

@Column(name = "title")
public String getString() {
return title;
}

public void setString(String title){
this.title = title;
}

@Column(name = "description")
public String getString() {
return description;
}

public void setString(String description){
this.description = description;
}

@Column(name = "first_supervisor_id")
public Integer getInteger() {
return firstSupervisorId;
}

public void setInteger(Integer firstSupervisorId){
this.firstSupervisorId = firstSupervisorId;
}

@Column(name = "second_supervisor_id")
public Integer getInteger() {
return secondSupervisorId;
}

public void setInteger(Integer secondSupervisorId){
this.secondSupervisorId = secondSupervisorId;
}

@Column(name = "first_supervisor_accepted")
public Integer getInteger() {
return firstSupervisorAccepted;
}

public void setInteger(Integer firstSupervisorAccepted){
this.firstSupervisorAccepted = firstSupervisorAccepted;
}

@Column(name = "second_supervisor_accepted")
public Integer getInteger() {
return secondSupervisorAccepted;
}

public void setInteger(Integer secondSupervisorAccepted){
this.secondSupervisorAccepted = secondSupervisorAccepted;
}
}


23 pom.xml
@@ -11,9 +11,18 @@
<packaging>pom</packaging>

<modules>
<module>core-module</module>
<!-- Core Modules-->
<module>core</module>
<module>util</module>

<!-- Bundle Modules-->
<module>bundle-question</module>

<!-- Main Modules-->
<module>module-shell</module>

<!-- Addon Modules-->
<module>addon-entity-generation</module>
<module>terminal-question</module>
</modules>

<dependencies>
@@ -61,11 +70,11 @@
<version>2.3</version>
</dependency>

<dependency>
<groupId>org.apache.ddlutils</groupId>
<artifactId>ddlutils</artifactId>
<version>1.0</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.apache.ddlutils</groupId>-->
<!--<artifactId>ddlutils</artifactId>-->
<!--<version>1.0</version>-->
<!--</dependency>-->

<dependency>
<groupId>net.java.dev.jna</groupId>
@@ -0,0 +1,98 @@
package vn.locdt.jats.addon.entity.model;

import javax.persistence.*;

/**
* Created by dinht_000 on 10/29/2016.
* Created by cuong on 10/30/2016.
*/
@Entity
@Table(name = "admin")
public class Admin {

private int adminId;
private User user;
private String name;

/**
* Lấy id của admin
* @return id id của admin
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "admin_id")
public int getAdminId() {
return adminId;
}

/**
* Đặt id cho admin
* @param adminId id truyền vào
*/
public void setAdminId(int adminId) {
this.adminId = adminId;
}

/**
* Lấy user của admin
* @return đối tượng user mà admin sở hữu
*/
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
public User getUser() {
return user;
}

/**
* Đặt user cho admin
* @param user đối trượng user truyền vào
*/
public void setUser(User user) {
this.user = user;
}

/**
* Lấy tên của admin
* @return tên admin
*/
@Basic
@Column(name = "name")
public String getName() {
return name;
}

/**
* Đặt tên cho admin
* @param name tên admin
*/
public void setName(String name) {
this.name = name;
}

/**
* Kiểm tra hai admin có giống nhau hay không
* @param o
* @return true/false
*/
@Override
public boolean equals(Object o) {

if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Admin admin = (Admin) o;

if (name != null ? !name.equals(admin.name) : admin.name != null) return false;

return true;
}

/**
* Lấy mã băm của tên admin
* @return mã băm của tên admin
*/
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
}
@@ -0,0 +1,77 @@
package vn.locdt.jats.addon.entity.model;

import com.fasterxml.jackson.annotation.JsonProperty;

import javax.persistence.*;

/**
* Created by dinht_000 on 10/29/2016.
*/
@Entity
@Table(name = "class")
public class Class {

@JsonProperty("class_id")
private int classId; // id của class

@JsonProperty("name")
private String name; // tên của class

@JsonProperty("faculty")
private Faculty faculty;

/**
* Lấy khoa quản lý
* @return khoa
*/
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "faculty_id")
public Faculty getFaculty() {
return faculty;
}

/**
* Đặt khoa quản lý
* @param faculty đối tượng khoa
*/
public void setFaculty(Faculty faculty) {
this.faculty = faculty;
}

/**
* Lấy id của lớp
* @return id của lớp
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "class_id")
public int getClassId() {
return classId;
}

/**
* Đặt id cho class
* @param classId id của class
*/
public void setClassId(int classId) {
this.classId = classId;
}

/**
* Lấy tên của class
* @return tên class
*/
@Basic
@Column(name = "name")
public String getName() {
return name;
}

/**
* Đặt tên cho class
* @param name tên của class
*/
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,116 @@
package vn.locdt.jats.addon.entity.model;

import com.fasterxml.jackson.annotation.JsonProperty;

import javax.persistence.*;
import java.util.List;
import java.util.Queue;
import java.util.Set;

/**
* Created by dinht_000 on 12/13/2016.
*/
@Entity
@Table(name = "council")
public class Council {
@JsonProperty("council_id")
private int councilId;

@JsonProperty("council_name")
private String councilName;

@JsonProperty("president")
private Supervisor president;

@JsonProperty("secretary")
private Supervisor secretary;

@JsonProperty("reviewer")
private Set<Supervisor> reviewers;

@JsonProperty("location")
private String location;

@JsonProperty("thesis")
private List<Thesis> theses;

@Basic
@Column(name = "location")
public String getLocation() {
return location;
}

public void setLocation(String location) {
this.location = location;
}

@Transient
public List<Thesis> getTheses() {
return theses;
}

public void setTheses(List<Thesis> theses) {
this.theses = theses;
}

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "council_id")
public int getCouncilId() {
return councilId;
}

public void setCouncilId(int councilId) {
this.councilId = councilId;
}

@Basic
@Column(name = "council_name")
public String getCouncilName() {
return councilName;
}

public void setCouncilName(String councilName) {
this.councilName = councilName;
}

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "president_id")
public Supervisor getPresident() {
return president;
}

public void setPresident(Supervisor president) {
this.president = president;
}

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "secretary_id")
public Supervisor getSecretary() {
return secretary;
}

public void setSecretary(Supervisor secretary) {
this.secretary = secretary;
}

@OneToMany(mappedBy = "council", fetch = FetchType.EAGER)
public Set<Supervisor> getReviewers() {
return reviewers;
}

public void setReviewers(Set<Supervisor> reviewers) {
this.reviewers = reviewers;
}

@Override
public String toString() {
return "Council{" +
"councilId=" + councilId +
", councilName='" + councilName + '\'' +
", president=" + president +
", secretary=" + secretary +
", reviewer=" + reviewers +
'}';
}
}
@@ -0,0 +1,119 @@
package vn.locdt.jats.addon.entity.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.persistence.*;

/**
* Created by cuong on 10/24/2016.
*/
@Entity
@Table(name = "department")
public class Department {

@JsonProperty("id")
private int departmentId; // id của department

@JsonProperty("name")
private String name; // tên của department

@JsonProperty("faculty")
private Faculty faculty; // faculty của department

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "department_id")

/**
* Lấy id của khoa
* @return departmentId id của khoa
*/
public int getDepartmentId() {
return departmentId;
}

/**
* Đặt Id cho khoa
* @param departmentId id cho khoa
*/
public void setDepartmentId(int departmentId) {
this.departmentId = departmentId;
}

@Basic
@Column(name = "name")

/**
* Lấy tên của khoa
* @return name tên khoa
*/
public String getName() {
return name;
}

/**
* Đặt tên cho khoa
* @param name tên khoa
*/
public void setName(String name) {
this.name = name;
}

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "faculty_id")

/**
* Lấy giảng viên của khoa
* @return giảng viên
*/
public Faculty getFaculty() {
return faculty;
}

/**
* Đặt giảng viên cho khoa
* @param faculty giảng viên
*/
public void setFaculty(Faculty faculty) {
this.faculty = faculty;
}

/**
* Kiểm tra hai đối tượng khoa có giống nhau hay không
* @param o
* @return true/false
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Department that = (Department) o;

if (departmentId != that.departmentId) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;

return true;
}

/**
* Lấy mã băm của id khoa
* @return mã băm của id khoa
*/
@Override
public int hashCode() {
int result = departmentId;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "Department{" +
"departmentId=" + departmentId +
", name='" + name + '\'' +
", faculty=" + (faculty == null ? "null" : faculty.getFacultyId()) +
'}';
}
}