cdc.applic.dictionaries.impl.RefSynImpl Maven / Gradle / Ivy
Show all versions of cdc-applic-dictionaries-impl Show documentation
package cdc.applic.dictionaries.impl;
import java.io.PrintStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import cdc.applic.dictionaries.NamingConvention;
import cdc.applic.dictionaries.RefSyn;
import cdc.util.debug.ControlledPrintable;
import cdc.util.debug.Verbosity;
import cdc.util.lang.Checks;
import cdc.util.meta.BasicMetaData;
import cdc.util.meta.MetaData;
/**
* Implementation of {@link RefSyn}.
*
* @author Damien Carbonne
*
* @param The value type.
*/
public class RefSynImpl> implements RefSyn, ControlledPrintable {
private static final String CONVENTION = "convention";
/**
* The reference value.
*/
private final T reference;
/**
* (synonym, Set) map.
*
* Reference value is excluded.
*/
private final Map> synonymToConventions = new HashMap<>();
/**
* (NamingConvention, value) map.
*
* Default naming convention is included and is associated to {@code reference}.
*/
private final Map conventionToValue = new HashMap<>();
public RefSynImpl(T reference) {
this.reference = Checks.isNotNull(reference, "reference");
this.conventionToValue.put(NamingConvention.DEFAULT, reference);
}
public void addSynonym(T synonym,
NamingConvention convention) {
Checks.isNotNull(synonym, "synonym");
Checks.isNotNull(convention, CONVENTION);
Checks.isTrue(NamingConvention.DEFAULT != convention, "Can not associate a synonym to default convention.");
Checks.isFalse(Objects.equals(reference, synonym), "Can not associate a convention to the reference value.");
Checks.isFalse(conventionToValue.containsKey(convention), "A synonym is already associated to " + convention);
final Set conventions = synonymToConventions.computeIfAbsent(synonym, k -> new HashSet<>());
conventions.add(convention);
conventionToValue.put(convention, synonym);
}
public void removeSynonym(NamingConvention convention) {
Checks.isNotNull(convention, CONVENTION);
Checks.isTrue(NamingConvention.DEFAULT != convention, "Can not remove the value associated to default convention.");
// We known it is not the reference value
if (conventionToValue.containsKey(convention)) {
final T synonym = conventionToValue.get(convention);
final Set conventions = synonymToConventions.get(synonym);
conventions.remove(convention);
if (conventions.isEmpty()) {
synonymToConventions.remove(synonym);
}
conventionToValue.remove(convention);
}
}
@Override
public T getReferenceValue() {
return reference;
}
@Override
public Set getSynonyms() {
return synonymToConventions.keySet();
}
@Override
public Set getNamingConventions() {
return conventionToValue.keySet();
}
@Override
public Set getNonDefaultNamingConventions() {
final Set set = new HashSet<>(conventionToValue.keySet());
set.remove(NamingConvention.DEFAULT);
return set;
}
@Override
public boolean hasSynonyms() {
return !synonymToConventions.isEmpty();
}
@Override
public Set getNamingConventions(T value) {
if (synonymToConventions.containsKey(value)) {
return synonymToConventions.get(value);
} else if (Objects.equals(reference, value)) {
return DEFAULT_NAMING_CONVENTIONS;
} else {
return Collections.emptySet();
}
}
@Override
public T getValue(NamingConvention convention) {
return conventionToValue.getOrDefault(convention, reference);
}
@Override
public int hashCode() {
// Ignore other fields.
// This map contains all information
return conventionToValue.hashCode();
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof RefSynImpl)) {
return false;
}
final RefSynImpl> other = (RefSynImpl>) object;
// Ignore other fields
// This map contains all information
return conventionToValue.equals(other.conventionToValue);
}
@Override
public void print(PrintStream out,
int level,
Verbosity verbosity) {
for (final NamingConvention convention : getNamingConventions()) {
if (convention != NamingConvention.DEFAULT) {
indent(out, level);
out.print("synonym(");
out.print(getReferenceValue());
out.print("): ");
out.print(convention.getName());
out.print("->");
out.print(getValue(convention));
out.println();
}
}
}
public MetaData encode() {
if (hasSynonyms()) {
final BasicMetaData md = new BasicMetaData();
for (final NamingConvention convention : getNamingConventions()) {
if (convention != NamingConvention.DEFAULT) {
md.put(convention.getName().getNonEscapedLiteral(),
getValue(convention).toString());
}
}
return md;
} else {
return MetaData.EMPTY;
}
}
public void addSynonyms(MetaData meta,
Function namingConventionConstructor,
Function valueConstructor) {
for (final String key : meta.getKeys()) {
final NamingConvention convention = namingConventionConstructor.apply(key);
final T value = valueConstructor.apply(meta.get(key));
addSynonym(value, convention);
}
}
}