From b45309968b7345d8830688c7d4ca32de97eb7627 Mon Sep 17 00:00:00 2001 From: MarcGuiot Date: Tue, 1 Oct 2024 22:13:32 +0200 Subject: [PATCH] Add GlobTypeBuilder.declareFrom to not duplicate annotations => WARN : FieldName annotation is not replaced. --- .../core/metamodel/GlobTypeBuilder.java | 2 + .../metamodel/fields/impl/AbstractField.java | 2 - .../impl/DefaultGlobUnionArrayField.java | 14 +++-- .../fields/impl/DefaultGlobUnionField.java | 14 +++-- .../metamodel/impl/DefaultAnnotations.java | 7 +++ .../impl/DefaultGlobTypeBuilder.java | 56 +++++++++++++++++++ .../container/hash/Hash4ElementContainer.java | 15 +++++ .../utils/container/hash/HashContainer.java | 4 +- .../container/hash/HashEmptyContainer.java | 4 ++ .../container/hash/HashMapContainer.java | 8 +++ .../hash/HashOneElementContainer.java | 4 ++ .../hash/HashTwoElementContainer.java | 11 ++++ .../specific/Hash4GlobKeyContainer.java | 11 ++++ .../specific/HashEmptyGlobContainer.java | 4 ++ .../specific/HashMapGlobKeyContainer.java | 23 ++++++++ .../specific/HashOneGlobKeyContainer.java | 8 +++ .../specific/HashTwoGlobKeyContainer.java | 13 ++++- 17 files changed, 183 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/globsframework/core/metamodel/GlobTypeBuilder.java b/src/main/java/org/globsframework/core/metamodel/GlobTypeBuilder.java index 34ac9ad..48acbd6 100644 --- a/src/main/java/org/globsframework/core/metamodel/GlobTypeBuilder.java +++ b/src/main/java/org/globsframework/core/metamodel/GlobTypeBuilder.java @@ -92,6 +92,8 @@ public interface GlobTypeBuilder { Field declare(String fieldName, DataType dataType, Collection annotations); + Field declareFrom(String fieldName, Field field); + default GlobTypeBuilder addStringField(String fieldName, Glob... annotations) { return addStringField(fieldName, Arrays.asList(annotations)); } diff --git a/src/main/java/org/globsframework/core/metamodel/fields/impl/AbstractField.java b/src/main/java/org/globsframework/core/metamodel/fields/impl/AbstractField.java index c2bfdd0..c0e7dc2 100644 --- a/src/main/java/org/globsframework/core/metamodel/fields/impl/AbstractField.java +++ b/src/main/java/org/globsframework/core/metamodel/fields/impl/AbstractField.java @@ -10,8 +10,6 @@ import org.globsframework.core.utils.container.hash.HashContainer; import org.globsframework.core.utils.exceptions.InvalidParameter; -import java.util.LinkedHashMap; - abstract public class AbstractField extends DefaultAnnotations { private final int index; private final int keyIndex; diff --git a/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionArrayField.java b/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionArrayField.java index 443459d..838d165 100644 --- a/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionArrayField.java +++ b/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionArrayField.java @@ -10,25 +10,27 @@ import org.globsframework.core.utils.exceptions.UnexpectedApplicationState; import java.util.Collection; +import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; public class DefaultGlobUnionArrayField extends AbstractField implements GlobArrayUnionField { - private final Map targetTypes; + private volatile Map targetTypes; public DefaultGlobUnionArrayField(String name, GlobType globType, Collection targetTypes, int index, boolean isKeyField, final int keyIndex, HashContainer annotations) { super(name, globType, Glob[].class, index, keyIndex, isKeyField, null, DataType.GlobUnionArray, annotations); - this.targetTypes = new ConcurrentHashMap<>(); - targetTypes.forEach(this::__add__); + this.targetTypes = new HashMap<>(); + targetTypes.forEach(type -> this.targetTypes.put(type.getName(), type)); } public Collection getTargetTypes() { return targetTypes.values(); } - public void __add__(GlobType t) { - this.targetTypes.put(t.getName(), t); + synchronized public void __add__(GlobType t) { + Map tmp = new HashMap<>(targetTypes); + tmp.put(t.getName(), t); + targetTypes = tmp; } public GlobType getTargetType(String name) { diff --git a/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionField.java b/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionField.java index fa75fd1..b0da667 100644 --- a/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionField.java +++ b/src/main/java/org/globsframework/core/metamodel/fields/impl/DefaultGlobUnionField.java @@ -10,25 +10,27 @@ import org.globsframework.core.utils.exceptions.UnexpectedApplicationState; import java.util.Collection; +import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; public class DefaultGlobUnionField extends AbstractField implements GlobUnionField { - private final Map targetTypes; + private volatile Map targetTypes; public DefaultGlobUnionField(String name, GlobType globType, Collection targetTypes, int index, boolean isKeyField, final int keyIndex, HashContainer annotations) { super(name, globType, Glob.class, index, keyIndex, isKeyField, null, DataType.GlobUnion, annotations); - this.targetTypes = new ConcurrentHashMap<>(); - targetTypes.forEach(this::__add__); + this.targetTypes = new HashMap<>(); + targetTypes.forEach(type -> this.targetTypes.put(type.getName(), type)); } public Collection getTargetTypes() { return targetTypes.values(); } - public void __add__(GlobType t) { - this.targetTypes.put(t.getName(), t); + synchronized public void __add__(GlobType t) { + Map tmp = new HashMap<>(targetTypes); + tmp.put(t.getName(), t); + targetTypes = tmp; } public GlobType getTargetType(String name) { diff --git a/src/main/java/org/globsframework/core/metamodel/impl/DefaultAnnotations.java b/src/main/java/org/globsframework/core/metamodel/impl/DefaultAnnotations.java index 736b6f8..dd7058e 100644 --- a/src/main/java/org/globsframework/core/metamodel/impl/DefaultAnnotations.java +++ b/src/main/java/org/globsframework/core/metamodel/impl/DefaultAnnotations.java @@ -56,6 +56,9 @@ public DefaultAnnotations(Collection annotations) { } } + // annotations.size() + 1 can be false if the glob key is already present + // but annotations is expected to not be changed + public MutableAnnotations addAnnotation(Glob glob) { if (glob != null) { synchronized (this) { @@ -103,4 +106,8 @@ public Glob getAnnotation(Key key) { public Glob findAnnotation(Key key) { return annotations.get(key); } + + HashContainer getInternal() { + return annotations; + } } diff --git a/src/main/java/org/globsframework/core/metamodel/impl/DefaultGlobTypeBuilder.java b/src/main/java/org/globsframework/core/metamodel/impl/DefaultGlobTypeBuilder.java index f287c9b..e2d58a7 100644 --- a/src/main/java/org/globsframework/core/metamodel/impl/DefaultGlobTypeBuilder.java +++ b/src/main/java/org/globsframework/core/metamodel/impl/DefaultGlobTypeBuilder.java @@ -11,6 +11,7 @@ import org.globsframework.core.utils.container.hash.HashContainer; import org.globsframework.core.utils.container.specific.HashEmptyGlobContainer; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; @@ -454,6 +455,61 @@ public Field declare(String fieldName, DataType dataType, Collection annot throw new RuntimeException("creation of " + dataType + " not possible without additional parameter (globType)"); } + /* + TODO : remove annotations FieldName, Index, DefaultValue from annotations : it is a duplication. + Or replace them here with the + */ + + public Field declareFrom(String name, Field field) { + boolean isKeyField = field.isKeyField(); + final HashContainer hashContainer = ((DefaultAnnotations) field).getInternal(); +// HashContainer duplicate = hashContainer.duplicate(); +// MutableGlob glob = FieldName.create(name); +// duplicate.put(glob.getKey(), glob); + + Field newField = switch (field.getDataType()) { + case String -> factory.addString(name, field.isKeyField(), keyIndex, index, + ((String) field.getDefaultValue()), hashContainer); + case StringArray -> factory.addStringArray(name, field.isKeyField(), keyIndex, index, hashContainer); + case Double -> + factory.addDouble(name, field.isKeyField(), keyIndex, index, ((Double) field.getDefaultValue()), + hashContainer); + case DoubleArray -> factory.addDoubleArray(name, field.isKeyField(), keyIndex, index, hashContainer); + case BigDecimal -> + factory.addBigDecimal(name, field.isKeyField(), keyIndex, index, ((BigDecimal) field.getDefaultValue()), + hashContainer); + case BigDecimalArray -> + factory.addBigDecimalArray(name, field.isKeyField(), keyIndex, index, hashContainer); + case Long -> factory.addLong(name, field.isKeyField(), keyIndex, index, ((Long) field.getDefaultValue()), + hashContainer); + case LongArray -> factory.addLongArray(name, field.isKeyField(), keyIndex, index, hashContainer); + case Integer -> + factory.addInteger(name, field.isKeyField(), keyIndex, index, ((Integer) field.getDefaultValue()), + hashContainer); + case IntegerArray -> factory.addIntegerArray(name, field.isKeyField(), keyIndex, index, hashContainer); + case Boolean -> + factory.addBoolean(name, field.isKeyField(), keyIndex, index, ((Boolean) field.getDefaultValue()), + hashContainer); + case BooleanArray -> factory.addBooleanArray(name, field.isKeyField(), keyIndex, index, hashContainer); + case Date -> factory.addDate(name, field.isKeyField(), keyIndex, index, hashContainer); + case DateTime -> factory.addDateTime(name, field.isKeyField(), keyIndex, index, hashContainer); + case Bytes -> factory.addBlob(name, index, hashContainer); + case Glob -> + factory.addGlob(name, ((GlobField) field).getTargetType(), isKeyField, keyIndex, index, hashContainer); + case GlobArray -> + factory.addGlobArray(name, ((GlobArrayField) field).getTargetType(), isKeyField, keyIndex, index, hashContainer); + case GlobUnion -> + factory.addGlobUnion(name, ((GlobUnionField) field).getTargetTypes(), index, hashContainer); + case GlobUnionArray -> + factory.addGlobArrayUnion(name, ((GlobUnionField) field).getTargetTypes(), index, hashContainer); + }; + index++; + if (isKeyField) { + keyIndex++; + } + return newField; + } + public void register(Class klass, T t) { type.register(klass, t); } diff --git a/src/main/java/org/globsframework/core/utils/container/hash/Hash4ElementContainer.java b/src/main/java/org/globsframework/core/utils/container/hash/Hash4ElementContainer.java index eee07f2..25f0402 100644 --- a/src/main/java/org/globsframework/core/utils/container/hash/Hash4ElementContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/hash/Hash4ElementContainer.java @@ -32,6 +32,17 @@ public Hash4ElementContainer(HashTwoElementContainer elementContainer, T k this.key4 = (T) HashOneElementContainer.NULL; } + public Hash4ElementContainer(Hash4ElementContainer tdHash4ElementContainer) { + key1 = tdHash4ElementContainer.key1; + value1 = tdHash4ElementContainer.value1; + key2 = tdHash4ElementContainer.key2; + value2 = tdHash4ElementContainer.value2; + key3 = tdHash4ElementContainer.key3; + value3 = tdHash4ElementContainer.value3; + key4 = tdHash4ElementContainer.key4; + value4 = tdHash4ElementContainer.value4; + } + public D get(T key) { return Utils.equalWithHash(key, this.key1) ? value1 : Utils.equalWithHash(key, this.key2) ? value2 : Utils.equalWithHash(key, this.key3) ? value3 : Utils.equalWithHash(key, this.key4) ? value4 : null; } @@ -120,6 +131,10 @@ public void remove() { }; } + public HashContainer duplicate() { + return new Hash4ElementContainer<>(this); + } + public TwoElementIterator entryIterator() { return new TwoElementIterator() { int i = 0; diff --git a/src/main/java/org/globsframework/core/utils/container/hash/HashContainer.java b/src/main/java/org/globsframework/core/utils/container/hash/HashContainer.java index c237b04..f1304a1 100644 --- a/src/main/java/org/globsframework/core/utils/container/hash/HashContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/hash/HashContainer.java @@ -21,6 +21,8 @@ static HashContainer empty() { Iterator values(); + HashContainer duplicate(); + TwoElementIterator entryIterator(); D remove(T value); @@ -31,7 +33,7 @@ static HashContainer empty() { boolean containsKey(T key); - default Stream stream(){ + default Stream stream() { return StreamSupport.stream(Spliterators.spliterator(values(), size(), Spliterator.NONNULL), false); } diff --git a/src/main/java/org/globsframework/core/utils/container/hash/HashEmptyContainer.java b/src/main/java/org/globsframework/core/utils/container/hash/HashEmptyContainer.java index 637975f..787db82 100644 --- a/src/main/java/org/globsframework/core/utils/container/hash/HashEmptyContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/hash/HashEmptyContainer.java @@ -21,6 +21,10 @@ public Iterator values() { return Collections.emptyIterator(); } + public HashContainer duplicate() { + return this; + } + public TwoElementIterator entryIterator() { return EmptyTwoElementIterator.INSTANCE; } diff --git a/src/main/java/org/globsframework/core/utils/container/hash/HashMapContainer.java b/src/main/java/org/globsframework/core/utils/container/hash/HashMapContainer.java index 6b7b7c8..b76e7f0 100644 --- a/src/main/java/org/globsframework/core/utils/container/hash/HashMapContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/hash/HashMapContainer.java @@ -16,6 +16,10 @@ public HashMapContainer(T key, D value) { elements.put(key, value); } + public HashMapContainer(HashMapContainer tdHashMapContainer) { + elements = new HashMap<>(tdHashMapContainer.elements); + } + public D get(T key) { return elements.get(key); } @@ -33,6 +37,10 @@ public Iterator values() { return elements.values().iterator(); } + public HashContainer duplicate() { + return new HashMapContainer<>(this); + } + public TwoElementIterator entryIterator() { return new TwoElementIterator() { Iterator> iterator = elements.entrySet().iterator(); diff --git a/src/main/java/org/globsframework/core/utils/container/hash/HashOneElementContainer.java b/src/main/java/org/globsframework/core/utils/container/hash/HashOneElementContainer.java index af12926..883be06 100644 --- a/src/main/java/org/globsframework/core/utils/container/hash/HashOneElementContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/hash/HashOneElementContainer.java @@ -45,6 +45,10 @@ public Iterator values() { return new OneStepIterator(); } + public HashContainer duplicate() { + return new HashOneElementContainer<>(this.key, this.value); + } + public TwoElementIterator entryIterator() { return new TwoElementIterator() { diff --git a/src/main/java/org/globsframework/core/utils/container/hash/HashTwoElementContainer.java b/src/main/java/org/globsframework/core/utils/container/hash/HashTwoElementContainer.java index 6b52734..107a25b 100644 --- a/src/main/java/org/globsframework/core/utils/container/hash/HashTwoElementContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/hash/HashTwoElementContainer.java @@ -23,6 +23,13 @@ public HashTwoElementContainer(HashOneElementContainer elementContainer, T this.value2 = value; } + public HashTwoElementContainer(HashTwoElementContainer tdHashTwoElementContainer) { + this.key1 = tdHashTwoElementContainer.getKey1(); + this.value1 = tdHashTwoElementContainer.getValue1(); + this.key2 = tdHashTwoElementContainer.getKey2(); + this.value2 = tdHashTwoElementContainer.getValue2(); + } + public D get(T key) { return Utils.equalWithHash(key, this.key1) ? value1 : Utils.equalWithHash(key, this.key2) ? value2 : null; } @@ -58,6 +65,10 @@ public Iterator values() { return new TwoStepIterator(); } + public HashContainer duplicate() { + return new HashTwoElementContainer<>(this); + } + public TwoElementIterator entryIterator() { return new TwoElementIterator() { int i = 0; diff --git a/src/main/java/org/globsframework/core/utils/container/specific/Hash4GlobKeyContainer.java b/src/main/java/org/globsframework/core/utils/container/specific/Hash4GlobKeyContainer.java index f048cac..3892b57 100644 --- a/src/main/java/org/globsframework/core/utils/container/specific/Hash4GlobKeyContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/specific/Hash4GlobKeyContainer.java @@ -17,6 +17,17 @@ public class Hash4GlobKeyContainer implements HashContainer { public Hash4GlobKeyContainer() { } + public Hash4GlobKeyContainer(Glob value1, Glob value2, Glob value3, Glob value4) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + } + + public HashContainer duplicate() { + return new Hash4GlobKeyContainer(value1, value2, value3, value4); + } + public Hash4GlobKeyContainer(HashTwoGlobKeyContainer elementContainer, Glob value) { value1 = elementContainer.getValue1(); value2 = elementContainer.getValue2(); diff --git a/src/main/java/org/globsframework/core/utils/container/specific/HashEmptyGlobContainer.java b/src/main/java/org/globsframework/core/utils/container/specific/HashEmptyGlobContainer.java index 969d398..002ca0e 100644 --- a/src/main/java/org/globsframework/core/utils/container/specific/HashEmptyGlobContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/specific/HashEmptyGlobContainer.java @@ -48,6 +48,10 @@ public Iterator values() { return Collections.emptyIterator(); } + public HashContainer duplicate() { + return this; + } + public TwoElementIterator entryIterator() { return EmptyTwoElementIterator.INSTANCE; } diff --git a/src/main/java/org/globsframework/core/utils/container/specific/HashMapGlobKeyContainer.java b/src/main/java/org/globsframework/core/utils/container/specific/HashMapGlobKeyContainer.java index 078c258..5667ac5 100644 --- a/src/main/java/org/globsframework/core/utils/container/specific/HashMapGlobKeyContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/specific/HashMapGlobKeyContainer.java @@ -5,6 +5,7 @@ import org.globsframework.core.utils.Utils; import org.globsframework.core.utils.container.hash.HashContainer; +import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; @@ -28,6 +29,11 @@ public HashMapGlobKeyContainer(int size) { this.values = new Values(roundUpToPowerOf2(size)); } + public HashMapGlobKeyContainer(HashMapGlobKeyContainer hashMapGlobKeyContainer) { + this.values = hashMapGlobKeyContainer.values.duplicate(); + size = hashMapGlobKeyContainer.size; + } + private static int roundUpToPowerOf2(int number) { int rounded; return (rounded = Integer.highestOneBit(number)) != 0 @@ -78,6 +84,10 @@ public Iterator values() { return iterate(values); } + public HashContainer duplicate() { + return new HashMapGlobKeyContainer(this); + } + public TwoElementIterator entryIterator() { final Iterator values = values(); return new KeyGlobTwoElementIterator(values); @@ -120,6 +130,19 @@ public Values(int size) { threshold = (int) (size * LOAD_FACTOR); } + public Values(Values org) { + this.values = Arrays.copyOf(org.values, org.values.length); + if (org.next != null) { + this.next = org.next.duplicate(); + } + count = org.count; + threshold = org.threshold; + } + + Values duplicate() { + return new Values(this); + } + public Glob getValue(int hash, Key key) { Glob glob = values[indexFor(hash, values.length)]; if (glob == null) { diff --git a/src/main/java/org/globsframework/core/utils/container/specific/HashOneGlobKeyContainer.java b/src/main/java/org/globsframework/core/utils/container/specific/HashOneGlobKeyContainer.java index e86b22d..2b5d6a9 100644 --- a/src/main/java/org/globsframework/core/utils/container/specific/HashOneGlobKeyContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/specific/HashOneGlobKeyContainer.java @@ -15,6 +15,10 @@ public class HashOneGlobKeyContainer implements HashContainer { public HashOneGlobKeyContainer() { } + public HashOneGlobKeyContainer(Glob value) { + this.value = value; + } + public HashOneGlobKeyContainer(Key key, Glob value) { checkEqual(key, value); this.value = value; @@ -51,6 +55,10 @@ public Iterator values() { return new OneStepIterator(); } + public HashContainer duplicate() { + return new HashOneGlobKeyContainer(value); + } + public TwoElementIterator entryIterator() { return new TwoElementIterator() { boolean isNext = value != null; diff --git a/src/main/java/org/globsframework/core/utils/container/specific/HashTwoGlobKeyContainer.java b/src/main/java/org/globsframework/core/utils/container/specific/HashTwoGlobKeyContainer.java index d733c72..85d2996 100644 --- a/src/main/java/org/globsframework/core/utils/container/specific/HashTwoGlobKeyContainer.java +++ b/src/main/java/org/globsframework/core/utils/container/specific/HashTwoGlobKeyContainer.java @@ -19,7 +19,12 @@ public HashTwoGlobKeyContainer() { public HashTwoGlobKeyContainer(HashOneGlobKeyContainer elementContainer, Glob value) { value1 = elementContainer.getValue(); - this.value2 = value; + value2 = value; + } + + public HashTwoGlobKeyContainer(HashTwoGlobKeyContainer hashTwoGlobKeyContainer) { + value1 = hashTwoGlobKeyContainer.getValue1(); + value2 = hashTwoGlobKeyContainer.getValue2(); } public Glob get(Key key) { @@ -57,6 +62,10 @@ public Iterator values() { return new TwoStepIterator(); } + public HashContainer duplicate() { + return new HashTwoGlobKeyContainer(this); + } + public TwoElementIterator entryIterator() { return new TwoElementIterator() { int i = 0; @@ -135,7 +144,7 @@ public > E forEach(E functor) { public boolean containsKey(Key key) { return value1 != null && Utils.equalWithHash(value1.getKey(), key) - || value2 != null && Utils.equalWithHash(value2.getKey(),key); + || value2 != null && Utils.equalWithHash(value2.getKey(), key); } public > E applyAndRemoveIfTrue(E functor) {