diff --git a/sfm-jmh/src/main/java/org/simpleflatmapper/csv/DiscriminatorBenchmark.java b/sfm-jmh/src/main/java/org/simpleflatmapper/csv/DiscriminatorBenchmark.java index 834451f35..0185c1e39 100644 --- a/sfm-jmh/src/main/java/org/simpleflatmapper/csv/DiscriminatorBenchmark.java +++ b/sfm-jmh/src/main/java/org/simpleflatmapper/csv/DiscriminatorBenchmark.java @@ -6,6 +6,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.infra.Blackhole; +import org.simpleflatmapper.util.Consumer; import java.io.File; import java.io.FileOutputStream; @@ -96,6 +97,76 @@ public void testWithDiscriminator(Blackhole blackhole) throws IOException { }); } + @Benchmark + public void testWithDiscriminatorWithKeys(Blackhole blackhole) throws IOException { + CsvParser.mapWith( + CsvMapperFactory.newInstance() + .discriminator(A.class, r -> r.getString(2), b -> { + for(int i = 1; i <= 40; i++) { + try { + b.when("typea" + i, Class.forName("org.simpleflatmapper.csv.DiscriminatorBenchmark$A" + i)); + } catch (ClassNotFoundException e) { + throw new Error(e); + } + } + }) + .discriminator(B.class, r -> r.getString(4), b -> { + for(int i = 1; i <= 20; i++) { + try { + b.when("typeb" + i, Class.forName("org.simpleflatmapper.csv.DiscriminatorBenchmark$B" + i)); + } catch (ClassNotFoundException e) { + throw new Error(e); + } + } + }) + .addKeys("id", "b_id", "b_c_id") + .newMapper(A.class) + ).stream(file, s -> { + s.forEach(blackhole::consume); + return null; + }); + } + + public void withDiscriminatorWithKeys(Consumer aConsumer) throws IOException { + CsvParser.mapWith( + CsvMapperFactory.newInstance() + .discriminator(A.class, r -> r.getString(2), b -> { + for(int i = 1; i <= 40; i++) { + try { + b.when("typea" + i, Class.forName("org.simpleflatmapper.csv.DiscriminatorBenchmark$A" + i)); + } catch (ClassNotFoundException e) { + throw new Error(e); + } + } + }) + .discriminator(B.class, r -> r.getString(4), b -> { + for(int i = 1; i <= 20; i++) { + try { + b.when("typeb" + i, Class.forName("org.simpleflatmapper.csv.DiscriminatorBenchmark$B" + i)); + } catch (ClassNotFoundException e) { + throw new Error(e); + } + } + }) + .addKeys("id", "b_id", "b_c_id") + .newMapper(A.class) + ).stream(file, s -> { + s.forEach(aConsumer); + return null; + }); + } + + + public static void main(String[] args) throws IOException { + DiscriminatorBenchmark db = new DiscriminatorBenchmark(); + db.setUp(); + + db.withDiscriminatorWithKeys(v -> { + System.out.println("v = " + v); + }); + + db.tearDown(); + } public static class A { public final Integer id; @@ -313,9 +384,6 @@ public B20(Integer id, String type, C c) { } } - public static void main(String[] args) { - System.out.println("A1.class.getName() = " + A1.class.getName()); - } public static class A1 extends A @@ -598,4 +666,6 @@ public A40(Integer id, String name, String type, B b) { super(id, name, type, b); } } + } + diff --git a/sfm-map/src/main/java/org/simpleflatmapper/map/context/KeyAndPredicate.java b/sfm-map/src/main/java/org/simpleflatmapper/map/context/KeyAndPredicate.java index 3261250e2..c44025086 100644 --- a/sfm-map/src/main/java/org/simpleflatmapper/map/context/KeyAndPredicate.java +++ b/sfm-map/src/main/java/org/simpleflatmapper/map/context/KeyAndPredicate.java @@ -16,11 +16,29 @@ public boolean test(S s) { return predicate == null ? true : predicate.test(s); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + KeyAndPredicate that = (KeyAndPredicate) o; + + if (!key.equals(that.key)) return false; + return predicate != null ? predicate.equals(that.predicate) : that.predicate == null; + } + + @Override + public int hashCode() { + int result = key.hashCode(); + result = 31 * result + (predicate != null ? predicate.hashCode() : 0); + return result; + } + public KeyAndPredicate mergeWith(KeyAndPredicate keyAndPredicate) { if (!this.key.equals(keyAndPredicate.key)) throw new IllegalArgumentException(); if (this.predicate == null || keyAndPredicate.predicate == null) { // null is equivalent to true - return new KeyAndPredicate(key, null); + return this; } if (this.predicate.equals(keyAndPredicate.predicate)) { diff --git a/sfm-map/src/main/java/org/simpleflatmapper/map/context/MappingContextFactoryBuilder.java b/sfm-map/src/main/java/org/simpleflatmapper/map/context/MappingContextFactoryBuilder.java index 1ff4b1037..3a3549748 100644 --- a/sfm-map/src/main/java/org/simpleflatmapper/map/context/MappingContextFactoryBuilder.java +++ b/sfm-map/src/main/java/org/simpleflatmapper/map/context/MappingContextFactoryBuilder.java @@ -75,6 +75,13 @@ public Predicate nullChecker() { } public MappingContextFactoryBuilder newBuilder(List> subKeys, PropertyMeta owner) { + // look for duplicate + for(MappingContextFactoryBuilder child : children) { + if (!subKeys.isEmpty() && child.keys.equals(subKeys) && owner.equals(owner)) { + return child; + } + } + MappingContextFactoryBuilder subBuilder = new MappingContextFactoryBuilder(counter, subKeys, keySourceGetter, this, owner); children.add(subBuilder); return subBuilder; diff --git a/sfm-map/src/main/java/org/simpleflatmapper/map/mapper/DefaultConstantSourceMapperBuilder.java b/sfm-map/src/main/java/org/simpleflatmapper/map/mapper/DefaultConstantSourceMapperBuilder.java index 53536afb1..30f52e671 100644 --- a/sfm-map/src/main/java/org/simpleflatmapper/map/mapper/DefaultConstantSourceMapperBuilder.java +++ b/sfm-map/src/main/java/org/simpleflatmapper/map/mapper/DefaultConstantSourceMapperBuilder.java @@ -1017,18 +1017,9 @@ public void accept(Type type, PropertyMeta propertyMeta) { } }).not; + if (not.isEmpty()) return null; - return new Predicate() { - @Override - public boolean test(S s) { - for(Predicate p : not) { - if (p.test(s)) { - return false; - } - } - return true; - } - }; + return new DiscriminatorKeyPredicate<>(not); } else if (propertyMeta.isSubProperty()) { SubPropertyMeta subPropertyMeta = (SubPropertyMeta) propertyMeta; @@ -1391,4 +1382,22 @@ public static String getterNotFoundErrorMessage(PropertyMapping propertyMapping) + " path " + currentPath + ". See " + CSFM_GETTER_NOT_FOUND.toUrl(); } + + private static class DiscriminatorKeyPredicate implements Predicate { + private final List> not; + + public DiscriminatorKeyPredicate(List> not) { + this.not = not; + } + + @Override + public boolean test(S s) { + for(Predicate p : not) { + if (p.test(s)) { + return false; + } + } + return true; + } + } } \ No newline at end of file