From 894fc29901fec09ce46f75f46555a24c0682b33b Mon Sep 17 00:00:00 2001 From: quyixiao <2621048238@qq.com> Date: Thu, 21 Jan 2021 18:03:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/lz/common/cli/CliToken.java | 23 +++ .../java/com/lz/common/cli/CliTokens.java | 43 +++++ .../java/com/lz/common/cli/IntConsumer.java | 8 + .../java/com/lz/common/cli/LineStatus.java | 160 ++++++++++++++++ .../com/lz/common/cli/impl/CliTokenImpl.java | 175 ++++++++++++++++++ src/main/java/com/lz/common/utils/R.java | 16 ++ .../java/com/lz/common/utils/TaskCommand.java | 60 ++++++ .../app/controller/ThirdTaskController.java | 7 + 8 files changed, 492 insertions(+) create mode 100644 src/main/java/com/lz/common/cli/CliToken.java create mode 100644 src/main/java/com/lz/common/cli/CliTokens.java create mode 100644 src/main/java/com/lz/common/cli/IntConsumer.java create mode 100644 src/main/java/com/lz/common/cli/LineStatus.java create mode 100644 src/main/java/com/lz/common/cli/impl/CliTokenImpl.java create mode 100644 src/main/java/com/lz/common/utils/TaskCommand.java diff --git a/src/main/java/com/lz/common/cli/CliToken.java b/src/main/java/com/lz/common/cli/CliToken.java new file mode 100644 index 00000000..48fda924 --- /dev/null +++ b/src/main/java/com/lz/common/cli/CliToken.java @@ -0,0 +1,23 @@ +package com.lz.common.cli; + +public interface CliToken { + /** + * @return the token value + */ + String value(); + + /** + * @return the raw token value, that may contain unescaped chars, for instance {@literal "ab\"cd"} + */ + String raw(); + + /** + * @return true when it's a text token + */ + boolean isText(); + + /** + * @return true when it's a blank token + */ + boolean isBlank(); +} diff --git a/src/main/java/com/lz/common/cli/CliTokens.java b/src/main/java/com/lz/common/cli/CliTokens.java new file mode 100644 index 00000000..c70f5625 --- /dev/null +++ b/src/main/java/com/lz/common/cli/CliTokens.java @@ -0,0 +1,43 @@ +package com.lz.common.cli; + + + + +import com.lz.common.cli.impl.CliTokenImpl; + +import java.util.List; + +/** + * @author beiwei30 on 09/11/2016. + */ +public class CliTokens { + /** + * Create a text token. + * + * @param text the text + * @return the token + */ + public static CliToken createText(String text) { + return new CliTokenImpl(true, text, text); + } + + /** + * Create a new blank token. + * + * @param blank the blank value + * @return the token + */ + public static CliToken createBlank(String blank) { + return new CliTokenImpl(false, blank, blank); + } + + /** + * Tokenize the string argument and return a list of tokens. + * + * @param s the tokenized string + * @return the tokens + */ + public static List tokenize(String s) { + return CliTokenImpl.tokenize(s); + } +} diff --git a/src/main/java/com/lz/common/cli/IntConsumer.java b/src/main/java/com/lz/common/cli/IntConsumer.java new file mode 100644 index 00000000..a2f23539 --- /dev/null +++ b/src/main/java/com/lz/common/cli/IntConsumer.java @@ -0,0 +1,8 @@ +package com.lz.common.cli; + +/** + * @author bw on 25/10/2016. + */ +public interface IntConsumer { + void accept(int value); +} diff --git a/src/main/java/com/lz/common/cli/LineStatus.java b/src/main/java/com/lz/common/cli/LineStatus.java new file mode 100644 index 00000000..3e4a9854 --- /dev/null +++ b/src/main/java/com/lz/common/cli/LineStatus.java @@ -0,0 +1,160 @@ +/* + * Copyright 2015 Julien Viet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lz.common.cli; + + +import java.util.LinkedList; + +/** + * @author Julien Viet + */ +public class LineStatus implements IntConsumer { + + // Keeping this internal to this package + static class Ext extends LineStatus implements IntConsumer { + final LinkedList buffer; + Ext() { + this.buffer = new LinkedList(); + } + public void accept(int codePoint) { + super.accept(codePoint); + switch (transition) { + case TO_WEAK: + buffer.add((int) '"'); + break; + case TO_STRONG: + buffer.add((int) '\''); + break; + case FROM_WEAK: + buffer.add((int) '"'); + break; + case FROM_STRONG: + buffer.add((int) '\''); + break; + case TO_ESC: + buffer.add((int)'\\'); + break; + case FROM_ESC: + if (codePoint != '\r') { + buffer.add(codePoint); + } else { + buffer.removeLast(); + } + break; + case CODE_POINT: + buffer.add(codePoint); + break; + } + } + } + + protected int quote = 0; + protected Transition transition; + + public boolean isEscaped() { + return transition == Transition.FROM_ESC; + } + + public boolean isEscaping() { + return transition == Transition.TO_ESC; + } + + /** + * @return true if it's currently quoted + */ + public boolean isQuoted() { + return quote != 0; + } + + public boolean isWeaklyQuoted() { + return quote == '"'; + } + + public boolean isStronglyQuoted() { + return quote == '\''; + } + + /** + * @return the current quote: {@code 0}, {@code '} or {@code "} value + */ + public int getQuote() { + return quote; + } + + public boolean isCodePoint() { + return transition == Transition.CODE_POINT || transition == Transition.FROM_ESC; + } + + @Override + public void accept(int cp) { + Transition next; + if (transition == Transition.TO_ESC) { + next = Transition.FROM_ESC; + } else { + switch (quote) { + case 0: + switch (cp) { + case '\'': + quote = '\''; + next = Transition.TO_STRONG; + break; + case '"': + quote = '"'; + next = Transition.TO_WEAK; + break; + case '\\': + next = Transition.TO_ESC; + break; + default: + next = Transition.CODE_POINT; + break; + } + break; + case '\'': + if (cp == '\'') { + quote = 0; + next = Transition.FROM_STRONG; + } else { + next = Transition.CODE_POINT; + } + break; + case '"': + if (cp == '"') { + quote = 0; + next = Transition.FROM_WEAK; + } else if (cp == '\\') { + // Note we don't make the distinction between special chars like " or \ from other chars + // that are supposed to not escaped (i.e "\a" is \a and "\$" is $) + // this interpretation is not done by termd + next = Transition.TO_ESC; + } else { + next = Transition.CODE_POINT; + } + break; + default: + throw new AssertionError(); + } + } + this.transition = next; + } + + private enum Transition { + + TO_STRONG, TO_WEAK, FROM_STRONG, FROM_WEAK, TO_ESC, CODE_POINT, FROM_ESC; + + } +} diff --git a/src/main/java/com/lz/common/cli/impl/CliTokenImpl.java b/src/main/java/com/lz/common/cli/impl/CliTokenImpl.java new file mode 100644 index 00000000..bf4bbad5 --- /dev/null +++ b/src/main/java/com/lz/common/cli/impl/CliTokenImpl.java @@ -0,0 +1,175 @@ +package com.lz.common.cli.impl; + + +import com.lz.common.cli.CliToken; +import com.lz.common.cli.LineStatus; + +import java.util.LinkedList; +import java.util.List; + +/** + * @author Julien Viet + */ +public class CliTokenImpl implements CliToken { + + final boolean text; + final String raw; + final String value; + + public CliTokenImpl(boolean text, String value) { + this(text, value, value); + } + + public CliTokenImpl(boolean text, String raw, String value) { + this.text = text; + this.raw = raw; + this.value = value; + } + + @Override + public boolean isText() { + return text; + } + + @Override + public boolean isBlank() { + return !text; + } + + public String raw() { + return raw; + } + + public String value() { + return value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof CliTokenImpl) { + CliTokenImpl that = (CliTokenImpl) obj; + return text == that.text && value.equals(that.value); + } + return false; + } + + @Override + public String toString() { + return "CliToken[text=" + text + ",value=" + value + "]"; + } + + public static List tokenize(String s) { + + List tokens = new LinkedList(); + + tokenize(s, 0, tokens); + return tokens; + + } + + private static void tokenize(String s, int index, List builder) { + while (index < s.length()) { + char c = s.charAt(index); + switch (c) { + case ' ': + case '\t': + index = blankToken(s, index, builder); + break; + case '(': + index = khToken(s, index, builder); + break; + default: + index = textToken(s, index, builder); + break; + } + } + } + + // Todo use code points and not chars + private static int textToken(String s, int index, List builder) { + LineStatus quoter = new LineStatus(); + int from = index; + StringBuilder value = new StringBuilder(); + while (index < s.length()) { + char c = s.charAt(index); + if (isLeftKuo(c)) { + break; + } + quoter.accept(c); + if (!quoter.isQuoted() && !quoter.isEscaped() && isBlank(c)) { + break; + } + if (quoter.isCodePoint()) { + if (quoter.isEscaped() && quoter.isWeaklyQuoted() && c != '"') { + value.append('\\'); + } + value.append(c); + } + index++; + } + builder.add(new CliTokenImpl(true, s.substring(from, index), value.toString())); + return index; + } + + private static int blankToken(String s, int index, List builder) { + int from = index; + while (index < s.length() && isBlank(s.charAt(index))) { + index++; + } + // builder.add(new CliTokenImpl(false, s.substring(from, index))); + return index; + } + + + private static int khToken(String s, int index, List builder) { + int from = index; + int kuo = 0; + while (index < s.length()) { + index++; + char c = s.charAt(index); + try { + //Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + if (isLeftKuo(c)) { + kuo++; + continue; + } + if (isRightKuo(c)) { + if (kuo == 0) { + index++; + break; + } else { + kuo--; + continue; + } + } + } + builder.add(new CliTokenImpl(false, s.substring(from, index))); + return index; + } + + + private static boolean isBlank(char c) { + return c == ' ' || c == '\t'; + } + + + private static boolean isLeftKuo(char c) { + return c == '('; + } + + private static boolean isRightKuo(char c) { + return c == ')'; + } + + +} diff --git a/src/main/java/com/lz/common/utils/R.java b/src/main/java/com/lz/common/utils/R.java index e604cace..05a6f4e3 100644 --- a/src/main/java/com/lz/common/utils/R.java +++ b/src/main/java/com/lz/common/utils/R.java @@ -8,6 +8,7 @@ package com.lz.common.utils; +import com.lz.modules.app.utils.t.Tuple; import org.apache.http.HttpStatus; import java.util.HashMap; @@ -23,6 +24,8 @@ public class R extends HashMap { private boolean isSuccess; + private Tuple tuple; + public R() { put("code", 200); put("msg", "success"); @@ -45,6 +48,19 @@ public class R extends HashMap { return r; } + + public R putObj(Tuple tuple) { + this.tuple = tuple; + return this; + } + + public static R ok(int code) { + R r = new R(); + r.put("code", code); + return r; + } + + public static R ok(String msg) { R r = new R(); r.put("msg", msg); diff --git a/src/main/java/com/lz/common/utils/TaskCommand.java b/src/main/java/com/lz/common/utils/TaskCommand.java new file mode 100644 index 00000000..0999d946 --- /dev/null +++ b/src/main/java/com/lz/common/utils/TaskCommand.java @@ -0,0 +1,60 @@ +package com.lz.common.utils; + + +import com.lz.common.cli.CliToken; +import com.lz.common.cli.CliTokens; +import com.lz.modules.app.utils.t.Tuple; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TaskCommand { + + public static final String add = "add"; + public static final String update = "update"; + public static final String list = "list"; + public static final String task = "task"; + public static final String record = "record"; + + public static List commandCommands = new ArrayList(Arrays.asList(new String[]{"add","update","list"})); + + public static List optTargets = new ArrayList(Arrays.asList(new String[]{"task", "record"})); + + + public static Tuple parse(String command) { + String[] tokens = getTokens(command); + if (commandCommands.contains(tokens[0])) { + return new Tuple(488, "命令的第一个参数必需是 add or update or list"); + } + if (optTargets.contains(tokens[1])) { + return new Tuple(488, "命令的第二个参数必需是 task or record"); + } + if (task.equals(tokens[1])) { //表示对 task 增删改查 + + } else if (record.equals(tokens[1])) { //表示对 list 增删改查 + + } + return new Tuple(); + } + + + public static String [] getTokens(String command) { + List tokenList = new ArrayList<>(); + List tokens = CliTokens.tokenize(command); + for (int i = 0; i < tokens.size(); i++) { + tokenList.add(tokens.get(i).value()); + } + return tokenList.toArray(new String[tokenList.size()]); + } + + @Test + public void test11() { + String ln = " abcdef b csssss dddddd -c \"b ccc ' bb a , bb x b\" a "; + List tokens = CliTokens.tokenize(ln); + for (int i = 0; i < tokens.size(); i++) { + System.out.println(tokens.get(i).value()); + } + } +} diff --git a/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java b/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java index 723a9369..271d75c5 100644 --- a/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java +++ b/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java @@ -43,6 +43,9 @@ public class ThirdTaskController { } log.info("command:" + command); + + + List> data = new ArrayList<>(); for (int i = 0; i < 5; i++) { List a = new ArrayList<>(); @@ -52,6 +55,10 @@ public class ThirdTaskController { data.add(a); } List header = new ArrayList<>(Arrays.asList(new String[]{"用户名", "密码", "哈哈", "双", "你是"})); + + + + return R.ok().put("header", header).put("data", data); }