From 1eb85ee31ffa520a309e0e305548ee49252bb762 Mon Sep 17 00:00:00 2001 From: Haruaki TAMADA Date: Mon, 29 Nov 2021 15:28:05 +0900 Subject: [PATCH 1/8] update ASM version to 9.2 for supporting Java 17 --- kunai2/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kunai2/pom.xml b/kunai2/pom.xml index f52e00d4..464349c3 100644 --- a/kunai2/pom.xml +++ b/kunai2/pom.xml @@ -19,7 +19,7 @@ org.ow2.asm asm - 8.0.1 + 9.2 diff --git a/pom.xml b/pom.xml index 86f35a5f..7e98cb75 100644 --- a/pom.xml +++ b/pom.xml @@ -228,7 +228,7 @@ org.jacoco jacoco-maven-plugin - 0.8.6 + 0.8.7 prepare-agent From 6d4604fb8cf05d6d3c52c0287f14c85b5fce6af9 Mon Sep 17 00:00:00 2001 From: Haruaki TAMADA Date: Mon, 29 Nov 2021 15:29:07 +0900 Subject: [PATCH 2/8] fix: hold the thrown exceptions for building Birthmarks --- .../cafebabe/birthmarks/BirthmarkParser.java | 2 +- .../birthmarks/entities/Birthmarks.java | 25 +++++++++++++++--- .../birthmarks/entities/Frequency.java | 2 +- .../entities/elements/FrequencyElements.java | 7 +++++ .../entities/elements/ListElements.java | 5 ++++ .../birthmarks/extractors/Extractor.java | 2 +- .../birthmarks/entities/BirthmarksTest.java | 4 +-- .../main/java/jp/cafebabe/pochi/Pochi.java | 2 +- .../uc/FUCBirthmarkExtractorTest.java | 26 +++++++++---------- 9 files changed, 52 insertions(+), 23 deletions(-) diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/BirthmarkParser.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/BirthmarkParser.java index 49ba36e5..69ac4986 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/BirthmarkParser.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/BirthmarkParser.java @@ -25,7 +25,7 @@ default List> parseForStream(DataSource source) { default Birthmarks parse(DataSource source){ List> stream = parseForStream(source); // do termination operation before calling ```type()``` - return new Birthmarks<>(stream.stream()); + return Birthmarks.of(stream.stream()); } List> parseEntry(Entry entry); diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java index 84408a89..eb5be535 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java @@ -1,23 +1,27 @@ package jp.cafebabe.birthmarks.entities; import java.io.Serializable; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; +import io.vavr.control.Either; import jp.cafebabe.birthmarks.pairs.Streamable; import jp.cafebabe.kunai.entries.ClassName; public class Birthmarks implements Acceptor, Iterable>, Streamable>, Serializable { private List> list; + private List exceptions; public Birthmarks(){ this(Stream.empty()); } - public Birthmarks(Stream> stream) { - this.list = stream.collect(Collectors.toList()); + public Birthmarks(Stream>> stream) { + list = new ArrayList<>(); + exceptions = new ArrayList<>(); + stream.forEach(either -> either.bimap(t -> exceptions.add(t), r -> list.add(r))); } public Stream> find(ClassName name) { @@ -29,6 +33,10 @@ public Stream> stream() { return list.stream(); } + public Stream exceptionStream() { + return exceptions.stream(); + } + public long count() { return list.size(); } @@ -39,13 +47,22 @@ public Iterator> iterator() { } public Birthmarks merge(Stream> stream) { - return new Birthmarks<>(Stream.concat(stream(), stream)); + return new Birthmarks<>(Stream.concat(stream(), stream) + .map(item -> Either.right(item))); } public Birthmarks merge(Birthmarks other) { return merge(other.stream()); } + public static Birthmarks of(Stream> stream) { + return ofEither(stream.map(item -> Either.right(item))); + } + + public static Birthmarks ofEither(Stream>> stream) { + return new Birthmarks<>(stream); + } + @Override public void accept(Visitor visitor) { list.stream() diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Frequency.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Frequency.java index c40ef48a..d04c71c3 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Frequency.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Frequency.java @@ -11,7 +11,7 @@ public static Frequency of(String item, Integer frequency) { @Override public String toString() { - return String.format("%s=%d", left(), right()); + return String.format("<%s,%d>", left(), right()); } @Override diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/FrequencyElements.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/FrequencyElements.java index 192787de..96d86915 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/FrequencyElements.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/FrequencyElements.java @@ -106,4 +106,11 @@ public static FrequencyElements of(String... elements) { public static FrequencyElements of(Stream stream) { return new FrequencyElements(stream); } + + @Override + public String toString() { + return frequencies.entrySet() + .stream().map(entry -> String.format("<%s,%d>", entry.getKey(), entry.getValue())) + .collect(Collectors.joining(",")); + } } diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/ListElements.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/ListElements.java index ed48e1f9..c9e6d15a 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/ListElements.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/elements/ListElements.java @@ -78,4 +78,9 @@ public static ListElements asSetOf(String... elements) { return new ListElements(Arrays.stream(elements) .distinct()); } + + @Override + public String toString() { + return list.stream().collect(Collectors.joining(",")); + } } diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/extractors/Extractor.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/extractors/Extractor.java index 20f959eb..532f85ad 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/extractors/Extractor.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/extractors/Extractor.java @@ -42,7 +42,7 @@ default Stream>> extractStream(DataSource sou * @return extracted birthmarks */ default Birthmarks extract(DataSource source){ - return new Birthmarks(stripEither(extractStream(source))); + return new Birthmarks(extractStream(source)); } /** diff --git a/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java b/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java index 12a704bf..0211a8b1 100644 --- a/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java +++ b/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java @@ -26,7 +26,7 @@ public void setUp() throws Exception{ Elements.listElements(IntStream.range(1, 4).mapToObj(label -> "e" + label)))); list.add(new Birthmark(new Metadata(new ClassName("c3"), new URI("source3"), BirthmarkType.of("hoge1")), Elements.listElements(IntStream.range(1, 6).mapToObj(label -> "e" + label)))); - this.birthmarks = new Birthmarks<>(list.stream()); + this.birthmarks = Birthmarks.of(list.stream()); } @Test @@ -59,7 +59,7 @@ public void testAppend() throws Exception{ Birthmark b1 = new Birthmark<>(new Metadata(new ClassName("o1"), new URI("otherSource"), BirthmarkType.of("hoge1")), Elements.listElements(IntStream.range(1, 7).mapToObj(label -> "e" + label))); - Birthmarks other = birthmarks.merge(new Birthmarks<>(Stream.of(b1))); + Birthmarks other = birthmarks.merge(Birthmarks.of(Stream.of(b1))); List> list = other.stream().collect(Collectors.toList()); assertThat(list.size(), is(4)); diff --git a/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java b/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java index 15d3fa90..b8672a76 100644 --- a/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java +++ b/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java @@ -22,7 +22,7 @@ public static final Path home() { } private static List targetPaths() { - return Arrays.asList(System.getenv("POCHI_HOME"), "/opt/pochi", "/usr/local/opt/pochi", String.format("pochi-%s", Pochi.VERSION), "."); + return Arrays.asList(System.getenv("POCHI_HOME"), "/opt/pochi", "/usr/local/opt/pochi", "/opt/homebrew/opt/pochi", String.format("pochi-%s", Pochi.VERSION), "."); } private Path findPochiHome() { diff --git a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java index 70a65647..f5a95762 100644 --- a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java +++ b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java @@ -43,8 +43,8 @@ public void testBasic() throws Exception{ list.get(0).forEach(item -> elements.add(item.toString())); assertThat(elements.size(), is(4)); - assertThat(elements, is(containsInAnyOrder("java.io.PrintStream=2", - "java.lang.Object=2", "java.lang.String=2", "java.lang.System=1"))); + assertThat(elements, is(containsInAnyOrder("", + "", "", ""))); } @Test @@ -60,12 +60,12 @@ public void testBasic2() throws Exception{ list.get(0).forEach(item -> elements.add(item.toString())); assertThat(elements.size(), is(13)); - assertThat(elements, is(containsInAnyOrder("java.io.PrintStream=2", - "java.lang.Integer=5", "java.lang.Object=5", "java.lang.String=1", - "java.lang.System=1", "java.util.Iterator=3", "java.util.List=5", - "java.util.function.IntFunction=1", "java.util.function.IntUnaryOperator=1", - "java.util.stream.Collector=2", "java.util.stream.Collectors=1", - "java.util.stream.IntStream=7", "java.util.stream.Stream=2"))); + assertThat(elements, is(containsInAnyOrder("", + "", "", "", + "", "", "", + "", "", + "", "", + "", ""))); } @Test @@ -81,9 +81,9 @@ public void testBasic3() throws Exception{ list.get(0).forEach(item -> elements.add(item.toString())); assertThat(elements.size(), is(6)); - assertThat(elements, is(containsInAnyOrder("java.io.PrintStream=4", - "java.lang.Integer=70", "java.lang.Object=2", "java.lang.String=10", - "java.lang.System=2", "java.util.Random=4"))); + assertThat(elements, is(containsInAnyOrder("", + "", "", "", + "", ""))); } @Test @@ -99,7 +99,7 @@ public void testBasic4() throws Exception{ list.get(0).forEach(item -> elements.add(item.toString())); assertThat(elements.size(), is(3)); - assertThat(elements, is(containsInAnyOrder("java.io.IOException=1", - "java.lang.Object=2", "java.net.ServerSocket=7"))); + assertThat(elements, is(containsInAnyOrder("", + "", ""))); } } From cf57d3210caad9beb61e05e597eac94176b9e603 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 29 Nov 2021 06:46:49 +0000 Subject: [PATCH 3/8] version up to 2.6.0, ready to publish v2.6.0 --- README.md | 19 ++++++++++--------- bin/build_site.sh | 2 +- bin/make_dist.sh | 2 +- dockers/pochi-groovysh/Dockerfile | 2 +- dockers/pochi/Dockerfile | 2 +- kunai2/pom.xml | 2 +- pochi-api/pom.xml | 4 ++-- pochi-cmd/pom.xml | 4 ++-- pochi-core/pom.xml | 6 +++--- .../main/java/jp/cafebabe/pochi/Pochi.java | 2 +- pom.xml | 2 +- site/content/_index.md | 6 +++--- site/content/description.md | 5 +++-- site/content/install.md | 8 ++++---- site/pom.xml | 8 ++++---- 15 files changed, 38 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 52948b49..1cb05517 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ [![codebeat badge](https://codebeat.co/badges/8e8c5e70-cb07-4f58-941c-3ddb64f3c059)](https://codebeat.co/projects/github-com-tamada-pochi-main) [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://github.com/tamada/pochi/blob/master/LICENSE) -[![Version](https://img.shields.io/badge/Version-2.5.2-green.svg)](https://github.com/tamada/pochi/releases/tag/v2.5.2) +[![Version](https://img.shields.io/badge/Version-2.6.0-green.svg)](https://github.com/tamada/pochi/releases/tag/v2.6.0) [![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.4271132-green.svg)](https://zenodo.org/badge/latestdoi/82773287) -[![Javadoc](https://img.shields.io/badge/Javadoc-v2.5.2-blue?logo=java)](https://tamada.github.io/pochi/apidocs) -[![Docker](https://img.shields.io/badge/Docker-ghcr.io%2Ftamada%2Fpochi%3A2.5.2-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) +[![Javadoc](https://img.shields.io/badge/Javadoc-v2.6.0-blue?logo=java)](https://tamada.github.io/pochi/apidocs) +[![Docker](https://img.shields.io/badge/Docker-ghcr.io%2Ftamada%2Fpochi%3A2.6.0-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) [![GitHub Discussion](https://img.shields.io/badge/GitHub-Discussions-blue?logo=github)](https://github.com/tamada/pochi/discussions) Detecting the software theft, the birthmark toolkit for the JVM platform. @@ -83,7 +83,8 @@ For more detail, see [:ant: Examples](https://tamada.github.io/pochi/examples). Container images of **pochi** for Docker are: * [`ghcr.io/tamada/pochi`](https://github.com/users/tamada/packages/container/package/pochi) - * `2.5.2`, `latest` + * `2.6.0`, `latest` + * `2.5.2` * `2.5.1` * `2.5.0` * `2.4.6` @@ -106,7 +107,7 @@ Container images of **pochi** for Docker are: * `1.0.0` * accept only `.js` script files. -[![Docker](https://img.shields.io/badge/Docker-ghcir.io%2Ftamada%2Fpochi%3A2.5.2-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) +[![Docker](https://img.shields.io/badge/Docker-ghcir.io%2Ftamada%2Fpochi%3A2.6.0-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) To run **pochi** on Docker container OS, type the following commands. @@ -158,10 +159,10 @@ Then, add the dependencies of your `pom.xml`. | groupId | artifactId | version | |--------------------|--------------|---------| -|`jp.cafebabe.pochi` | `kunai2` | `2.5.2` | -|`jp.cafebabe.pochi` | `pochi-core` | `2.5.2` | -|`jp.cafebabe.pochi` | `pochi-api` | `2.5.2` | -|`jp.cafebabe.pochi` | `pochi-cmd` | `2.5.2` | +|`jp.cafebabe.pochi` | `kunai2` | `2.6.0` | +|`jp.cafebabe.pochi` | `pochi-core` | `2.6.0` | +|`jp.cafebabe.pochi` | `pochi-api` | `2.6.0` | +|`jp.cafebabe.pochi` | `pochi-cmd` | `2.6.0` | ## Modules diff --git a/bin/build_site.sh b/bin/build_site.sh index da1f9aa4..88e0949c 100755 --- a/bin/build_site.sh +++ b/bin/build_site.sh @@ -1,6 +1,6 @@ #! /bin/sh -VERSION="2.5.2" +VERSION="2.6.0" function build_apidocs() { mkdir -p site/msp diff --git a/bin/make_dist.sh b/bin/make_dist.sh index 26a72da6..cbcedc3a 100755 --- a/bin/make_dist.sh +++ b/bin/make_dist.sh @@ -1,6 +1,6 @@ #! /bin/sh -VERSION="2.5.2" +VERSION="2.6.0" function mkdirIfNeeded () { if [ ! -d $1 ] ; then diff --git a/dockers/pochi-groovysh/Dockerfile b/dockers/pochi-groovysh/Dockerfile index 6417627d..0e3aa891 100644 --- a/dockers/pochi-groovysh/Dockerfile +++ b/dockers/pochi-groovysh/Dockerfile @@ -15,7 +15,7 @@ RUN apk --no-cache add openjdk11=11.0.4_p4-r1 \ # building pochi FROM alpine:3.10.1 -ARG PochiVersion="2.5.2" +ARG PochiVersion="2.6.0" ARG GroovyVersion="3.0.9" LABEL maintainer="Haruaki Tamada" \ diff --git a/dockers/pochi/Dockerfile b/dockers/pochi/Dockerfile index 1c83c791..0b8d0374 100644 --- a/dockers/pochi/Dockerfile +++ b/dockers/pochi/Dockerfile @@ -15,7 +15,7 @@ RUN apk --no-cache add openjdk11=11.0.4_p4-r1 \ # building pochi FROM alpine:3.10.1 -ARG PochiVersion="2.5.2" +ARG PochiVersion="2.6.0" LABEL maintainer="Haruaki Tamada" \ pochi-version="${PochiVersion}" \ diff --git a/kunai2/pom.xml b/kunai2/pom.xml index 464349c3..b50f72e6 100644 --- a/kunai2/pom.xml +++ b/kunai2/pom.xml @@ -4,7 +4,7 @@ jp.cafebabe pochi - 2.5.2 + 2.6.0 4.0.0 diff --git a/pochi-api/pom.xml b/pochi-api/pom.xml index 241aec80..8f1c3caf 100644 --- a/pochi-api/pom.xml +++ b/pochi-api/pom.xml @@ -6,7 +6,7 @@ jp.cafebabe pochi - 2.5.2 + 2.6.0 jp.cafebabe.pochi @@ -33,7 +33,7 @@ jp.cafebabe.pochi kunai2 - 2.5.2 + 2.6.0 compile diff --git a/pochi-cmd/pom.xml b/pochi-cmd/pom.xml index 4222f702..61898fb8 100644 --- a/pochi-cmd/pom.xml +++ b/pochi-cmd/pom.xml @@ -6,7 +6,7 @@ jp.cafebabe pochi - 2.5.2 + 2.6.0 jp.cafebabe.pochi @@ -38,7 +38,7 @@ jp.cafebabe.pochi pochi-core - 2.5.2 + 2.6.0 compile diff --git a/pochi-core/pom.xml b/pochi-core/pom.xml index 59cca0bf..e234fdfb 100644 --- a/pochi-core/pom.xml +++ b/pochi-core/pom.xml @@ -4,7 +4,7 @@ jp.cafebabe pochi - 2.5.2 + 2.6.0 4.0.0 @@ -20,13 +20,13 @@ jp.cafebabe.pochi kunai2 - 2.5.2 + 2.6.0 compile jp.cafebabe.pochi pochi-api - 2.5.2 + 2.6.0 compile diff --git a/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java b/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java index b8672a76..fbd327b7 100644 --- a/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java +++ b/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java @@ -8,7 +8,7 @@ import java.util.Optional; public class Pochi { - public static final String VERSION = "2.5.2"; + public static final String VERSION = "2.6.0"; private static final Pochi INSTANCE = new Pochi(); private final Path home; diff --git a/pom.xml b/pom.xml index 7e98cb75..d991d0b4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ jp.cafebabe pochi - 2.5.2 + 2.6.0 pom diff --git a/site/content/_index.md b/site/content/_index.md index b7738796..3f9c8ea8 100644 --- a/site/content/_index.md +++ b/site/content/_index.md @@ -9,11 +9,11 @@ draft: false [![codebeat badge](https://codebeat.co/badges/8e8c5e70-cb07-4f58-941c-3ddb64f3c059)](https://codebeat.co/projects/github-com-tamada-pochi-main) [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg?style=flat)](https://github.com/tamada/pochi/blob/master/LICENSE) -[![Version](https://img.shields.io/badge/Version-2.5.2-green.svg)](https://github.com/tamada/pochi/releases/tag/v2.5.2) +[![Version](https://img.shields.io/badge/Version-2.6.0-green.svg)](https://github.com/tamada/pochi/releases/tag/v2.6.0) [![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.4271132-green.svg)](https://zenodo.org/badge/latestdoi/82773287) -[![Javadoc](https://img.shields.io/badge/Javadoc-v2.5.2-blue?logo=java)](https://tamada.github.io/pochi/apidocs) -[![Docker](https://img.shields.io/badge/Docker-ghcr.io%2Ftamada%2Fpochi%3A2.5.2-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) +[![Javadoc](https://img.shields.io/badge/Javadoc-v2.6.0-blue?logo=java)](https://tamada.github.io/pochi/apidocs) +[![Docker](https://img.shields.io/badge/Docker-ghcr.io%2Ftamada%2Fpochi%3A2.6.0-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) [![GitHub Discussion](https://img.shields.io/badge/GitHub-Discussions-blue?logo=github)](https://github.com/tamada/pochi/discussions) Detecting the software theft, the birthmark toolkit for the JVM platform. diff --git a/site/content/description.md b/site/content/description.md index f4333397..8aa81965 100644 --- a/site/content/description.md +++ b/site/content/description.md @@ -49,7 +49,8 @@ For more detail, see [:ant: Examples](../examples). Container images of **pochi** for Docker are: * [`ghcr.io/tamada/pochi`](https://github.com/users/tamada/packages/container/package/pochi) - * `2.5.2`, `latest` + * `2.6.0`, `latest` + * `2.5.2` * `2.5.1` * `2.5.0` * `2.4.6` @@ -72,7 +73,7 @@ Container images of **pochi** for Docker are: * `1.0.0` * accept only `.js` script files. -[![Docker](https://img.shields.io/badge/Docker-ghcir.io%2Ftamada%2Fpochi%3A2.5.2-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) +[![Docker](https://img.shields.io/badge/Docker-ghcir.io%2Ftamada%2Fpochi%3A2.6.0-blue?logo=docker)](https://github.com/users/tamada/packages/container/package/pochi) To run **pochi** on Docker container OS, type the following commands. diff --git a/site/content/install.md b/site/content/install.md index 993567a8..2b2cd0ad 100644 --- a/site/content/install.md +++ b/site/content/install.md @@ -47,10 +47,10 @@ Then, add the dependencies of your `pom.xml`. | groupId | artifactId | version | |--------------------|--------------|---------| -|`jp.cafebabe.pochi` | `kunai2` | `2.5.2` | -|`jp.cafebabe.pochi` | `pochi-core` | `2.5.2` | -|`jp.cafebabe.pochi` | `pochi-api` | `2.5.2` | -|`jp.cafebabe.pochi` | `pochi-cmd` | `2.5.2` | +|`jp.cafebabe.pochi` | `kunai2` | `2.6.0` | +|`jp.cafebabe.pochi` | `pochi-core` | `2.6.0` | +|`jp.cafebabe.pochi` | `pochi-api` | `2.6.0` | +|`jp.cafebabe.pochi` | `pochi-cmd` | `2.6.0` | ## :briefcase: Requirements diff --git a/site/pom.xml b/site/pom.xml index 2a78d53a..d25df25f 100644 --- a/site/pom.xml +++ b/site/pom.xml @@ -4,7 +4,7 @@ jp.cafebabe pochi - 2.5.2 + 2.6.0 4.0.0 @@ -20,19 +20,19 @@ jp.cafebabe.pochi kunai2 - 2.5.2 + 2.6.0 provided jp.cafebabe.pochi pochi-api - 2.5.2 + 2.6.0 provided jp.cafebabe.pochi pochi-core - 2.5.2 + 2.6.0 provided From de8d927a9ec6ac1d5236f9a268d54649a3e6f40a Mon Sep 17 00:00:00 2001 From: Haruaki TAMADA Date: Thu, 2 Dec 2021 14:16:59 +0900 Subject: [PATCH 4/8] add unify method to Birthmarks class --- .../birthmarks/entities/Birthmarks.java | 6 ++ .../birthmarks/entities/BirthmarksMerger.java | 61 +++++++++++++++++++ .../cafebabe/birthmarks/entities/Couple.java | 5 ++ .../utils/LongestCommonSubstring.java | 47 ++++++++++++++ pochi-api/src/main/java/module-info.java | 3 +- .../birthmarks/entities/BirthmarksTest.java | 13 ++++ .../utils/LongestCommonSubstringTest.java | 15 +++++ 7 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java create mode 100644 pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java create mode 100644 pochi-api/src/test/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstringTest.java diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java index eb5be535..57abbd2c 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Birthmarks.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.Stream; import io.vavr.control.Either; @@ -24,6 +26,10 @@ public Birthmarks(Stream>> stream) { stream.forEach(either -> either.bimap(t -> exceptions.add(t), r -> list.add(r))); } + public Optional> unify() { + return BirthmarksMerger.unifyTo(this); + } + public Stream> find(ClassName name) { return list.stream() .filter(birthmark -> birthmark.isSame(name)); diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java new file mode 100644 index 00000000..cc25ca48 --- /dev/null +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java @@ -0,0 +1,61 @@ +package jp.cafebabe.birthmarks.entities; + +import io.vavr.control.Try; +import jp.cafebabe.birthmarks.utils.LongestCommonSubstring; +import jp.cafebabe.kunai.entries.ClassName; + +import java.net.URI; +import java.nio.file.Path; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class BirthmarksMerger { + public Optional> unify(Birthmarks birthmarks) { + Optional> elements = mergeElements(birthmarks); + Metadata metadata = mergeMetadata(birthmarks); + return elements.map(e -> new Birthmark<>(metadata, e)); + } + + private Metadata mergeMetadata(Birthmarks birthmarks) { + String location = findCommonLocation(birthmarks.stream()); + return constructMetadata(location, findType(birthmarks)); + } + + private Optional findType(Birthmarks birthmarks) { + return birthmarks.stream().map(b -> b.type()) + .collect(Collectors.reducing((a, b) -> a)); + } + + private Metadata constructMetadata(String location, Optional type) { + Try tryUri = Try.of(() -> new URI(location)); + Optional uri = tryUri.toJavaOptional(); + Optional name = uri.map(u -> new ClassName(findBaseName(u))); + return new Metadata(name.orElseGet(() -> new ClassName("")), uri.get(), type.get()); + } + + private String findBaseName(URI uri) { + String path = uri.toString(); + int index = path.lastIndexOf('/'); + if(index >= 0) + return path.substring(index + 1); + return path; + } + + private String findCommonLocation(Stream> stream) { + Optional location = stream.map(birthmark -> birthmark.metadata()) + .map(m -> m.location().toString()) + .collect(Collectors.reducing((s1, s2) -> LongestCommonSubstring.of(s1, s2))); + return location.orElseGet(() -> ""); + } + + private Optional> mergeElements(Birthmarks birthmarks) { + return birthmarks.stream() + .map(birthmark -> birthmark.elements()) + .collect(Collectors.reducing((a, b) -> a.merge(b))); + } + + public static Optional> unifyTo(Birthmarks birthmarks) { + return new BirthmarksMerger().unify(birthmarks); + } +} diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Couple.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Couple.java index 278cd52a..45042590 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Couple.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/Couple.java @@ -16,6 +16,11 @@ protected Couple(L left, R right) { this.right = Objects.requireNonNull(right); } + public void applyIf(BiPredicate predicate, BiConsumer consumer) { + if(predicate.test(left, right)) + consumer.accept(left, right); + } + public L left() { return left; } diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java new file mode 100644 index 00000000..881b0c12 --- /dev/null +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java @@ -0,0 +1,47 @@ +package jp.cafebabe.birthmarks.utils; + +import jp.cafebabe.birthmarks.entities.Couple; + +import java.util.Optional; + +public class LongestCommonSubstring { + public static final String of(String s1, String s2) { + return new LongestCommonSubstring() + .calculate(s1, s2); + } + + private String calculate(String s1, String s2) { + int[][] table = new int[s1.length() + 1][s2.length() + 1]; + Result r = Result.of(0, 0, 0); + for(int i = 0; i < table.length; i++) { + for(int j = 0; j < table[i].length; j++) { + if(i == 0 || j == 0) table[i][j] = 0; + else if(s1.charAt(i - 1) == s2.charAt(j - 1)) { + table[i][j] = 1 + table[i - 1][j - 1]; + r = updateResultIfNeeded(r, i, j, table[i][j]); + } + // printTable(table); + } + } + return s1.substring(r.i - r.max, r.i); + } + + private Result updateResultIfNeeded(Result r, int i, int j, int v) { + if(r.max > v) + return r; + return Result.of(i, j, v); + } + + private static final class Result { + private int i, j; + private int max; + private Result(int i, int j, int max) { + this.i = i; + this.j = j; + this.max = max; + } + public static Result of(int i, int j, int max) { + return new Result(i, j, max); + } + } +} diff --git a/pochi-api/src/main/java/module-info.java b/pochi-api/src/main/java/module-info.java index 30cf358c..8e046bf6 100644 --- a/pochi-api/src/main/java/module-info.java +++ b/pochi-api/src/main/java/module-info.java @@ -60,8 +60,9 @@ exports jp.cafebabe.birthmarks.entities.elements; exports jp.cafebabe.birthmarks.extractors; exports jp.cafebabe.birthmarks.pairs; + exports jp.cafebabe.birthmarks.utils; - uses jp.cafebabe.birthmarks.comparators.ComparatorBuilder; + uses jp.cafebabe.birthmarks.comparators.ComparatorBuilder; uses jp.cafebabe.birthmarks.extractors.ExtractorBuilder; uses jp.cafebabe.birthmarks.pairs.PairMatcherBuilder; } diff --git a/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java b/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java index 0211a8b1..cda35b8e 100644 --- a/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java +++ b/pochi-api/src/test/java/jp/cafebabe/birthmarks/entities/BirthmarksTest.java @@ -7,6 +7,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -68,4 +69,16 @@ public void testAppend() throws Exception{ assertThat(list.get(2).metadata().toString(), is("c3,source3,hoge1")); assertThat(list.get(3).metadata().toString(), is("o1,otherSource,hoge1")); } + + @Test + public void testUnify() throws Exception { + Optional> optionalResult = birthmarks.unify(); + if(optionalResult.isEmpty()) + throw new InternalError(); + Birthmark result = optionalResult.get(); + Elements elements = result.elements(); + + assertThat(result.className(), is(new ClassName("source"))); + assertThat(elements.size(), is(9)); + } } diff --git a/pochi-api/src/test/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstringTest.java b/pochi-api/src/test/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstringTest.java new file mode 100644 index 00000000..ad68372e --- /dev/null +++ b/pochi-api/src/test/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstringTest.java @@ -0,0 +1,15 @@ +package jp.cafebabe.birthmarks.utils; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import org.junit.Test; + +public class LongestCommonSubstringTest { + @Test + public void basicTest() { + assertThat(LongestCommonSubstring.of("abcdxyz", "xyzabcd"), is("abcd")); + assertThat(LongestCommonSubstring.of("abracadabra", "open sesame"), is("a")); + assertThat(LongestCommonSubstring.of("aaaa", "bbb"), is("")); + } +} From 9be156b3e64f5ea67ac28ef0c5556cb20c2e9d2d Mon Sep 17 00:00:00 2001 From: Haruaki TAMADA Date: Thu, 2 Dec 2021 14:37:31 +0900 Subject: [PATCH 5/8] fix the issues from codacy --- .../jp/cafebabe/birthmarks/entities/BirthmarksMerger.java | 1 - .../cafebabe/birthmarks/utils/LongestCommonSubstring.java | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java index cc25ca48..6b9fa989 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java @@ -5,7 +5,6 @@ import jp.cafebabe.kunai.entries.ClassName; import java.net.URI; -import java.nio.file.Path; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; diff --git a/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java index 881b0c12..2df7b427 100644 --- a/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java @@ -1,9 +1,5 @@ package jp.cafebabe.birthmarks.utils; -import jp.cafebabe.birthmarks.entities.Couple; - -import java.util.Optional; - public class LongestCommonSubstring { public static final String of(String s1, String s2) { return new LongestCommonSubstring() @@ -33,7 +29,8 @@ private Result updateResultIfNeeded(Result r, int i, int j, int v) { } private static final class Result { - private int i, j; + private int i; + private int j; private int max; private Result(int i, int j, int max) { this.i = i; From 97344da857e20d5749e388fa257c61dc1ab9754d Mon Sep 17 00:00:00 2001 From: Haruaki Tamada Date: Wed, 8 Dec 2021 15:18:22 +0900 Subject: [PATCH 6/8] update exports of module-info in kunai2 (#125) * update exports of module-info in kunai2 and add instance method for DataSinkFactory, * DataSourceFactory to create the default instance of them, and * fix the compilation errors. --- kunai2/README.md | 4 ++-- .../src/main/java/jp/cafebabe/kunai/Demo.java | 8 +++---- .../kunai/sink/factories/DataSinkFactory.java | 4 ++++ .../factories/DefaultDataSinkFactory.java | 2 +- .../source/factories/DataSourceFactory.java | 4 ++++ .../factories/DefaultDataSourceFactory.java | 2 +- .../kunai/source/factories/package-info.java | 2 +- kunai2/src/main/java/module-info.java | 9 ++++---- .../kunai/sink/DirectoryDataSinkTest.java | 23 +++++++++---------- .../kunai/sink/JarFileDataSinkTest.java | 23 +++++++++---------- .../kunai/source/AbstractDataSourceTest.java | 6 ++--- .../kunai/source/ClassFileDataSourceTest.java | 18 +++++++-------- .../kunai/source/DirectoryDataSourceTest.java | 18 +++++++-------- .../kunai/source/FilteredDataSourceTest.java | 18 +++++++-------- .../kunai/source/JarFileDataSourceTest.java | 18 +++++++-------- .../kunai/source/WarFileDataSourceTest.java | 18 +++++++-------- .../cafebabe/pochi/BirthmarkSystemHelper.java | 8 +++---- .../KGramBasedBirthmarkExtractorTest.java | 4 ++-- .../uc/FUCBirthmarkExtractorTest.java | 6 ++--- .../uc/UCBirthmarkExtractorTest.java | 4 ++-- .../VerbsOfMethodsBirthmarkExtractorTest.java | 4 ++-- 21 files changed, 100 insertions(+), 103 deletions(-) diff --git a/kunai2/README.md b/kunai2/README.md index d1c660e1..7c4a94e2 100644 --- a/kunai2/README.md +++ b/kunai2/README.md @@ -9,11 +9,11 @@ Kunai2 implemented for Java 8 and used streaming API. ```java // Reading Path sourcePath = Paths.get("path/of/source/file/or/directory"); -DataSourceFactory sourceFactory = new DefaultDataSourceFactory(); +DataSourceFactory sourceFactory = DataSourceFactory.instance(); try(DataSource source = sourceFactory.build(sourcePath)){ // Storing Path outputPath = Paths.get("path/of/output/file.jar"); - DataSinkFactory sinkFactory = new DefaultDataSinkFactory(); + DataSinkFactory sinkFactory = DataSinkFactory.instance(); try(DataSink sink = sinkFactory.build(outputPath)){ sink.consume(source); // above lines means following code. diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/Demo.java b/kunai2/src/main/java/jp/cafebabe/kunai/Demo.java index 9727b49b..a8db7a5c 100644 --- a/kunai2/src/main/java/jp/cafebabe/kunai/Demo.java +++ b/kunai2/src/main/java/jp/cafebabe/kunai/Demo.java @@ -3,9 +3,9 @@ import java.nio.file.Paths; import jp.cafebabe.kunai.sink.DataSink; -import jp.cafebabe.kunai.sink.factories.DefaultDataSinkFactory; +import jp.cafebabe.kunai.sink.factories.DataSinkFactory; import jp.cafebabe.kunai.source.DataSource; -import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory; +import jp.cafebabe.kunai.source.factories.DataSourceFactory; public class Demo { public Demo(String[] args) throws Exception{ @@ -13,8 +13,8 @@ public Demo(String[] args) throws Exception{ } private void copy(String from, String to) throws Exception{ - try(DataSource source = new DefaultDataSourceFactory().build(Paths.get(from)); - DataSink sink = new DefaultDataSinkFactory().create(Paths.get(to))){ + try(DataSource source = DataSourceFactory.instance().build(Paths.get(from)); + DataSink sink = DataSinkFactory.instance().create(Paths.get(to))) { copy(source, sink); } } diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DataSinkFactory.java b/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DataSinkFactory.java index 122d3f45..3a106665 100644 --- a/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DataSinkFactory.java +++ b/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DataSinkFactory.java @@ -8,4 +8,8 @@ public interface DataSinkFactory { DataSink create(Path path); boolean isTarget(Path path); + + static DataSinkFactory instance() { + return new DefaultDataSinkFactory(); + } } diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DefaultDataSinkFactory.java b/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DefaultDataSinkFactory.java index 1607f111..c08da6ef 100644 --- a/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DefaultDataSinkFactory.java +++ b/kunai2/src/main/java/jp/cafebabe/kunai/sink/factories/DefaultDataSinkFactory.java @@ -11,7 +11,7 @@ import jp.cafebabe.kunai.sink.JarFileDataSink; import jp.cafebabe.kunai.sink.WarFileDataSink; -public class DefaultDataSinkFactory implements DataSinkFactory{ +class DefaultDataSinkFactory implements DataSinkFactory{ private List factories = new ArrayList<>(); public DefaultDataSinkFactory(){ diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DataSourceFactory.java b/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DataSourceFactory.java index cc12f007..eaec0074 100644 --- a/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DataSourceFactory.java +++ b/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DataSourceFactory.java @@ -35,4 +35,8 @@ default DataSource build(Path path) throws KunaiException{ default DataSource build(File file) throws KunaiException{ return build(file.toPath()); } + + static DataSourceFactory instance() { + return new DefaultDataSourceFactory(); + } } diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DefaultDataSourceFactory.java b/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DefaultDataSourceFactory.java index 12866eb8..93896dee 100644 --- a/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DefaultDataSourceFactory.java +++ b/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/DefaultDataSourceFactory.java @@ -9,7 +9,7 @@ import jp.cafebabe.kunai.entries.KunaiException; import jp.cafebabe.kunai.source.DataSource; -public class DefaultDataSourceFactory implements DataSourceFactory{ +class DefaultDataSourceFactory implements DataSourceFactory{ private DataSourceFactories factories = new DataSourceFactories(); @Override diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/package-info.java b/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/package-info.java index 44c6646b..e468025c 100644 --- a/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/package-info.java +++ b/kunai2/src/main/java/jp/cafebabe/kunai/source/factories/package-info.java @@ -4,7 +4,7 @@ * Typical usage is: *
  * Path path = Paths.get("some/data/source/path");
- * DataSourceFactory factory = DefaultDataSourceFactory();
+ * DataSourceFactory factory = DataSourceFactory.instance();
  * try(DataSource source = factory.build(path)){
  *     source.stream()
  *         .forEach(entry ->
diff --git a/kunai2/src/main/java/module-info.java b/kunai2/src/main/java/module-info.java
index 0d2d226b..e350ca19 100644
--- a/kunai2/src/main/java/module-info.java
+++ b/kunai2/src/main/java/module-info.java
@@ -1,7 +1,7 @@
 import jp.cafebabe.kunai.sink.DataSink;
-import jp.cafebabe.kunai.sink.factories.DefaultDataSinkFactory;
+import jp.cafebabe.kunai.sink.factories.DataSinkFactory;
 import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
 
 /**
  * 

@@ -15,8 +15,8 @@ * *

  * public void copy(String from, String to) throws Exception {
- *     try({@link DataSource} source = new {@link DefaultDataSourceFactory}().build(Paths.get(from));
- *             {@link DataSink} sink = new {@link DefaultDataSinkFactory}().create(Paths.get(to))){
+ *     try({@link DataSource} source = {@link DataSourceFactory}.instance().build(Paths.get(from));
+ *             {@link DataSink} sink = {@link DataSinkFactory}.instance().create(Paths.get(to))){
  *         copy(source, sink);
  *     }
  * }
@@ -33,6 +33,7 @@
 
     exports jp.cafebabe.kunai.entries;
     exports jp.cafebabe.kunai.sink;
+    exports jp.cafebabe.kunai.sink.factories;
     exports jp.cafebabe.kunai.source;
     exports jp.cafebabe.kunai.source.factories;
 }
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/sink/DirectoryDataSinkTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/sink/DirectoryDataSinkTest.java
index 720f5b1b..fdfccbaf 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/sink/DirectoryDataSinkTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/sink/DirectoryDataSinkTest.java
@@ -1,27 +1,26 @@
 package jp.cafebabe.kunai.sink;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.DataSource;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import jp.cafebabe.kunai.util.PathHelper;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
-import jp.cafebabe.kunai.util.PathHelper;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 public class DirectoryDataSinkTest {
     @Before
     public void setUp() throws Exception{
         Path path = Paths.get("target/test-classes/hello/target/hello-1.0-SNAPSHOT.jar");
-        try(DataSource source = new DefaultDataSourceFactory().build(path)){
+        try(DataSource source = DataSourceFactory.instance().build(path)){
             try(DataSink sink = new DirectoryDataSink(Paths.get("dir"))){
                 sink.consume(source);
             }
@@ -30,7 +29,7 @@ public void setUp() throws Exception{
 
     @Test
     public void testCreatedDirectory() throws Exception{
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get("dir"));
+        DataSource source = DataSourceFactory.instance().build(Paths.get("dir"));
 
         List list = new ArrayList<>();
         source.forEach(entry -> list.add(entry));
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/sink/JarFileDataSinkTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/sink/JarFileDataSinkTest.java
index 52e5a9eb..41d3704d 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/sink/JarFileDataSinkTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/sink/JarFileDataSinkTest.java
@@ -1,7 +1,10 @@
 package jp.cafebabe.kunai.sink;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.DataSource;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import org.junit.After;
+import org.junit.Test;
 
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -9,24 +12,20 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.junit.After;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 public class JarFileDataSinkTest {
     @Test
     public void testCreatedJarFile() throws Exception{
         Path path = Paths.get("target/test-classes/hello/target/classes/");
-        try(DataSource source = new DefaultDataSourceFactory().build(path)){
+        try(DataSource source = DataSourceFactory.instance().build(path)){
             try(DataSink sink = new JarFileDataSink(Paths.get("hoge.jar"))){
                 sink.consume(source);
             }
         }
 
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get("hoge.jar"));
+        DataSource source = DataSourceFactory.instance().build(Paths.get("hoge.jar"));
 
         List list = new ArrayList<>();
         source.forEach(entry -> list.add(entry));
@@ -37,13 +36,13 @@ public void testCreatedJarFile() throws Exception{
     @Test
     public void testJarFromJar() throws Exception{
         Path path = Paths.get("target/test-classes/hello/target/hello-1.0-SNAPSHOT.jar");
-        try(DataSource source = new DefaultDataSourceFactory().build(path)){
+        try(DataSource source = DataSourceFactory.instance().build(path)){
             try(DataSink sink = new JarFileDataSink(Paths.get("hoge.jar"))){
                 sink.consume(source);
             }
         }
 
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get("hoge.jar"));
+        DataSource source = DataSourceFactory.instance().build(Paths.get("hoge.jar"));
 
         List list = new ArrayList<>();
         source.forEach(entry -> list.add(entry));
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/source/AbstractDataSourceTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/source/AbstractDataSourceTest.java
index 9e5084ce..8492e390 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/source/AbstractDataSourceTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/source/AbstractDataSourceTest.java
@@ -1,11 +1,11 @@
 package jp.cafebabe.kunai.source;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import org.junit.Test;
 
 import java.nio.file.Paths;
 
-import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 public class AbstractDataSourceTest{
     @Test
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/source/ClassFileDataSourceTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/source/ClassFileDataSourceTest.java
index 9ae02403..f5f2c246 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/source/ClassFileDataSourceTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/source/ClassFileDataSourceTest.java
@@ -1,18 +1,16 @@
 package jp.cafebabe.kunai.source;
 
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.ClassName;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.Before;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.ClassName;
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.factories.DataSourceFactory;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 public class ClassFileDataSourceTest {
     private Path path;
@@ -24,7 +22,7 @@ public void setUp(){
 
     @Test
     public void testDataSource() throws Exception{
-        DataSourceFactory factory = new DefaultDataSourceFactory();
+        DataSourceFactory factory = DataSourceFactory.instance();
 
         assertThat(factory.isTarget(path), is(true));
 
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/source/DirectoryDataSourceTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/source/DirectoryDataSourceTest.java
index 5395a803..0c9a4aa4 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/source/DirectoryDataSourceTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/source/DirectoryDataSourceTest.java
@@ -1,18 +1,16 @@
 package jp.cafebabe.kunai.source;
 
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.ClassName;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.Before;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.ClassName;
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.factories.DataSourceFactory;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 public class DirectoryDataSourceTest {
     private Path path;
@@ -24,7 +22,7 @@ public void setUp(){
 
     @Test
     public void testDataSource() throws Exception{
-        DataSourceFactory factory = new DefaultDataSourceFactory();
+        DataSourceFactory factory = DataSourceFactory.instance();
 
         assertThat(factory.isTarget(path), is(true));
 
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/source/FilteredDataSourceTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/source/FilteredDataSourceTest.java
index 99af23c6..90eb87b3 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/source/FilteredDataSourceTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/source/FilteredDataSourceTest.java
@@ -1,18 +1,16 @@
 package jp.cafebabe.kunai.source;
 
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.ClassName;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.Before;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.ClassName;
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.factories.DataSourceFactory;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 public class FilteredDataSourceTest {
     private Path path;
@@ -24,7 +22,7 @@ public void setUp(){
 
     @Test
     public void testDataSource() throws Exception{
-        DataSourceFactory factory = new DefaultDataSourceFactory();
+        DataSourceFactory factory = DataSourceFactory.instance();
 
         try(DataSource source = factory.build(path).filter(entry -> entry.endsWith("World.class"))){
             Entry[] entries = source.stream()
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/source/JarFileDataSourceTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/source/JarFileDataSourceTest.java
index bdf6e1dc..cbc4791c 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/source/JarFileDataSourceTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/source/JarFileDataSourceTest.java
@@ -1,18 +1,16 @@
 package jp.cafebabe.kunai.source;
 
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.ClassName;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.Before;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.ClassName;
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.factories.DataSourceFactory;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 public class JarFileDataSourceTest {
     private Path path;
@@ -24,7 +22,7 @@ public void setUp(){
 
     @Test
     public void testDataSource() throws Exception{
-        DataSourceFactory factory = new DefaultDataSourceFactory();
+        DataSourceFactory factory = DataSourceFactory.instance();
 
         assertThat(factory.isTarget(path), is(true));
 
diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/source/WarFileDataSourceTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/source/WarFileDataSourceTest.java
index 00b2c57e..e7d40a13 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/source/WarFileDataSourceTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/source/WarFileDataSourceTest.java
@@ -1,18 +1,16 @@
 package jp.cafebabe.kunai.source;
 
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import jp.cafebabe.kunai.entries.ClassName;
+import jp.cafebabe.kunai.entries.Entry;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.Before;
-import org.junit.Test;
-
-import jp.cafebabe.kunai.entries.ClassName;
-import jp.cafebabe.kunai.entries.Entry;
-import jp.cafebabe.kunai.source.factories.DataSourceFactory;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 public class WarFileDataSourceTest {
     private Path path;
@@ -24,7 +22,7 @@ public void setUp(){
 
     @Test
     public void testDataSource() throws Exception{
-        DataSourceFactory factory = new DefaultDataSourceFactory();
+        DataSourceFactory factory = DataSourceFactory.instance();
 
         assertThat(factory.isTarget(path), is(true));
 
diff --git a/pochi-core/src/main/java/jp/cafebabe/pochi/BirthmarkSystemHelper.java b/pochi-core/src/main/java/jp/cafebabe/pochi/BirthmarkSystemHelper.java
index acca41e2..777f2590 100644
--- a/pochi-core/src/main/java/jp/cafebabe/pochi/BirthmarkSystemHelper.java
+++ b/pochi-core/src/main/java/jp/cafebabe/pochi/BirthmarkSystemHelper.java
@@ -13,11 +13,11 @@
 import jp.cafebabe.birthmarks.pairs.PairMatcher;
 import jp.cafebabe.birthmarks.pairs.PairMatcherBuilder;
 import jp.cafebabe.birthmarks.pairs.PairMatcherType;
-import jp.cafebabe.pochi.pairs.PairMatcherBuilders;
-import jp.cafebabe.pochi.parsers.DefaultParser;
 import jp.cafebabe.kunai.entries.KunaiException;
 import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
+import jp.cafebabe.pochi.pairs.PairMatcherBuilders;
+import jp.cafebabe.pochi.parsers.DefaultParser;
 
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -50,7 +50,7 @@ public Configuration config() {
     }
 
     public DataSource source(String path) throws KunaiException {
-        return new DefaultDataSourceFactory()
+        return DataSourceFactory.instance()
                 .build(Paths.get(path));
     }
 
diff --git a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/kgram/KGramBasedBirthmarkExtractorTest.java b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/kgram/KGramBasedBirthmarkExtractorTest.java
index 92a54ed7..d0a352fd 100644
--- a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/kgram/KGramBasedBirthmarkExtractorTest.java
+++ b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/kgram/KGramBasedBirthmarkExtractorTest.java
@@ -8,7 +8,7 @@
 import jp.cafebabe.birthmarks.extractors.ExtractorBuilder;
 import jp.cafebabe.kunai.entries.ClassName;
 import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
 import jp.cafebabe.pochi.extractors.ExtractorBuilders;
 import org.junit.Test;
 import org.objectweb.asm.Opcodes;
@@ -26,7 +26,7 @@ public class KGramBasedBirthmarkExtractorTest {
     public Birthmarks extract(String path, String type) throws Exception{
         URL location = getClass().getResource(path);
         ExtractorBuilder builder = new ExtractorBuilders().builder(BirthmarkType.of(type));
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get(location.toURI()));
+        DataSource source = DataSourceFactory.instance().build(Paths.get(location.toURI()));
         Extractor extractor = builder.build(new ConfigurationBuilder().configuration());
         return extractor.extract(source);
     }
diff --git a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java
index f5a95762..7914682a 100644
--- a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java
+++ b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/FUCBirthmarkExtractorTest.java
@@ -8,7 +8,7 @@
 import jp.cafebabe.birthmarks.extractors.Extractor;
 import jp.cafebabe.kunai.entries.ClassName;
 import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
 import org.junit.Test;
 
 import java.net.URL;
@@ -17,16 +17,16 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
 
 public class FUCBirthmarkExtractorTest {
     public Birthmarks extract(String path) throws Exception{
         URL location = getClass().getResource(path);
         Configuration config = new ConfigurationBuilder().configuration();
         Extractor extractor = new FUCBirthmarkExtractorBuilder().build(config);
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get(location.toURI()));
+        DataSource source = DataSourceFactory.instance().build(Paths.get(location.toURI()));
         return extractor.extract(source);
     }
 
diff --git a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/UCBirthmarkExtractorTest.java b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/UCBirthmarkExtractorTest.java
index c1c2ea78..4da8080a 100644
--- a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/UCBirthmarkExtractorTest.java
+++ b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/uc/UCBirthmarkExtractorTest.java
@@ -7,7 +7,7 @@
 import jp.cafebabe.birthmarks.extractors.Extractor;
 import jp.cafebabe.kunai.entries.ClassName;
 import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
 import org.junit.Test;
 
 import java.net.URL;
@@ -24,7 +24,7 @@ public Birthmarks extract(String path) throws Exception{
         URL location = getClass().getResource(path);
         Configuration config = new ConfigurationBuilder().configuration();
         Extractor extractor = new UCBirthmarkExtractorBuilder().build(config);
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get(location.toURI()));
+        DataSource source = DataSourceFactory.instance().build(Paths.get(location.toURI()));
         return extractor.extract(source);
     }
 
diff --git a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/verbs/VerbsOfMethodsBirthmarkExtractorTest.java b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/verbs/VerbsOfMethodsBirthmarkExtractorTest.java
index e808eec6..273cdd10 100644
--- a/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/verbs/VerbsOfMethodsBirthmarkExtractorTest.java
+++ b/pochi-core/src/test/java/jp/cafebabe/pochi/birthmarks/verbs/VerbsOfMethodsBirthmarkExtractorTest.java
@@ -7,7 +7,7 @@
 import jp.cafebabe.birthmarks.extractors.Extractor;
 import jp.cafebabe.kunai.entries.ClassName;
 import jp.cafebabe.kunai.source.DataSource;
-import jp.cafebabe.kunai.source.factories.DefaultDataSourceFactory;
+import jp.cafebabe.kunai.source.factories.DataSourceFactory;
 import org.junit.Test;
 
 import java.net.URL;
@@ -24,7 +24,7 @@ public Birthmarks extract(String path) throws Exception{
         URL location = getClass().getResource(path);
         Configuration config = new ConfigurationBuilder().configuration();
         Extractor extractor = new VerbsOfMethodsExtractorBuilder().build(config);
-        DataSource source = new DefaultDataSourceFactory().build(Paths.get(location.toURI()));
+        DataSource source = DataSourceFactory.instance().build(Paths.get(location.toURI()));
         return extractor.extract(source);
     }
 

From f8904695976c43a8bf0b3cc71c293039d9c904e8 Mon Sep 17 00:00:00 2001
From: Haruaki TAMADA 
Date: Wed, 8 Dec 2021 15:33:12 +0900
Subject: [PATCH 7/8] update unit test

---
 .../jp/cafebabe/kunai/entries/NameTest.java     | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/kunai2/src/test/java/jp/cafebabe/kunai/entries/NameTest.java b/kunai2/src/test/java/jp/cafebabe/kunai/entries/NameTest.java
index ab68f0d8..6be1cc26 100644
--- a/kunai2/src/test/java/jp/cafebabe/kunai/entries/NameTest.java
+++ b/kunai2/src/test/java/jp/cafebabe/kunai/entries/NameTest.java
@@ -26,4 +26,21 @@ public void testBasic(){
         assertThat(name.toString(), is("Haruaki Tamada"));
         assertThat(name.name(), is("Haruaki Tamada"));
     }
+
+    @Test
+    public void testMatch() {
+        assertThat(name.matches("H.*Tamada"), is(true));
+        assertThat(name.matches("tamada"), is(false));
+        assertThat(name.contains("ki Ta"), is(true));
+        assertThat(name.endsWith("a"), is(true));
+        assertThat(name.startsWith("H"), is(true));
+    }
+
+    @Test
+    public void testEquals() {
+        assertThat(name.equals(new Name("Haruaki Tamada")), is(true));
+        assertThat(name.equals(new Name("Different Name")), is(false));
+        assertThat(name.equals(new Object()), is(false));
+        assertThat(name.equals(null), is(false));
+    }
 }

From 5dfbe7a241fa4dbed6aa59b4711d2d763f40eea1 Mon Sep 17 00:00:00 2001
From: Haruaki TAMADA 
Date: Mon, 13 Dec 2021 13:57:13 +0900
Subject: [PATCH 8/8] feat: add new constructor receives the cause Exception

---
 .../main/java/jp/cafebabe/kunai/entries/KunaiException.java    | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kunai2/src/main/java/jp/cafebabe/kunai/entries/KunaiException.java b/kunai2/src/main/java/jp/cafebabe/kunai/entries/KunaiException.java
index c65eb9d7..c91a0000 100644
--- a/kunai2/src/main/java/jp/cafebabe/kunai/entries/KunaiException.java
+++ b/kunai2/src/main/java/jp/cafebabe/kunai/entries/KunaiException.java
@@ -7,4 +7,7 @@ public KunaiException(String message) {
         super(message);
     }
 
+    public KunaiException(Exception e) {
+        super(e);
+    }
 }