Skip to content

Commit

Permalink
add unify method to Birthmarks class
Browse files Browse the repository at this point in the history
  • Loading branch information
tamada committed Dec 2, 2021
1 parent cf57d32 commit de8d927
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,6 +26,10 @@ public Birthmarks(Stream<Either<Exception, Birthmark<T>>> stream) {
stream.forEach(either -> either.bimap(t -> exceptions.add(t), r -> list.add(r)));
}

public Optional<Birthmark<T>> unify() {
return BirthmarksMerger.unifyTo(this);
}

public Stream<Birthmark<T>> find(ClassName name) {
return list.stream()
.filter(birthmark -> birthmark.isSame(name));
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <T> Optional<Birthmark<T>> unify(Birthmarks<T> birthmarks) {
Optional<Elements<T>> elements = mergeElements(birthmarks);
Metadata metadata = mergeMetadata(birthmarks);
return elements.map(e -> new Birthmark<>(metadata, e));
}

private <T> Metadata mergeMetadata(Birthmarks<T> birthmarks) {
String location = findCommonLocation(birthmarks.stream());
return constructMetadata(location, findType(birthmarks));
}

private <T> Optional<BirthmarkType> findType(Birthmarks<T> birthmarks) {
return birthmarks.stream().map(b -> b.type())
.collect(Collectors.reducing((a, b) -> a));
}

private Metadata constructMetadata(String location, Optional<BirthmarkType> type) {
Try<URI> tryUri = Try.of(() -> new URI(location));
Optional<URI> uri = tryUri.toJavaOptional();
Optional<ClassName> name = uri.map(u -> new ClassName(findBaseName(u)));
return new Metadata(name.orElseGet(() -> new ClassName("<merged>")), 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 <T> String findCommonLocation(Stream<Birthmark<T>> stream) {
Optional<String> location = stream.map(birthmark -> birthmark.metadata())
.map(m -> m.location().toString())
.collect(Collectors.reducing((s1, s2) -> LongestCommonSubstring.of(s1, s2)));
return location.orElseGet(() -> "");
}

private <T> Optional<Elements<T>> mergeElements(Birthmarks<T> birthmarks) {
return birthmarks.stream()
.map(birthmark -> birthmark.elements())
.collect(Collectors.reducing((a, b) -> a.merge(b)));
}

public static <T> Optional<Birthmark<T>> unifyTo(Birthmarks<T> birthmarks) {
return new BirthmarksMerger().unify(birthmarks);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ protected Couple(L left, R right) {
this.right = Objects.requireNonNull(right);
}

public void applyIf(BiPredicate<L, R> predicate, BiConsumer<L, R> consumer) {
if(predicate.test(left, right))
consumer.accept(left, right);
}

public L left() {
return left;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
3 changes: 2 additions & 1 deletion pochi-api/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Birthmark<String>> optionalResult = birthmarks.unify();
if(optionalResult.isEmpty())
throw new InternalError();
Birthmark<String> result = optionalResult.get();
Elements<String> elements = result.elements();

assertThat(result.className(), is(new ClassName("source")));
assertThat(elements.size(), is(9));
}
}
Original file line number Diff line number Diff line change
@@ -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(""));
}
}

0 comments on commit de8d927

Please sign in to comment.