* 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/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)); + } } 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")); Listlist = 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-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 @@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 jp.cafebabe.pochi kunai2 -2.5.2 +2.6.0 compile > 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..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 @@ -1,23 +1,33 @@ package jp.cafebabe.birthmarks.entities; import java.io.Serializable; +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; 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 Optional > unify() { + return BirthmarksMerger.unifyTo(this); } public Stream > find(ClassName name) { @@ -29,6 +39,10 @@ public Stream > stream() { return list.stream(); } + public Stream exceptionStream() { + return exceptions.stream(); + } + public long count() { return list.size(); } @@ -39,13 +53,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/BirthmarksMerger.java b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java new file mode 100644 index 00000000..6b9fa989 --- /dev/null +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/entities/BirthmarksMerger.java @@ -0,0 +1,60 @@ +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.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/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/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..2df7b427 --- /dev/null +++ b/pochi-api/src/main/java/jp/cafebabe/birthmarks/utils/LongestCommonSubstring.java @@ -0,0 +1,44 @@ +package jp.cafebabe.birthmarks.utils; + +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; + private int 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 12a704bf..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; @@ -26,7 +27,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 +60,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)); @@ -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("")); + } +} 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 @@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 pochi-core -2.5.2 +2.6.0 compile 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 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/main/java/jp/cafebabe/pochi/Pochi.java b/pochi-core/src/main/java/jp/cafebabe/pochi/Pochi.java index 15d3fa90..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; @@ -22,7 +22,7 @@ public static final Path home() { } private static List jp.cafebabe.pochi pochi-api -2.5.2 +2.6.0 compile 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/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 70a65647..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); } @@ -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(" ", + " ", " "))); } } 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); } diff --git a/pom.xml b/pom.xml index 86f35a5f..d991d0b4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ jp.cafebabe pochi -2.5.2 +2.6.0 pom @@ -228,7 +228,7 @@ org.jacoco jacoco-maven-plugin -0.8.6 +0.8.7 prepare-agent 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