diff --git a/pom.xml b/pom.xml
index 4e600a4..2dc5e53 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,24 +23,16 @@
-
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.18.1
+
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+ 2.18.1
+
@@ -49,5 +41,11 @@
commons-csv
1.5
+
+ junit
+ junit
+ 4.10
+ test
+
\ No newline at end of file
diff --git a/src/main/java/jp/co/training/Book.java b/src/main/java/jp/co/training/Book.java
index ad5515a..9ebb507 100644
--- a/src/main/java/jp/co/training/Book.java
+++ b/src/main/java/jp/co/training/Book.java
@@ -1,5 +1,6 @@
package jp.co.training;
+import static jp.co.training.Const.DATE_PATTERN;
import static jp.co.training.Const.MAX_AUTHOR;
import static jp.co.training.Const.MAX_BOOK_NAME;
import static jp.co.training.Const.MAX_ISBN;
@@ -15,18 +16,27 @@ public class Book {
private final String publicationDate;
private final String price;
-
public Result validate() {
Result result = new Result();
- //最大最小チェック
- BookUtil.checkRange(isbn, 1, MAX_ISBN, "ISBM").ifPresent(msg -> result.addErrMessage(msg));
- BookUtil.checkRange(bookName, 1, MAX_BOOK_NAME, "BOOK_NAME").ifPresent(msg -> result.addErrMessage(msg));
- BookUtil.checkRange(author, 1, MAX_AUTHOR, "AUTHOR").ifPresent(msg -> result.addErrMessage(msg));
- BookUtil.checkRange(publisher, 1, MAX_PUBLISHER, "PUBLISHER").ifPresent(msg -> result.addErrMessage(msg));
- BookUtil.checkRange(price, 1, MAX_PRICE, "PRICE").ifPresent(msg -> result.addErrMessage(msg));
+ //isbn
+ BookUtil.checkLength(isbn, 1, MAX_ISBN).ifPresent(msg -> result.addMessage("ISBM:" + msg));
+
+ //bookName
+ BookUtil.checkLength(bookName, 1, MAX_BOOK_NAME).ifPresent(msg -> result.addMessage("BOOK_NAME:" + msg));
+
+ //author
+ BookUtil.checkLength(author, 1, MAX_AUTHOR).ifPresent(msg -> result.addMessage("AUTHOR" + msg));
+ //publisher
+ BookUtil.checkLength(publisher, 1, MAX_PUBLISHER).ifPresent(msg -> result.addMessage("PUBLISHER:" + msg));
+ //price
+ BookUtil.checkLength(price, 1, MAX_PRICE).ifPresent(msg -> result.addMessage("PRICE:" + msg));
+ BookUtil.checkNumber(price).ifPresent(msg -> result.addMessage("PRICE:" + msg));
+
+ //publicationDate
+ BookUtil.checkDatePattern(publicationDate, DATE_PATTERN).ifPresent(msg -> result.addMessage("PUBLICATION_DATE:" + msg));
return result;
}
@@ -65,6 +75,7 @@ private Book(Builder builder) {
}
public static class Builder {
+
private String isbn;
private String bookName;
private String author;
diff --git a/src/main/java/jp/co/training/BookUtil.java b/src/main/java/jp/co/training/BookUtil.java
index 19e52b7..b44156e 100644
--- a/src/main/java/jp/co/training/BookUtil.java
+++ b/src/main/java/jp/co/training/BookUtil.java
@@ -1,6 +1,10 @@
package jp.co.training;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.util.Optional;
+import java.util.regex.Pattern;
public class BookUtil {
@@ -15,15 +19,43 @@ private BookUtil() {
* @param target :
* @param min
* @param max
- * @param targetName
* @return
*/
- public static Optional checkRange(String target, int min, int max, String targetName) {
+ public static Optional checkLength(String target, int min, int max) {
if (target.length() < min) {
- return Optional.of(targetName + "of size: min is " + min + ". but your input is " + target.length() + ".");
+ return Optional.of("the length must be " + min + " or more. but actual is " + target.length() + ".");
} else if (target.length() > max) {
- return Optional.of(targetName + "of size: max is " + max + ". but your input is " + target.length() + ".");
+ return Optional.of("the length must be " + max + " or less. but actual is " + target.length() + ".");
}
return Optional.empty();
}
+
+ public static Optional checkDatePattern(String target, String pattern) {
+ DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
+ try {
+ LocalDate.parse(target, df);
+ } catch (DateTimeParseException e) {
+ return Optional.of("Invalid Pattern. valid pattern is " + pattern + ".");
+ }
+ return Optional.empty();
+ }
+
+ public static Optional checkNumber(String target) {
+ if (!isNumber(target)) {
+ return Optional.of("It is not a numerical format.");
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * valueが数値文字列の場合、または空文字の場合はtrueを返す
+ *
+ * @param value
+ * @return
+ */
+ private static boolean isNumber(String value) {
+ return Pattern.compile("^[0-9]*$").matcher(value).matches();
+// return false;
+ }
+
}
diff --git a/src/main/java/jp/co/training/Command.java b/src/main/java/jp/co/training/Command.java
index 538072e..6c351f0 100644
--- a/src/main/java/jp/co/training/Command.java
+++ b/src/main/java/jp/co/training/Command.java
@@ -1,12 +1,9 @@
package jp.co.training;
-import java.util.List;
-
public interface Command {
- void setArgments(List argments);
+ void setArgments(String[] argments);
- void execute();
+ Result execute();
- Result validate();
}
diff --git a/src/main/java/jp/co/training/Const.java b/src/main/java/jp/co/training/Const.java
index a4a3ab8..24629ce 100644
--- a/src/main/java/jp/co/training/Const.java
+++ b/src/main/java/jp/co/training/Const.java
@@ -13,22 +13,26 @@ public final class Const {
public static final int MAX_AUTHOR = 30;
public static final int MAX_PUBLISHER = 30;
public static final int MAX_PRICE = 9;
+ public static final String DATE_PATTERN = "yyyyMMdd";
//外部ファイルによる設定が可能な定数
public static final String PROMPT;
public static final String DELIMITER;
public static final String SAVE_FILE;
+ public static final String END_MESSAGE;
//外部ファイルの設定ファイルのキー
private static final String PROMPT_KEY = "prompt";
private static final String DELIMITER_KEY = "delimiter";
private static final String SAVE_FILE_KEY = "save.file";
+ private static final String END_MESSAGE_KEY = "end.message";
static {
ResourceBundle rb = loadResource();
PROMPT = (rb == null || !rb.containsKey(PROMPT_KEY)) ? "books>" : rb.getString(PROMPT_KEY);
DELIMITER = (rb == null || !rb.containsKey(DELIMITER_KEY)) ? "," : rb.getString(DELIMITER_KEY);
SAVE_FILE = (rb == null || !rb.containsKey(SAVE_FILE_KEY)) ? "savefile" : rb.getString(SAVE_FILE_KEY);
+ END_MESSAGE = (rb == null || !rb.containsKey(END_MESSAGE_KEY)) ? "bye." : rb.getString(END_MESSAGE_KEY);
}
private static ResourceBundle loadResource() {
diff --git a/src/main/java/jp/co/training/ExitCommand.java b/src/main/java/jp/co/training/ExitCommand.java
index 8487f8f..6008b4d 100644
--- a/src/main/java/jp/co/training/ExitCommand.java
+++ b/src/main/java/jp/co/training/ExitCommand.java
@@ -1,31 +1,17 @@
package jp.co.training;
-import java.util.List;
-
public final class ExitCommand implements Command {
- private List argments;
- @Override
- public void execute() {
- System.exit(0);
- }
+ private final Result result = new Result();
@Override
- public void setArgments(List argments) {
- this.argments = argments;
+ public Result execute() {
+ result.setExit(true);
+ return result;
}
@Override
- public Result validate() {
- Result result = new Result();
- //パラメータ数
- if (argments != null && !argments.isEmpty()) {
- if (argments.size() == 1 && argments.get(0).trim().equals("")) {
- return result;
- }
- result.addErrMessage("SyntaxError. The number of arguments does not match.");
- }
- return result;
+ public void setArgments(String[] argments) {
}
}
diff --git a/src/main/java/jp/co/training/InsertCommand.java b/src/main/java/jp/co/training/InsertCommand.java
index 80e02fe..d534670 100644
--- a/src/main/java/jp/co/training/InsertCommand.java
+++ b/src/main/java/jp/co/training/InsertCommand.java
@@ -5,53 +5,64 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import static jp.co.training.Const.SAVE_FILE;
public final class InsertCommand implements Command {
- private List argments;
-
+ private final Result result = new Result();
+ private String[] argments;
private Book book;
@Override
- public void setArgments(List argments) {
+ public void setArgments(String[] argments) {
this.argments = argments;
}
@Override
- public void execute() {
+ public Result execute() {
+ if (!validate()) {
+ return result;
+ }
+ return createBook();
+ }
+
+ private Result createBook() {
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(SAVE_FILE, true), StandardCharsets.UTF_8))) {
- for (int i = 0, size = argments.size(); i < size; i++) {
- bw.write((i == 0 ? "" : ",") + argments.get(i).trim());
- }
+ bw.write(book.getIsbn());
+ bw.write(book.getBookName());
+ bw.write(book.getAuthor());
+ bw.write(book.getPublisher());
+ bw.write(book.getPublicationDate());
+ bw.write(book.getPrice());
bw.newLine();
} catch (IOException ex) {
- Logger.getLogger(InsertCommand.class.getName()).log(Level.SEVERE, null, ex);
+ result.addMessage(SAVE_FILE + ": cannot open.");
+ result.setExit(true);
+ return result;
}
- System.out.println("inserted.");
+ result.addMessage("inserted.");
+ return result;
}
- @Override
- public Result validate() {
- Result result = new Result();
- //パラメータ数
- if (argments.size() != 6) {
- result.addErrMessage("SyntaxError. The number of arguments does not match.");
+ /*
+ 検証の結果OKならtrueを返す。それ以外はfalseを返す
+ */
+ private boolean validate() {
+ //パラメータ数チェック
+ if (argments.length != 6) {
+ result.addMessage("SyntaxError. The number of arguments does not match.");
+ return false;
}
- book = new Book.Builder().isbn(argments.get(0))
- .bookName(argments.get(1))
- .author(argments.get(2))
- .publisher(argments.get(3))
- .publicationDate(argments.get(4))
- .author(argments.get(5))
- .price(argments.get(6))
+ //書籍情報のチェック
+ book = new Book.Builder().isbn(argments[0].trim())
+ .bookName(argments[1].trim())
+ .author(argments[2].trim())
+ .publisher(argments[3].trim())
+ .publicationDate(argments[4].trim())
+ .price(argments[5].trim())
.build();
- result.getErrMesages().addAll(book.validate().getErrMesages());
-
- return result;
+ result.getMesages().addAll(book.validate().getMesages());
+ return result.getMesages().isEmpty();
}
}
diff --git a/src/main/java/jp/co/training/InvalidCommand.java b/src/main/java/jp/co/training/InvalidCommand.java
index f5063ba..585fd0e 100644
--- a/src/main/java/jp/co/training/InvalidCommand.java
+++ b/src/main/java/jp/co/training/InvalidCommand.java
@@ -1,21 +1,16 @@
package jp.co.training;
-import java.util.List;
-
public final class InvalidCommand implements Command {
- @Override
- public void setArgments(List argments) {
- }
+ private final Result result = new Result();
@Override
- public void execute() {
+ public void setArgments(String[] argments) {
}
@Override
- public Result validate() {
- Result result = new Result();
- result.addErrMessage("Invalid Command.");
+ public Result execute() {
+ result.addMessage("Invalid Command.");
return result;
}
diff --git a/src/main/java/jp/co/training/Main.java b/src/main/java/jp/co/training/Main.java
index 8bca169..41f97ac 100644
--- a/src/main/java/jp/co/training/Main.java
+++ b/src/main/java/jp/co/training/Main.java
@@ -2,8 +2,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
import java.util.Scanner;
import static jp.co.training.Const.DELIMITER;
import static jp.co.training.Const.PROMPT;
@@ -14,18 +12,23 @@ public static void main(String... args) throws FileNotFoundException, IOExceptio
try (Scanner scan = new Scanner(System.in)) {
while (true) {
System.out.print(PROMPT);
- Command command = CommandFactory.createCommand(scan.next());
- List argments = Arrays.asList(scan.nextLine().split(DELIMITER));
+ Command command = CommandFactory.createCommand(scan.next().toLowerCase());
+ command.setArgments(scan.nextLine().split(DELIMITER));
- command.setArgments(argments);
- Result result = command.validate();
- if (result != null && result.getErrMesages().size() > 0) {
- result.getErrMesages().stream().forEach(message -> {
- System.err.println(message);
- });
+ Result result = command.execute();
+ outputMessages(result);
+ if (result != null && result.isExit()) {
+ break;
}
- command.execute();
}
}
}
+
+ private static void outputMessages(Result result) {
+ if (result != null && result.getMesages().size() > 0) {
+ result.getMesages().stream().forEach(message -> {
+ System.out.println(message);
+ });
+ }
+ }
}
diff --git a/src/main/java/jp/co/training/Result.java b/src/main/java/jp/co/training/Result.java
index 6e0a6e2..be2ecff 100644
--- a/src/main/java/jp/co/training/Result.java
+++ b/src/main/java/jp/co/training/Result.java
@@ -5,13 +5,23 @@
public class Result {
- private final List errMesages = new ArrayList<>();
+ private boolean exit = false;
+ private final List mesages = new ArrayList<>();
- public List getErrMesages() {
- return errMesages;
+ public List getMesages() {
+ return mesages;
}
- public void addErrMessage(String msg) {
- errMesages.add(msg);
+ public void addMessage(String msg) {
+ mesages.add(msg);
}
+
+ public boolean isExit() {
+ return exit;
+ }
+
+ public void setExit(boolean exit) {
+ this.exit = exit;
+ }
+
}
diff --git a/src/main/java/jp/co/training/Status.java b/src/main/java/jp/co/training/Status.java
new file mode 100644
index 0000000..2379628
--- /dev/null
+++ b/src/main/java/jp/co/training/Status.java
@@ -0,0 +1,8 @@
+package jp.co.training;
+
+public enum Status {
+
+ KEEP,//そのまま継続
+ BREAK//ループを抜ける
+
+}