cdc.applic.dictionaries.impl.io.RepositoryXml Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cdc-applic-dictionaries-impl Show documentation
Show all versions of cdc-applic-dictionaries-impl Show documentation
Applicabilities Dictionaries Implementation.
The newest version!
package cdc.applic.dictionaries.impl.io;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import cdc.applic.dictionaries.Constraint;
import cdc.applic.dictionaries.Constraints;
import cdc.applic.dictionaries.DItemUsage;
import cdc.applic.dictionaries.Description;
import cdc.applic.dictionaries.Dictionary;
import cdc.applic.dictionaries.NamingConvention;
import cdc.applic.dictionaries.RefSyn;
import cdc.applic.dictionaries.bindings.AliasAliasBinding;
import cdc.applic.dictionaries.bindings.BindingRole;
import cdc.applic.dictionaries.bindings.BooleanBooleanBinding;
import cdc.applic.dictionaries.bindings.DItemsBinding;
import cdc.applic.dictionaries.bindings.DictionariesBinding;
import cdc.applic.dictionaries.bindings.PropertyPropertyBinding;
import cdc.applic.dictionaries.bindings.TypesBinding;
import cdc.applic.dictionaries.impl.AbstractDictionaryImpl;
import cdc.applic.dictionaries.impl.AliasImpl;
import cdc.applic.dictionaries.impl.BooleanTypeImpl;
import cdc.applic.dictionaries.impl.DescriptionImpl;
import cdc.applic.dictionaries.impl.DescriptionSetter;
import cdc.applic.dictionaries.impl.EnumeratedTypeImpl;
import cdc.applic.dictionaries.impl.EnumeratedValueImpl;
import cdc.applic.dictionaries.impl.IntegerTypeImpl;
import cdc.applic.dictionaries.impl.NamingConventionImpl;
import cdc.applic.dictionaries.impl.PatternTypeImpl;
import cdc.applic.dictionaries.impl.PolicyImpl;
import cdc.applic.dictionaries.impl.PropertyImpl;
import cdc.applic.dictionaries.impl.RealTypeImpl;
import cdc.applic.dictionaries.impl.RegistryImpl;
import cdc.applic.dictionaries.impl.RepositoryImpl;
import cdc.applic.dictionaries.impl.SynonymSetter;
import cdc.applic.dictionaries.impl.UserDefinedAssertionImpl;
import cdc.applic.dictionaries.impl.bindings.AbstractExtensionTypesBinding;
import cdc.applic.dictionaries.impl.bindings.BooleanEnumeratedBindingImpl;
import cdc.applic.dictionaries.impl.bindings.BooleanIntegerBindingImpl;
import cdc.applic.dictionaries.impl.bindings.DictionariesBindingImpl;
import cdc.applic.dictionaries.impl.bindings.EnumeratedBooleanBindingImpl;
import cdc.applic.dictionaries.impl.bindings.EnumeratedEnumeratedBindingImpl;
import cdc.applic.dictionaries.impl.bindings.EnumeratedIntegerBindingImpl;
import cdc.applic.dictionaries.impl.bindings.IntegerBooleanBindingImpl;
import cdc.applic.dictionaries.impl.bindings.IntegerEnumeratedBindingImpl;
import cdc.applic.dictionaries.impl.bindings.IntegerIntegerBindingImpl;
import cdc.applic.dictionaries.impl.bindings.PatternPatternBindingImpl;
import cdc.applic.dictionaries.impl.bindings.RealRealBindingImpl;
import cdc.applic.dictionaries.items.Alias;
import cdc.applic.dictionaries.items.Assertion;
import cdc.applic.dictionaries.items.AssertionKind;
import cdc.applic.dictionaries.items.ConstraintAssertion;
import cdc.applic.dictionaries.items.DItem;
import cdc.applic.dictionaries.items.DerivedStandardAssertion;
import cdc.applic.dictionaries.items.NamedDItem;
import cdc.applic.dictionaries.items.UserDefinedAssertion;
import cdc.applic.dictionaries.s1000d.S1000DProductIdentifier;
import cdc.applic.dictionaries.s1000d.S1000DPropertyType;
import cdc.applic.dictionaries.s1000d.S1000DType;
import cdc.applic.dictionaries.types.BooleanType;
import cdc.applic.dictionaries.types.EnumeratedType;
import cdc.applic.dictionaries.types.EnumeratedValue;
import cdc.applic.dictionaries.types.IntegerType;
import cdc.applic.dictionaries.types.ModifiableType;
import cdc.applic.dictionaries.types.PatternType;
import cdc.applic.dictionaries.types.RealType;
import cdc.applic.dictionaries.types.Type;
import cdc.applic.expressions.Expression;
import cdc.applic.expressions.content.BooleanValue;
import cdc.applic.expressions.content.IntegerValue;
import cdc.applic.expressions.content.RealValue;
import cdc.applic.expressions.content.SItemSet;
import cdc.applic.expressions.content.StringValue;
import cdc.applic.expressions.content.Value;
import cdc.applic.expressions.literals.Name;
import cdc.applic.expressions.literals.Named;
import cdc.applic.expressions.literals.SName;
import cdc.io.xml.AbstractStAXLoader;
import cdc.io.xml.AbstractStAXParser;
import cdc.io.xml.XmlWriter;
import cdc.util.function.IterableUtils;
import cdc.util.lang.Checks;
import cdc.util.lang.CollectionUtils;
import cdc.util.lang.FailureReaction;
import cdc.util.strings.StringUtils;
/**
* Utilities to save / load a repository to / from an XML stream.
*
* @author Damien Carbonne
*/
public final class RepositoryXml {
private static final String ALIAS = "alias";
private static final String ALIAS_ALIAS_BINDING = "alias-alias";
private static final String ALIASES = "aliases";
private static final String ASSERTION = "assertion";
private static final String ASSERTIONS = "assertions";
private static final String BOOLEAN_TYPE = "boolean-type";
private static final String BOOLEAN_BOOLEAN_BINDING = "boolean-boolean";
private static final String BOOLEAN_ENUMERATED_BINDING = "boolean-enumerated";
private static final String BOOLEAN_INTEGER_BINDING = "boolean-integer";
private static final String CONSTRAINT_ID = "constraint-id";
private static final String CONSTRAINT = "constraint";
private static final String CONSTRAINTS = "constraints";
private static final String CONTEXT = "context";
private static final String DEF = "def";
private static final String DESCRIPTION = "description";
private static final String DESCRIPTIONS = "descriptions";
private static final String DICTIONARIES_BINDING = "binding";
private static final String DICTIONARIES_BINDINGS = "bindings";
private static final String DOMAIN = "domain";
private static final String ENUMERATED_TYPE = "enumerated-type";
private static final String ENUMERATED_BOOLEAN_BINDING = "enumerated-boolean";
private static final String ENUMERATED_ENUMERATED_BINDING = "enumerated-enumerated";
private static final String ENUMERATED_INTEGER_BINDING = "enumerated-integer";
private static final String EXPRESSION = "expression";
private static final String FROZEN = "frozen";
private static final String ID = "id";
private static final String INTEGER_TYPE = "integer-type";
private static final String INTEGER_BOOLEAN_BINDING = "integer-boolean";
private static final String INTEGER_ENUMERATED_BINDING = "integer-enumerated";
private static final String INTEGER_INTEGER_BINDING = "integer-integer";
private static final String ITEMS_BINDINGS = "items-bindings";
private static final String ITEM_USAGE = "item-usage";
private static final String ITEM_USAGES = "item-usages";
private static final String KIND = "kind";
private static final String LANGUAGE = "lang";
private static final String LESS_THAN = "less-than";
private static final String LITERAL = "literal";
private static final String LITERAL1 = "literal1";
private static final String LITERAL2 = "literal2";
private static final String MAP = "map";
private static final String NAME = "name";
private static final String NAMING_CONVENTION = "naming-convention";
private static final String NAMING_CONVENTIONS = "naming-conventions";
private static final String ORDINAL = "ordinal";
private static final String PARAMS = "params";
private static final String PARENT = "parent";
private static final String PARENTS = "parents";
private static final String PATTERN = "pattern";
private static final String PATTERN_TYPE = "pattern-type";
private static final String PATTERN_PATTERN_BINDING = "pattern-pattern";
private static final String POLICIES = "policies";
private static final String POLICY = "policy";
private static final String PREFIX = "prefix";
private static final String PROPERTIES = "properties";
private static final String PROPERTY = "property";
private static final String PROPERTY_PROPERTY_BINDING = "property-property";
private static final String REAL_TYPE = "real-type";
private static final String REAL_REAL_BINDING = "real-real";
private static final String REGISTRIES = "registries";
private static final String REGISTRY = "registry";
private static final String REPOSITORY = "applic-repository";
private static final String REVERT = "revert";
private static final String SHORT_LITERAL = "short-literal";
private static final String SOURCE_DICTIONARY = "source-dictionary";
private static final String SOURCE_NAME = "source";
private static final String SOURCE_LITERAL = "source";
private static final String SYNONYM = "synonym";
private static final String SYNONYMS = "synonyms";
private static final String S1000D_ID = "s1000d-id";
private static final String S1000D_PROPERTY_TYPE = "s1000d-property-type";
private static final String S1000D_PRODUCT_IDENTIFIER = "s1000d-product-identifier";
private static final String TARGET_NAME = "target";
private static final String TARGET_LITERAL = "target";
private static final String TYPE = "type";
private static final String TYPES = "types";
private static final String TYPES_BINDINGS = "types-bindings";
private static final String TYPES_BINDING_ID = "types-binding-id";
private static final String TYPE_USAGE = "type-usage";
private static final String TYPE_USAGES = "type-usages";
private static final String USAGE = "usage";
private static final String VALUE = "value";
private static final String WRITING_RULE = "writing-rule";
private static final String WRITING_RULES = "writing-rules";
private RepositoryXml() {
}
/**
* Utility class used to write a Repository as an XML stream.
*
* @author Damien Carbonne
*/
public static final class Printer {
private final XmlWriter writer;
boolean debug = true;
private final Map typesBindingToId = new HashMap<>();
private final Map constraintToId = new HashMap<>();
private Printer(XmlWriter writer) {
this.writer = writer;
}
public static void write(XmlWriter writer,
RepositoryImpl repository,
boolean debug) throws IOException {
final Printer printer = new Printer(writer);
printer.debug = debug;
printer.write(repository);
}
public static void write(XmlWriter writer,
RepositoryImpl repository) throws IOException {
write(writer, repository, false);
}
private void write(RepositoryImpl repository) throws IOException {
final String namespace = "https://www.gitlab.com/cdc-java";
final String schema = "https://www.gitlab.com/cdc-java/applic-repository.xsd";
writer.beginDocument();
writer.beginElement(REPOSITORY);
writer.addDefaultNamespace(namespace);
writer.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
writer.addAttribute("xsi:schemaLocation", namespace + " " + schema);
writeDescription(repository.getDescription());
writeRegistries(repository);
writeDictionariesBindings(repository);
writer.endElement();
writer.endDocument();
}
private void writeDescription(Description description) throws IOException {
if (!description.getLocales().isEmpty()) {
writer.beginElement(DESCRIPTIONS);
for (final Locale locale : IterableUtils.toSortedList(description.getLocales(),
Description.LOCALE_LANGUAGE_COMPARATOR)) {
writer.beginElement(DESCRIPTION);
writer.addAttribute(LANGUAGE, locale.toLanguageTag());
if (description.getContent(locale) != null && !description.getContent(locale).isEmpty()) {
writer.addElementContent(description.getContent(locale));
}
writer.endElement();
}
writer.endElement();
}
}
private > void writeSynonyms(RefSyn rs) throws IOException {
if (rs.hasSynonyms()) {
writer.beginElement(SYNONYMS);
for (final NamingConvention convention : IterableUtils.toSortedList(rs.getNamingConventions(),
Named.NAME_COMPARATOR)) {
if (convention != NamingConvention.DEFAULT) {
final T synonym = rs.getValue(convention);
writer.beginElement(SYNONYM);
writer.addAttribute(NAMING_CONVENTION, convention.getName().getNonEscapedLiteral());
writer.addElementContent(synonym.toString());
writer.endElement();
}
}
writer.endElement();
}
}
private static String toString(SItemSet domain) {
return domain.getContent();
}
private void writeModifiableType(ModifiableType type) throws IOException {
if (type.isFrozen()) {
writer.addAttribute(FROZEN, true);
}
}
private void writeTypes(RegistryImpl registry) throws IOException {
if (!registry.getDeclaredTypes().isEmpty()) {
writer.beginElement(TYPES);
for (final S1000DType type : CollectionUtils.toSortedList(registry.getDeclaredTypes(), Type.NAME_COMPARATOR)) {
writeType(type);
}
writer.endElement();
}
}
private void writeType(S1000DType type) throws IOException {
if (type instanceof BooleanType) {
writer.beginElement(BOOLEAN_TYPE);
writer.addAttribute(NAME, type.getName().getLocal().getNonEscapedLiteral());
writeDefaultValue(type);
writeS1000DAttributes(type);
writeDescription(type.getDescription());
writeSynonyms(type.getNames());
writer.endElement();
} else if (type instanceof final IntegerType t) {
writer.beginElement(INTEGER_TYPE);
writer.addAttribute(NAME, type.getName().getLocal().getNonEscapedLiteral());
writer.addAttribute(DOMAIN, toString(t.getDomain()));
writeDefaultValue(type);
writeS1000DAttributes(type);
writeModifiableType((IntegerType) type);
writeDescription(type.getDescription());
writeSynonyms(type.getNames());
writer.endElement();
} else if (type instanceof final RealType t) {
writer.beginElement(REAL_TYPE);
writer.addAttribute(NAME, type.getName().getLocal().getNonEscapedLiteral());
writer.addAttribute(DOMAIN, toString(t.getDomain()));
writeDefaultValue(type);
writeS1000DAttributes(type);
writeModifiableType((RealType) type);
writeDescription(type.getDescription());
writeSynonyms(type.getNames());
writer.endElement();
} else if (type instanceof final EnumeratedType t) {
writer.beginElement(ENUMERATED_TYPE);
writer.addAttribute(NAME, type.getName().getLocal().getNonEscapedLiteral());
writeDefaultValue(type);
writeS1000DAttributes(type);
writeModifiableType((EnumeratedType) type);
writeDescription(type.getDescription());
writeSynonyms(type.getNames());
for (final EnumeratedValue value : t.getValues()) {
writer.beginElement(VALUE);
writer.addAttribute(LITERAL, value.getLiteral().getNonEscapedLiteral());
if (!value.getLiteral().equals(value.getShortLiteral())) {
writer.addAttribute(SHORT_LITERAL, value.getShortLiteral().getNonEscapedLiteral());
}
writer.addAttribute(ORDINAL, value.getOrdinal());
writeDescription(value.getDescription());
writeSynonyms(value.getLiterals());
writer.endElement();
}
for (final EnumeratedValue value : t.getValues()) {
final StringValue literal1 = value.getLiteral();
final List others = new ArrayList<>(((EnumeratedType) type).getDefinedLessThan(literal1));
Collections.sort(others);
for (final StringValue literal2 : others) {
writer.beginElement(LESS_THAN);
writer.addAttribute(LITERAL1, literal1.getNonEscapedLiteral());
writer.addAttribute(LITERAL2, literal2.getNonEscapedLiteral());
writer.endElement();
}
}
writer.endElement();
} else if (type instanceof final PatternType t) {
writer.beginElement(PATTERN_TYPE);
writer.addAttribute(NAME, type.getName().getLocal().getNonEscapedLiteral());
writer.addAttribute(PATTERN, t.getPattern());
writeDefaultValue(type);
writeS1000DAttributes(type);
writeModifiableType((PatternType) type);
writeDescription(type.getDescription());
writeSynonyms(type.getNames());
writer.endElement();
}
}
private void writeDefaultValue(S1000DType type) throws IOException {
final Value value = type.getDefaultValue().orElse(null);
if (value != null) {
writer.addAttribute(DEF, value);
}
}
private void writeS1000DAttributes(S1000DType type) throws IOException {
writer.addAttribute(S1000D_ID, type.getS1000DId());
if (type.getS1000DPropertyType() != S1000DPropertyType.UNDEFINED) {
writer.addAttribute(S1000D_PROPERTY_TYPE, type.getS1000DPropertyType());
}
if (type.getS1000DProductIdentifier() != S1000DProductIdentifier.NONE
&& type.getS1000DProductIdentifier() != S1000DProductIdentifier.NOT_APPLICABLE) {
writer.addAttribute(S1000D_PRODUCT_IDENTIFIER, type.getS1000DProductIdentifier());
}
}
private void writeExpression(Expression expression) throws IOException {
writer.beginElement(EXPRESSION);
writer.addElementContent(expression.getContent());
writer.endElement();
}
private void writeRegistries(RepositoryImpl repository) throws IOException {
writer.beginElement(REGISTRIES);
for (final RegistryImpl registry : repository.getRegistries()) {
writeRegistry(registry);
}
writer.endElement();
}
private void writeRegistry(RegistryImpl registry) throws IOException {
writer.beginElement(REGISTRY);
writer.addAttribute(NAME, registry.getName());
final Optional prefix = registry.getPrefix();
if (prefix.isPresent()) {
writer.addAttribute(PREFIX, prefix.get());
}
writeDescription(registry.getDescription());
writeParents(registry);
writeContext(registry);
writeNamingConventions(registry);
writeTypes(registry);
writeProperties(registry);
writeAliases(registry);
writeTypeUsages(registry);
writeItemUsages(registry);
writeConstraints(registry);
writeAssertions(registry);
writeWritingRuleNames(registry);
writePolicies(registry);
writer.endElement();
}
private void writeContext(AbstractDictionaryImpl dictionary) throws IOException {
// We can only define context on children dictionaries
if (dictionary.hasParents() && !dictionary.getContextExpression().isTrue()) {
writer.beginElement(CONTEXT);
writer.addElementContent(dictionary.getContextExpression().getContent());
writer.endElement();
}
}
private void writeNamingConventions(RegistryImpl registry) throws IOException {
if (!registry.getDeclaredNamingConventions().isEmpty()) {
writer.beginElement(NAMING_CONVENTIONS);
for (final NamingConvention convention : IterableUtils.toSortedList(registry.getDeclaredNamingConventions(),
Named.NAME_COMPARATOR)) {
writer.beginElement(NAMING_CONVENTION);
writer.addAttribute(NAME, convention.getName().getLocal().getNonEscapedLiteral());
writeDescription(convention.getDescription());
writer.endElement();
}
writer.endElement();
}
}
private void writeParents(AbstractDictionaryImpl dictionary) throws IOException {
if (!dictionary.getParents().isEmpty()) {
writer.beginElement(PARENTS);
for (final AbstractDictionaryImpl parent : dictionary.getParents()) {
writer.beginElement(PARENT);
writer.addElementContent(parent.getPath().toStringSlash());
writer.endElement();
}
writer.endElement();
}
}
private void writeProperties(RegistryImpl registry) throws IOException {
if (!IterableUtils.isEmpty(registry.getDeclaredProperties())) {
writer.beginElement(PROPERTIES);
for (final PropertyImpl property : IterableUtils.toSortedList(registry.getDeclaredProperties(),
Named.NAME_COMPARATOR)) {
writeProperty(property, registry.getPrefix());
}
writer.endElement();
}
}
private void writeProperty(PropertyImpl property,
Optional prefix) throws IOException {
writer.beginElement(PROPERTY);
writer.addAttribute(NAME, property.getName().getLocal().getNonEscapedLiteral());
writer.addAttribute(TYPE, property.getType().getName().removePrefix(prefix));
writer.addAttribute(ORDINAL, property.getOrdinal());
writer.addAttribute(S1000D_ID, property.getS1000DId());
writeDescription(property.getDescription());
writeSynonyms(property.getNames());
writer.endElement();
}
private void writeAliases(RegistryImpl registry) throws IOException {
if (!IterableUtils.isEmpty(registry.getDeclaredAliases())) {
writer.beginElement(ALIASES);
for (final Alias alias : IterableUtils.toSortedList(registry.getDeclaredAliases(), Named.NAME_COMPARATOR)) {
writeAlias(alias);
}
writer.endElement();
}
}
private void writeAlias(Alias alias) throws IOException {
writer.beginElement(ALIAS);
writer.addAttribute(NAME, alias.getName().getLocal().getNonEscapedLiteral());
writer.addAttribute(ORDINAL, alias.getOrdinal());
writeDescription(alias.getDescription());
writeSynonyms(alias.getNames());
writeExpression(alias.getExpression());
writer.endElement();
}
private void writeConstraints(AbstractDictionaryImpl dictionary) throws IOException {
if (!IterableUtils.isEmpty(dictionary.getConstraints())) {
writer.beginElement(CONSTRAINTS);
for (final Constraint constraint : IterableUtils.toSortedList(dictionary.getConstraints(),
Constraint.TYPE_PARAMS_COMPARATOR)) {
writeConstraint(constraint);
}
writer.endElement();
}
}
private void writeConstraint(Constraint constraint) throws IOException {
Checks.assertTrue(!constraintToId.containsKey(constraint), "Duplicate constraint");
final int id = constraintToId.size() + 1;
constraintToId.put(constraint, id);
writer.beginElement(CONSTRAINT);
writer.addAttribute(ID, id);
writer.addAttribute(TYPE, constraint.getTypeName());
writeDescription(constraint.getDescription());
writer.addElementIfNonEmpty(PARAMS, constraint.getParams());
writer.endElement();
}
private void writeAssertions(AbstractDictionaryImpl dictionary) throws IOException {
if (!dictionary.getAllAssertions().isEmpty()) {
writer.beginElement(ASSERTIONS);
for (final Assertion assertion : CollectionUtils.toSortedList(dictionary.getAllAssertions(),
DItem.COMPARATOR)) {
if (debug || assertion instanceof UserDefinedAssertion) {
writeAssertion(assertion);
}
}
writer.endElement();
}
}
private void writeAssertion(Assertion assertion) throws IOException {
writer.beginElement(ASSERTION);
writer.addAttribute(KIND, assertion.getKind());
if (assertion instanceof final ConstraintAssertion a) {
writer.addAttribute(CONSTRAINT_ID, constraintToId.get(a.getConstraint()));
} else if (assertion instanceof final DerivedStandardAssertion a) {
writer.addAttribute(SOURCE_DICTIONARY, a.getSourceDictionary().getName());
}
writeDescription(assertion.getDescription());
writeExpression(assertion.getExpression());
if (assertion instanceof final ConstraintAssertion a) {
final String params = a.getParams();
if (!StringUtils.isNullOrEmpty(params)) {
writer.addElement(PARAMS, params);
}
}
writer.endElement();
}
private void writePolicies(AbstractDictionaryImpl dictionary) throws IOException {
if (!IterableUtils.isEmpty(dictionary.getChildren())) {
writer.beginElement(POLICIES);
for (final PolicyImpl policy : IterableUtils.toSortedList(dictionary.getChildren(PolicyImpl.class),
Dictionary.NAME_COMPARATOR)) {
writePolicy(policy);
}
writer.endElement();
}
}
private void writePolicy(PolicyImpl policy) throws IOException {
writer.beginElement(POLICY);
writer.addAttribute(NAME, policy.getName());
writeDescription(policy.getDescription());
writeContext(policy);
writeTypeUsages(policy);
writeItemUsages(policy);
writeConstraints(policy);
writeAssertions(policy);
writeWritingRuleNames(policy);
writePolicies(policy);
writer.endElement();
}
private void writeTypeUsages(AbstractDictionaryImpl dictionary) throws IOException {
if (dictionary.hasTypeUsages()) {
writer.beginElement(TYPE_USAGES);
for (final Type type : IterableUtils.toSortedList(dictionary.getRegistry().getAllTypes(),
Named.NAME_COMPARATOR)) {
final DItemUsage usage = dictionary.getTypeUsage(type);
if (usage != null) {
writeTypeUsage(dictionary, type);
}
}
writer.endElement();
}
}
private void writeTypeUsage(Dictionary dictionary,
Type type) throws IOException {
writer.beginElement(TYPE_USAGE);
writer.addAttribute(NAME, type.getName().getNonEscapedLiteral());
writer.addAttribute(USAGE, dictionary.getTypeUsage(type));
writer.endElement();
}
private void writeItemUsages(AbstractDictionaryImpl dictionary) throws IOException {
if (dictionary.hasItemUsages()) {
writer.beginElement(ITEM_USAGES);
for (final NamedDItem item : IterableUtils.toSortedList(dictionary.getAllItems(),
Named.NAME_COMPARATOR)) {
if (dictionary.getItemUsage(item) != null) {
writeItemUsage(dictionary, item);
}
}
writer.endElement();
}
}
private void writeItemUsage(Dictionary dictionary,
NamedDItem item) throws IOException {
writer.beginElement(ITEM_USAGE);
writer.addAttribute(NAME, item.getName().getNonEscapedLiteral());
writer.addAttribute(USAGE, dictionary.getEffectiveItemUsage(item));
writer.endElement();
}
private void writeWritingRuleNames(AbstractDictionaryImpl dictionary) throws IOException {
if (!IterableUtils.isEmpty(dictionary.getWritingRuleNames())) {
writer.beginElement(WRITING_RULES);
for (final String name : IterableUtils.toSortedList(dictionary.getWritingRuleNames())) {
writer.beginElement(WRITING_RULE);
writer.addAttribute(NAME, name);
writer.endElement();
}
writer.endElement();
}
}
private void writeDictionariesBindings(RepositoryImpl repository) throws IOException {
if (!repository.getBindings().isEmpty()) {
writer.beginElement(DICTIONARIES_BINDINGS);
for (final DictionariesBindingImpl binding : CollectionUtils.toSortedList(repository.getBindings(),
DictionariesBinding.TARGET_SOURCE_COMPARATOR)) {
writeDictionariesBinding(binding);
}
writer.endElement();
}
}
private void writeDictionariesBinding(DictionariesBindingImpl binding) throws IOException {
writer.beginElement(DICTIONARIES_BINDING);
writer.addAttribute(SOURCE_NAME, binding.getDictionary(BindingRole.SOURCE).getPath());
writer.addAttribute(TARGET_NAME, binding.getDictionary(BindingRole.TARGET).getPath());
writeTypesBindings(binding);
writeItemsBindings(binding);
writer.endElement();
}
private void writeTypesBindings(DictionariesBindingImpl binding) throws IOException {
writer.beginElement(TYPES_BINDINGS);
// FIXME this may not be sufficient to produce a stable sort
for (final TypesBinding typeBinding : CollectionUtils.toSortedList(binding.getTypesBindings(),
TypesBinding.TARGET_SOURCE_COMPARATOR)) {
writeTypeBinding(typeBinding);
}
writer.endElement();
}
private void writeTypeBindingAttributes(TypesBinding binding,
int id) throws IOException {
writer.addAttribute(ID, id);
writer.addAttribute(SOURCE_NAME, binding.getType(BindingRole.SOURCE).getName());
writer.addAttribute(TARGET_NAME, binding.getType(BindingRole.TARGET).getName());
}
private void writeTypeBinding(TypesBinding binding) throws IOException {
Checks.assertTrue(!typesBindingToId.containsKey(binding), "Duplicate type binding");
final int id = typesBindingToId.size() + 1;
typesBindingToId.put(binding, id);
if (binding instanceof final BooleanBooleanBinding b) {
writer.beginElement(BOOLEAN_BOOLEAN_BINDING);
writeTypeBindingAttributes(binding, id);
if (b.revert()) {
writer.addAttribute(REVERT, true);
}
writer.endElement();
} else if (binding instanceof IntegerIntegerBindingImpl) {
writer.beginElement(INTEGER_INTEGER_BINDING);
writeTypeBindingAttributes(binding, id);
writer.endElement();
} else if (binding instanceof RealRealBindingImpl) {
writer.beginElement(REAL_REAL_BINDING);
writeTypeBindingAttributes(binding, id);
writer.endElement();
} else if (binding instanceof PatternPatternBindingImpl) {
writer.beginElement(PATTERN_PATTERN_BINDING);
writeTypeBindingAttributes(binding, id);
writer.endElement();
} else if (binding instanceof AbstractExtensionTypesBinding) {
final AbstractExtensionTypesBinding, ?, ?, ?, ?, ?> b = (AbstractExtensionTypesBinding, ?, ?, ?, ?, ?>) binding;
if (binding instanceof BooleanEnumeratedBindingImpl) {
writer.beginElement(BOOLEAN_ENUMERATED_BINDING);
} else if (binding instanceof BooleanIntegerBindingImpl) {
writer.beginElement(BOOLEAN_INTEGER_BINDING);
} else if (binding instanceof EnumeratedBooleanBindingImpl) {
writer.beginElement(ENUMERATED_BOOLEAN_BINDING);
} else if (binding instanceof EnumeratedEnumeratedBindingImpl) {
writer.beginElement(ENUMERATED_ENUMERATED_BINDING);
} else if (binding instanceof EnumeratedIntegerBindingImpl) {
writer.beginElement(ENUMERATED_INTEGER_BINDING);
} else if (binding instanceof IntegerBooleanBindingImpl) {
writer.beginElement(INTEGER_BOOLEAN_BINDING);
} else if (binding instanceof IntegerEnumeratedBindingImpl) {
writer.beginElement(INTEGER_ENUMERATED_BINDING);
}
writeTypeBindingAttributes(binding, id);
for (final Value source : CollectionUtils.toSortedList(b.getSourceValues(), Value.COMPARATOR)) {
writer.beginElement(MAP);
writer.addAttribute(SOURCE_LITERAL, source);
writer.addAttribute(TARGET_LITERAL, b.forward(source));
writer.endElement();
}
writer.endElement();
}
}
private void writeItemsBindings(DictionariesBindingImpl binding) throws IOException {
writer.beginElement(ITEMS_BINDINGS);
for (final DItemsBinding itemBinding : CollectionUtils.toSortedList(binding.getDItemBindings(),
DItemsBinding.TARGET_SOURCE_COMPARATOR)) {
writeItemBinding(itemBinding);
}
writer.endElement();
}
private void writeItemBinding(DItemsBinding binding) throws IOException {
if (binding instanceof final AliasAliasBinding b) {
writer.beginElement(ALIAS_ALIAS_BINDING);
writer.addAttribute(SOURCE_NAME, b.getAlias(BindingRole.SOURCE).getName());
writer.addAttribute(TARGET_NAME, b.getAlias(BindingRole.TARGET).getName());
} else {
final PropertyPropertyBinding b = (PropertyPropertyBinding) binding;
writer.beginElement(PROPERTY_PROPERTY_BINDING);
writer.addAttribute(SOURCE_NAME, b.getProperty(BindingRole.SOURCE).getName());
writer.addAttribute(TARGET_NAME, b.getProperty(BindingRole.TARGET).getName());
writer.addAttribute(TYPES_BINDING_ID, typesBindingToId.get(b.getTypesBinding()));
}
writer.endElement();
}
}
public static class StAXLoader extends AbstractStAXLoader {
public StAXLoader(FailureReaction reaction) {
super((reader,
systemId) -> new Parser(reader, systemId, reaction));
}
private static class Parser extends AbstractStAXParser {
private final Map idToTypesBinding = new HashMap<>();
private final Map idToConstraint = new HashMap<>();
protected Parser(XMLStreamReader reader,
String systemId,
FailureReaction reaction) {
super(reader, systemId, reaction);
}
private static class SynonymContext {
/** The associated dictionary. */
private final SynonymSetter ss;
SynonymContext(SynonymSetter ss) {
this.ss = ss;
}
}
@Override
protected RepositoryImpl parse() throws XMLStreamException {
trace("parse()");
// Move to root start tag
nextTag();
if (isStartElement(REPOSITORY)) {
final RepositoryImpl result = parseRepository();
next();
return result;
} else {
throw unexpectedEvent();
}
}
/**
* Must be called cursor is on {@link #REPOSITORY} start tag.
*
* @return The parsed repository.
* @throws XMLStreamException When an exception occurs.
*/
private RepositoryImpl parseRepository() throws XMLStreamException {
final String ctx = "parseRepository()";
trace(ctx);
expectStartElement(ctx, REPOSITORY);
final RepositoryImpl repository = new RepositoryImpl();
// Move to next start tag or to end tag of repository
nextTag();
parseOptionalDescriptions(repository.getDescription());
if (isStartElement(REGISTRIES)) {
parseChildren(repository, REGISTRIES, this::parseRegistry);
nextTag();
}
if (isStartElement(DICTIONARIES_BINDINGS)) {
parseChildren(repository, DICTIONARIES_BINDINGS, this::parseDictionariesBinding);
nextTag();
}
expectEndElement(ctx, REPOSITORY);
return repository;
}
/**
* Must be called when cursor is on {@link #DESCRIPTIONS} start tag.
* In the end, cursor is on {@link #DESCRIPTIONS} end tag.
*
* @param descriptions The description.
* @throws XMLStreamException When an exception occurs.
*/
private void parseDescriptions(DescriptionSetter> descriptions) throws XMLStreamException {
final String ctx = "parseDescriptions()";
trace(ctx);
expectStartElement(ctx, DESCRIPTIONS);
// Cursor is supposed to be on start tag of descriptions
nextTag();
// Now cursor is either on the first description start tag or on the closing tag of descriptions
while (isStartElement(DESCRIPTION)) {
final String lang = getAttributeValue(LANGUAGE, "en");
final Locale locale = Locale.forLanguageTag(lang);
next();
if (reader.isCharacters()) {
final String content = reader.getText();
descriptions.description(locale, content);
// Move to closing tag
nextTag();
} else {
descriptions.description(locale, "");
// Already on closing tag
}
// Either move to next description start tag or on end tag of descriptions
nextTag();
}
// Must be on end tag of descriptions
expectEndElement(ctx, DESCRIPTIONS);
}
private void parseOptionalDescriptions(DescriptionSetter> descriptions) throws XMLStreamException {
trace("parseOptionalDescriptions()");
if (isStartElement(DESCRIPTIONS)) {
parseDescriptions(descriptions);
nextTag();
}
}
private DescriptionImpl parseOptionalDescriptions() throws XMLStreamException {
trace("parseOptionalDescriptions()");
final DescriptionImpl.Builder description = DescriptionImpl.builder();
if (isStartElement(DESCRIPTIONS)) {
parseDescriptions(description);
nextTag();
}
return description.build();
}
private > void parseSynonym(SynonymContext context) throws XMLStreamException {
final String ctx = "parseSynonym()";
trace(ctx);
expectStartElement(ctx, SYNONYM);
final String convention = getAttributeValue(NAMING_CONVENTION);
next();
final String synonym = getReader().getText();
context.ss.synonym(convention, synonym);
nextTag();
expectEndElement(ctx, SYNONYM);
}
private > void
parseOptionalSynonyms(SynonymContext context) throws XMLStreamException {
final String ctx = "parseOptionalSynonyms()";
trace(ctx);
if (isStartElement(SYNONYMS)) {
parseChildren(context, SYNONYMS, this::parseSynonym);
expectEndElement(ctx, SYNONYMS);
nextTag();
}
}
private void parseParent(List parentsPath) throws XMLStreamException {
final String ctx = "parseParent()";
trace(ctx);
expectStartElement(ctx, PARENT);
next();
parentsPath.add(reader.getText());
nextTag();
}
private void parseNamingConvention(RegistryImpl registry) throws XMLStreamException {
final String ctx = "parseNamingConvention()";
trace(ctx);
expectStartElement(ctx, NAMING_CONVENTION);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final NamingConventionImpl.Builder convention = registry.namingConvention()
.name(name);
nextTag();
parseOptionalDescriptions(convention);
convention.build();
expectEndElement(ctx, NAMING_CONVENTION);
}
private void parseType(RegistryImpl registry) throws XMLStreamException {
final String ctx = "parseType()";
trace(ctx);
expectStartElement(ctx,
BOOLEAN_TYPE,
INTEGER_TYPE,
REAL_TYPE,
ENUMERATED_TYPE,
PATTERN_TYPE);
final String s1000DId = getAttributeValue(S1000D_ID, null);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final boolean frozen = getAttributeAsBoolean(FROZEN, false);
final String def = getAttributeValue(DEF, null);
final S1000DPropertyType propertyType =
getAttributeAsEnum(S1000D_PROPERTY_TYPE, S1000DPropertyType.class, S1000DPropertyType.UNDEFINED);
final S1000DProductIdentifier keyKind = getAttributeAsEnum(S1000D_PRODUCT_IDENTIFIER,
S1000DProductIdentifier.class,
propertyType.getDefaultIdentifier());
if (isStartElement(BOOLEAN_TYPE)) {
final BooleanValue defaultValue = def == null ? null : BooleanValue.of(def);
final BooleanTypeImpl.Builder type = registry.booleanType()
.s1000DId(s1000DId)
.name(name)
.defaultValue(defaultValue)
.s1000DPropertyType(propertyType)
.s1000DProductIdentifier(keyKind);
nextTag();
parseOptionalDescriptions(type);
parseOptionalSynonyms(new SynonymContext<>(type));
type.build();
expectEndElement(ctx, BOOLEAN_TYPE);
} else if (isStartElement(INTEGER_TYPE)) {
final String domain = getAttributeValue(DOMAIN, null, FailureReaction.FAIL);
final IntegerValue defaultValue = def == null ? null : IntegerValue.of(def);
final IntegerTypeImpl.Builder type = registry.integerType()
.s1000DId(s1000DId)
.name(name)
.defaultValue(defaultValue)
.frozen(frozen)
.domain(domain)
.s1000DPropertyType(propertyType)
.s1000DProductIdentifier(keyKind);
nextTag();
parseOptionalDescriptions(type);
parseOptionalSynonyms(new SynonymContext<>(type));
type.build();
} else if (isStartElement(REAL_TYPE)) {
final String domain = getAttributeValue(DOMAIN, null, FailureReaction.FAIL);
final RealValue defaultValue = def == null ? null : RealValue.of(def);
final RealTypeImpl.Builder type = registry.realType()
.s1000DId(s1000DId)
.name(name)
.defaultValue(defaultValue)
.frozen(frozen)
.domain(domain)
.s1000DPropertyType(propertyType)
.s1000DProductIdentifier(keyKind);
nextTag();
parseOptionalDescriptions(type);
parseOptionalSynonyms(new SynonymContext<>(type));
type.build();
} else if (isStartElement(ENUMERATED_TYPE)) {
final StringValue defaultValue = def == null ? null : StringValue.of(def);
final EnumeratedTypeImpl.Builder type = registry.enumeratedType()
.s1000DId(s1000DId)
.name(name)
.defaultValue(defaultValue)
.frozen(frozen)
.s1000DPropertyType(propertyType)
.s1000DProductIdentifier(keyKind);
nextTag();
parseOptionalDescriptions(type);
parseOptionalSynonyms(new SynonymContext<>(type));
while (isStartElement(VALUE)) {
parseEnumeratedValue(type);
nextTag();
}
while (isStartElement(LESS_THAN)) {
parseLessThan(type);
nextTag();
}
type.build();
} else if (isStartElement(PATTERN_TYPE)) {
final String pattern = getAttributeValue(PATTERN, null, FailureReaction.FAIL);
final StringValue defaultValue = def == null ? null : StringValue.of(def);
final PatternTypeImpl.Builder type = registry.patternType()
.s1000DId(s1000DId)
.name(name)
.defaultValue(defaultValue)
.frozen(frozen)
.pattern(pattern)
.s1000DPropertyType(propertyType)
.s1000DProductIdentifier(keyKind);
nextTag();
parseOptionalDescriptions(type);
parseOptionalSynonyms(new SynonymContext<>(type));
type.build();
} else {
throw unexpectedEvent();
}
}
private void parseEnumeratedValue(EnumeratedTypeImpl.Builder type) throws XMLStreamException {
final String ctx = "parseEnumeratedValue()";
trace(ctx);
expectStartElement(ctx, VALUE);
final String literal = getAttributeValue(LITERAL, null, FailureReaction.FAIL);
final String shortLiteral = getAttributeValue(SHORT_LITERAL, literal);
final int ordinal = getAttributeAsInt(ORDINAL, 0);
final EnumeratedValueImpl.Builder value =
type.value()
.literal(literal)
.shortLiteral(shortLiteral)
.ordinal(ordinal);
nextTag();
parseOptionalDescriptions(value);
parseOptionalSynonyms(new SynonymContext<>(value));
value.back();
expectEndElement(ctx, VALUE);
}
private void parseLessThan(EnumeratedTypeImpl.Builder type) throws XMLStreamException {
final String ctx = "parseLessThan()";
trace(ctx);
expectStartElement(ctx, LESS_THAN);
final String literal1 = getAttributeValue(LITERAL1);
final String literal2 = getAttributeValue(LITERAL2);
nextTag();
type.lessThan(literal1, literal2);
expectEndElement(ctx, LESS_THAN);
}
private void parseRegistry(RepositoryImpl repository) throws XMLStreamException {
final String ctx = "parseRegistry()";
trace(ctx);
expectStartElement(ctx, REGISTRY);
final String name = getAttributeValue(NAME, null);
final String prefix = getAttributeValue(PREFIX, null);
final RegistryImpl registry = repository.registry().name(name).prefix(prefix).build();
nextTag();
parseOptionalDescriptions(registry.getDescription());
final List parentsPaths = new ArrayList<>();
if (isStartElement(PARENTS)) {
parseChildren(parentsPaths, PARENTS, this::parseParent);
nextTag();
final List parents = new ArrayList<>();
for (final String parentPath : parentsPaths) {
final AbstractDictionaryImpl parent = repository.getDictionary(parentPath);
parents.add(parent);
}
registry.setParents(parents);
}
if (isStartElement(CONTEXT)) {
next();
final String context = reader.getText();
registry.setContextExpression(new Expression(context));
nextTag();
nextTag();
}
if (isStartElement(NAMING_CONVENTIONS)) {
parseChildren(registry, NAMING_CONVENTIONS, this::parseNamingConvention);
nextTag();
}
if (isStartElement(TYPES)) {
parseChildren(registry, TYPES, this::parseType);
nextTag();
}
if (isStartElement(PROPERTIES)) {
parseChildren(registry, PROPERTIES, this::parseProperty);
nextTag();
}
if (isStartElement(ALIASES)) {
parseChildren(registry, ALIASES, this::parseAlias);
nextTag();
}
if (isStartElement(TYPE_USAGES)) {
parseChildren(registry, TYPE_USAGES, this::parseTypeUsage);
nextTag();
}
if (isStartElement(ITEM_USAGES)) {
parseChildren(registry, ITEM_USAGES, this::parseItemUsage);
nextTag();
}
if (isStartElement(CONSTRAINTS)) {
parseChildren(registry, CONSTRAINTS, this::parseConstraint);
nextTag();
}
if (isStartElement(ASSERTIONS)) {
parseChildren(registry, ASSERTIONS, this::parseAssertion);
nextTag();
}
if (isStartElement(WRITING_RULES)) {
parseChildren(registry, WRITING_RULES, this::parseWritingRule);
nextTag();
}
if (isStartElement(POLICIES)) {
parseChildren(registry, POLICIES, this::parsePolicy);
nextTag();
}
expectEndElement(ctx, REGISTRY);
}
private void parseDictionariesBinding(RepositoryImpl repository) throws XMLStreamException {
final String ctx = "parseRegistriesBinding()";
trace(ctx);
expectStartElement(ctx, DICTIONARIES_BINDING);
final String targetPath = getAttributeValue(TARGET_NAME, null, FailureReaction.FAIL);
final String sourcePath = getAttributeValue(SOURCE_NAME, null, FailureReaction.FAIL);
final DictionariesBindingImpl binding = repository.binding().source(sourcePath).target(targetPath).build();
nextTag();
if (isStartElement(TYPES_BINDINGS)) {
parseChildren(binding, TYPES_BINDINGS, this::parseTypesBinding);
nextTag();
}
if (isStartElement(ITEMS_BINDINGS)) {
parseChildren(binding, ITEMS_BINDINGS, this::parseItemsBinding);
nextTag();
}
expectEndElement(ctx, DICTIONARIES_BINDING);
}
private void parseTypesBinding(DictionariesBindingImpl binding) throws XMLStreamException {
final String ctx = "parseTypesBinding()";
trace(ctx);
expectStartElement(ctx,
BOOLEAN_BOOLEAN_BINDING,
INTEGER_INTEGER_BINDING,
REAL_REAL_BINDING,
ENUMERATED_ENUMERATED_BINDING,
PATTERN_PATTERN_BINDING);
final String id = getAttributeValue(ID, null, FailureReaction.FAIL);
final String targetName = getAttributeValue(TARGET_NAME, null, FailureReaction.FAIL);
final String sourceName = getAttributeValue(SOURCE_NAME, null, FailureReaction.FAIL);
final TypesBinding typesBinding;
if (isStartElement(BOOLEAN_BOOLEAN_BINDING)) {
final boolean revert = getAttributeAsBoolean(REVERT, false);
typesBinding = binding.booleanBooleanBinding()
.source(sourceName)
.target(targetName)
.revert(revert)
.build();
nextTag();
expectEndElement(ctx, BOOLEAN_BOOLEAN_BINDING);
} else if (isStartElement(BOOLEAN_ENUMERATED_BINDING)) {
typesBinding = parseExtension(BOOLEAN_ENUMERATED_BINDING,
binding.booleanEnumeratedBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(BOOLEAN_INTEGER_BINDING)) {
typesBinding = parseExtension(BOOLEAN_INTEGER_BINDING,
binding.booleanIntegerBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(INTEGER_INTEGER_BINDING)) {
typesBinding = binding.integerIntegerBinding()
.source(sourceName)
.target(targetName)
.build();
nextTag();
expectEndElement(ctx, INTEGER_INTEGER_BINDING);
} else if (isStartElement(REAL_REAL_BINDING)) {
typesBinding = binding.realRealBinding()
.source(sourceName)
.target(targetName)
.build();
nextTag();
expectEndElement(ctx, REAL_REAL_BINDING);
} else if (isStartElement(ENUMERATED_BOOLEAN_BINDING)) {
typesBinding = parseExtension(ENUMERATED_BOOLEAN_BINDING,
binding.enumeratedBooleanBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(ENUMERATED_ENUMERATED_BINDING)) {
typesBinding = parseExtension(ENUMERATED_ENUMERATED_BINDING,
binding.enumeratedEnumeratedBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(ENUMERATED_INTEGER_BINDING)) {
typesBinding = parseExtension(ENUMERATED_INTEGER_BINDING,
binding.enumeratedIntegerBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(INTEGER_BOOLEAN_BINDING)) {
typesBinding = parseExtension(INTEGER_BOOLEAN_BINDING,
binding.integerBooleanBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(INTEGER_ENUMERATED_BINDING)) {
typesBinding = parseExtension(INTEGER_ENUMERATED_BINDING,
binding.integerEnumeratedBinding()
.source(sourceName)
.target(targetName));
} else if (isStartElement(PATTERN_PATTERN_BINDING)) {
typesBinding = binding.patternPatternBinding()
.source(sourceName)
.target(targetName)
.build();
nextTag();
expectEndElement(ctx, PATTERN_PATTERN_BINDING);
} else {
throw unexpectedEvent();
}
idToTypesBinding.put(id, typesBinding);
}
private TypesBinding parseExtension(String name,
AbstractExtensionTypesBinding.Builder, ?, ?, ?, ?> builder) throws XMLStreamException {
nextTag();
while (isStartElement(MAP)) {
parseValueValueMap(builder);
nextTag();
}
final TypesBinding typeBinding = builder.build();
expectEndElement("parseExtension()", name);
return typeBinding;
}
private void
parseValueValueMap(AbstractExtensionTypesBinding.Builder, ?, ?, ?, ?> builder) throws XMLStreamException {
final String ctx = "parseValueValueMap()";
trace(ctx);
expectStartElement(ctx, MAP);
final String sourceLiteral = getAttributeValue(SOURCE_LITERAL, null, FailureReaction.FAIL);
final String targetLiteral = getAttributeValue(TARGET_LITERAL, null, FailureReaction.FAIL);
nextTag();
builder.map(sourceLiteral, targetLiteral);
expectEndElement(ctx, MAP);
}
private void parseItemsBinding(DictionariesBindingImpl binding) throws XMLStreamException {
final String ctx = "parseItemsBinding()";
trace(ctx);
expectStartElement(ctx, ALIAS_ALIAS_BINDING, PROPERTY_PROPERTY_BINDING);
final String targetName = getAttributeValue(TARGET_NAME, null, FailureReaction.FAIL);
final String sourceName = getAttributeValue(SOURCE_NAME, null, FailureReaction.FAIL);
if (isStartElement(ALIAS_ALIAS_BINDING)) {
binding.aliasAliasBinding()
.source(sourceName)
.target(targetName)
.build();
} else {
final String id = getAttributeValue(TYPES_BINDING_ID, null, FailureReaction.DEFAULT);
final TypesBinding typeBinding = idToTypesBinding.get(id);
if (typeBinding == null) {
binding.propertyPropertyBinding()
.source(sourceName)
.target(targetName)
.build();
} else {
binding.propertyPropertyBinding()
.source(sourceName)
.target(targetName)
.typeBinding(typeBinding)
.build();
}
}
nextTag();
expectEndElement(ctx, ALIAS_ALIAS_BINDING, PROPERTY_PROPERTY_BINDING);
}
private void parseProperty(RegistryImpl registry) throws XMLStreamException {
final String ctx = "parseProperty()";
trace(ctx);
expectStartElement(ctx, PROPERTY);
final String s1000DId = getAttributeValue(S1000D_ID, null);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final String typeName = getAttributeValue(TYPE, null, FailureReaction.FAIL);
final int ordinal = getAttributeAsInt(ORDINAL, 0);
final PropertyImpl.Builder property =
registry.property()
.s1000DId(s1000DId)
.name(name)
.type(typeName)
.ordinal(ordinal);
nextTag();
parseOptionalDescriptions(property);
parseOptionalSynonyms(new SynonymContext<>(property));
expectEndElement(ctx, PROPERTY);
property.build();
}
private void parseAlias(RegistryImpl registry) throws XMLStreamException {
final String ctx = "parseAlias()";
trace(ctx);
expectStartElement(ctx, ALIAS);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final int ordinal = getAttributeAsInt(ORDINAL, 0);
nextTag();
final AliasImpl.Builder alias = registry.alias().name(name).ordinal(ordinal);
expectStartElement(ctx, DESCRIPTIONS, EXPRESSION);
parseOptionalDescriptions(alias);
parseOptionalSynonyms(new SynonymContext<>(alias));
expectStartElement(ctx, EXPRESSION);
final Expression expression = parseExpression();
alias.expression(expression);
nextTag();
expectEndElement(ctx, ALIAS);
alias.build();
}
private void parseConstraint(AbstractDictionaryImpl dictionary) throws XMLStreamException {
final String ctx = "parseConstraint()";
trace(ctx);
expectStartElement(ctx, CONSTRAINT);
final String id = getAttributeValue(ID, null, FailureReaction.FAIL);
final String typeName = getAttributeValue(TYPE, null, FailureReaction.FAIL);
nextTag();
final DescriptionImpl description = parseOptionalDescriptions();
// Now located on or
final String params;
if (isStartElement(PARAMS)) {
next();
params = reader.getText();
nextTag();
expectEndElement(ctx, PARAMS);
nextTag();
} else {
params = null;
}
trace();
expectEndElement(ctx, CONSTRAINT);
final Constraint constraint = Constraints.create(typeName, dictionary, params);
((DescriptionImpl) constraint.getDescription()).set(description);
idToConstraint.put(id, constraint);
dictionary.addConstraint(constraint);
}
private void parseAssertion(AbstractDictionaryImpl dictionary) throws XMLStreamException {
final String ctx = "parseAssertion()";
trace(ctx);
expectStartElement(ctx, ASSERTION);
final String constraintId = getAttributeValue(CONSTRAINT_ID, null);
final AssertionKind kind = getAttributeAsEnum(KIND, AssertionKind.class, AssertionKind.USER_DEFINED);
nextTag();
expectStartElement(ctx, DESCRIPTIONS, EXPRESSION);
final DescriptionImpl description = parseOptionalDescriptions();
expectStartElement(ctx, EXPRESSION);
final Expression expression = parseExpression();
nextTag();
if ((kind == null || kind == AssertionKind.USER_DEFINED) && constraintId == null) {
final UserDefinedAssertionImpl assertion = dictionary.createAssertion(expression);
assertion.getDescription().set(description);
} else {
// Skip non user-defined assertions
if (isStartElement(PARAMS)) {
next();
reader.getText();
nextTag();
nextTag();
}
}
expectEndElement(ctx, ASSERTION);
}
private Expression parseExpression() throws XMLStreamException {
final String ctx = "parseExpression()";
trace(ctx);
expectStartElement(ctx, EXPRESSION);
next();
final String expression = reader.getText();
nextTag();
expectEndElement(ctx, EXPRESSION);
return new Expression(expression);
}
private void parsePolicy(AbstractDictionaryImpl dictionary) throws XMLStreamException {
final String ctx = "parsePolicy()";
trace(ctx);
expectStartElement(ctx, POLICY);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final PolicyImpl policy = dictionary.policy().name(name).build();
nextTag();
parseOptionalDescriptions(policy.getDescription());
if (isStartElement(CONTEXT)) {
next();
final String context = reader.getText();
policy.setContextExpression(new Expression(context));
nextTag();
nextTag();
}
if (isStartElement(TYPE_USAGES)) {
parseChildren(policy, TYPE_USAGES, this::parseTypeUsage);
nextTag();
}
if (isStartElement(ITEM_USAGES)) {
parseChildren(policy, ITEM_USAGES, this::parseItemUsage);
nextTag();
}
if (isStartElement(CONSTRAINTS)) {
parseChildren(policy, CONSTRAINTS, this::parseConstraint);
nextTag();
}
if (isStartElement(ASSERTIONS)) {
parseChildren(policy, ASSERTIONS, this::parseAssertion);
nextTag();
}
if (isStartElement(WRITING_RULES)) {
parseChildren(policy, WRITING_RULES, this::parseWritingRule);
nextTag();
}
if (isStartElement(POLICIES)) {
parseChildren(policy, POLICIES, this::parsePolicy);
nextTag();
}
expectEndElement(ctx, POLICY);
}
private void parseTypeUsage(AbstractDictionaryImpl dictionary) throws XMLStreamException {
final String ctx = "parseTypeUsage()";
trace(ctx);
expectStartElement(ctx, TYPE_USAGE);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final DItemUsage usage = getAttributeAsEnum(USAGE, DItemUsage.class, DItemUsage.OPTIONAL);
dictionary.setTypeUsage(Name.of(name), usage);
nextTag();
expectEndElement(ctx, TYPE_USAGE);
}
private void parseItemUsage(AbstractDictionaryImpl dictionary) throws XMLStreamException {
final String ctx = "parseItemUsage()";
trace(ctx);
expectStartElement(ctx, ITEM_USAGE);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
final DItemUsage usage = getAttributeAsEnum(USAGE, DItemUsage.class, DItemUsage.OPTIONAL);
dictionary.setItemUsage(Name.of(name), usage);
nextTag();
expectEndElement(ctx, ITEM_USAGE);
}
private void parseWritingRule(AbstractDictionaryImpl dictionary) throws XMLStreamException {
final String ctx = "parseWritingRule()";
trace(ctx);
expectStartElement(ctx, WRITING_RULE);
final String name = getAttributeValue(NAME, null, FailureReaction.FAIL);
dictionary.setWritingRuleEnabled(name, true);
nextTag();
expectEndElement(ctx, WRITING_RULE);
}
}
}
}