Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update DSL version to 9.22.0 #438

Merged
merged 4 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.enforced.version>[17,18)</java.enforced.version>
<maven.compiler.release>8</maven.compiler.release>
<rosetta.dsl.version>9.20.0</rosetta.dsl.version>
<rosetta.dsl.version>9.22.0</rosetta.dsl.version>

<!-- Release -->
<gpg.keyname>configured-by-release-profile</gpg.keyname>
Expand Down Expand Up @@ -507,10 +507,8 @@
<mainClass>com.regnosys.rosetta.tools.modelimport.XsdImportMain</mainClass>
<cleanupDaemonThreads>false</cleanupDaemonThreads>
<arguments>
<argument>-xsd-path</argument>
<argument>${project.basedir}/src/test/resources/xml-serialisation/schema/schema.xsd</argument>
<argument>-properties-path</argument>
<argument>${project.basedir}/src/test/resources/xml-serialisation/schema/import-schema.properties</argument>
<argument>-config-path</argument>
<argument>${project.basedir}/src/test/resources/xml-serialisation/schema/import-config.yml</argument>
<argument>-rosetta-output-path</argument>
<argument>${project.build.testOutputDirectory}/xml-serialisation/rosetta</argument>
<argument>-xml-config-output-path</argument>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public <T extends RosettaModelObject> KeyPostProcessReport runProcessStep(Class<
RosettaModelObjectBuilder builder = instance.toBuilder();
KeyPostProcessReport thisReport = new KeyPostProcessReport(builder, new HashMap<>());
ReKeyProcessor reKeyProcessor = new ReKeyProcessor(thisReport);
RosettaPath path = RosettaPath.valueOf(topClass.getSimpleName());
RosettaPath path = RosettaPath.valueOf(instance.getType().getSimpleName());
reKeyProcessor.processRosetta(path, topClass, builder, null);
builder.process(path, reKeyProcessor);
return thisReport;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public ReKeyProcessStep(GlobalKeyProcessStep keyProcessor) {

@Override
public <T extends RosettaModelObject> PostProcessorReport runProcessStep(Class<? extends T> topClass, T instance) {
RosettaPath path = RosettaPath.valueOf(topClass.getSimpleName());
RosettaPath path = RosettaPath.valueOf(instance.getType().getSimpleName());
RosettaModelObjectBuilder builder = instance.toBuilder();
ReKeyPostProcessReport report = new ReKeyPostProcessReport(builder);
ReKeyProcessor processor = new ReKeyProcessor(report, keyProcessor.runProcessStep(topClass, instance));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public String getName() {
public <T extends RosettaModelObject> ReferenceResolverPostProcessorReport runProcessStep(
Class<? extends T> topClass,
T instance) {
RosettaPath path = RosettaPath.valueOf(topClass.getSimpleName());
RosettaPath path = RosettaPath.valueOf(instance.getType().getSimpleName());
ReferenceCollector collector = new ReferenceCollector(referenceConfig);
instance.process(path, collector);
ReferenceResolver resolver =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public String getName() {
@Override
public <T extends RosettaModelObject> PostProcessorReport runProcessStep(Class<? extends T> topClass, T instance) {
MergeTemplateBuilderProcessor process = new MergeTemplateBuilderProcessor();
RosettaPath path = RosettaPath.valueOf(topClass.getSimpleName());
RosettaPath path = RosettaPath.valueOf(instance.getType().getSimpleName());
RosettaModelObjectBuilder builder= instance.toBuilder();
process.processRosetta(path, topClass, builder, null);
builder.process(path, process);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public String getName() {

@Override
public <T extends RosettaModelObject> QualificationReport runProcessStep(Class<? extends T> topClass, T instance) {
RosettaPath path = RosettaPath.valueOf(topClass.getSimpleName());
RosettaPath path = RosettaPath.valueOf(instance.getType().getSimpleName());
RosettaModelObjectBuilder builder = (RosettaModelObjectBuilder) instance;

List<QualificationResult> collectedResults = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
Expand All @@ -37,6 +38,7 @@
import com.regnosys.rosetta.common.serialisation.mixin.legacy.LegacyGlobalKeyFieldsMixIn;
import com.regnosys.rosetta.common.serialisation.mixin.legacy.LegacyKeyMixIn;
import com.regnosys.rosetta.common.serialisation.mixin.legacy.LegacyReferenceMixIn;
import com.regnosys.rosetta.common.serialisation.xml.RosettaSerialiserFactory;
import com.regnosys.rosetta.common.serialisation.xml.RosettaXMLModule;
import com.rosetta.model.lib.meta.GlobalKeyFields;
import com.rosetta.model.lib.meta.Key;
Expand Down Expand Up @@ -73,8 +75,15 @@ public static RosettaObjectMapperCreator forJSON() {
}
public static RosettaObjectMapperCreator forXML(RosettaXMLConfiguration config) {
boolean supportRosettaEnumValue = true;
ObjectMapper base = XmlMapper.xmlBuilder().defaultUseWrapper(false).build(); // TODO: enable default wrapping after this issue is resolved: https://github.com/FasterXML/jackson-databind/issues/4595
return new RosettaObjectMapperCreator(new RosettaXMLModule(config, supportRosettaEnumValue), base);

// See issue https://github.com/FasterXML/jackson-dataformat-xml/issues/678
XmlMapper baseXML = new XmlMapper((JacksonXmlModule) null);
baseXML.setSerializerFactory(RosettaSerialiserFactory.INSTANCE);

ObjectMapper base = new XmlMapper.Builder(baseXML)
.defaultUseWrapper(false) // TODO: enable default wrapping after this issue is resolved: https://github.com/FasterXML/jackson-databind/issues/4595
.build();
return new RosettaObjectMapperCreator(new RosettaXMLModule(base, config, supportRosettaEnumValue), base);
}
public static RosettaObjectMapperCreator forXML(InputStream configInputStream) throws IOException {
ObjectMapper xmlConfigurationMapper = new ObjectMapper()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.regnosys.rosetta.common.serialisation.xml;

/*-
* ==============
* Rune Common
* ==============
* Copyright (C) 2018 - 2024 REGnosys
* ==============
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ==============
*/

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.deser.impl.MethodProperty;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;

import java.util.ArrayList;
import java.util.List;

import static com.regnosys.rosetta.common.serialisation.xml.RosettaBeanSerializerModifier.findSubstitutionMap;

/**
* Support for deserialising substitution groups by adding additional properties
* to the `BeanDeserializerBuilder` for each additional name of a substitution.
*/
public class RosettaBeanDeserializerModifier extends BeanDeserializerModifier {
@Override
public BeanDeserializerBuilder updateBuilder(DeserializationConfig config,
BeanDescription beanDesc, BeanDeserializerBuilder builder) {
final AnnotationIntrospector intr = config.getAnnotationIntrospector();
List<PropertyName> propNames = new ArrayList<>();
builder.getProperties().forEachRemaining(p -> propNames.add(p.getFullName()));
for (PropertyName propName : propNames) {
SettableBeanProperty prop = builder.findProperty(propName);

AnnotatedMember acc = prop.getMember();
SubstitutionMap substitutionMap = findSubstitutionMap(config, intr, acc);
if (substitutionMap != null) {
for (JavaType substitutedType : substitutionMap.getTypes()) {
String substitutedName = substitutionMap.getName(substitutedType);
SettableBeanProperty substitutedProperty = new SubstitutedMethodProperty((MethodProperty)prop, substitutedType, (AnnotatedMethod) acc).withSimpleName(substitutedName);
// TODO: only replace the original property - make sure we are not accidentally replacing random other properties
builder.addOrReplaceProperty(substitutedProperty, true);
}
}
}
return builder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package com.regnosys.rosetta.common.serialisation.xml;

/*-
* ==============
* Rune Common
* ==============
* Copyright (C) 2018 - 2024 REGnosys
* ==============
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ==============
*/

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.io.SerializedString;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter;
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.BitSet;
import java.util.Set;

/**
* Add a `schemaLocation` to the root XML element, if configured.
* It can be configured through an object writer by using
* {@code withAttribute}. Example:
*
* <pre>
* xmlMapper
* .writerWithDefaultPrettyPrinter()
* .withAttribute("schemaLocation", "urn:my.schema ../schema/schema.xsd")
* </pre>
*/
public class RosettaBeanSerializer extends XmlBeanSerializer {
public static final String SCHEMA_LOCATION_ATTRIBUTE_NAME = "schemaLocation";
private static final String SCHEMA_LOCATION_ATTRIBUTE_PREFIXED_NAME = "xsi:" + SCHEMA_LOCATION_ATTRIBUTE_NAME;

private final SubstitutionMap _substitutionMap;

public RosettaBeanSerializer(XmlBeanSerializer src, SubstitutionMap substitutionMap) {
super(src);
this._substitutionMap = substitutionMap;
}

public RosettaBeanSerializer(RosettaBeanSerializer src, ObjectIdWriter objectIdWriter, Object filterId) {
super(src, objectIdWriter, filterId);
this._substitutionMap = src._substitutionMap;
}

public RosettaBeanSerializer(RosettaBeanSerializer src, Set<String> toIgnore, Set<String> toInclude) {
super(src, toIgnore, toInclude);
this._substitutionMap = src._substitutionMap;
}

protected RosettaBeanSerializer(RosettaBeanSerializer src, BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) {
super(src, properties, filteredProperties);
this._substitutionMap = src._substitutionMap;
}

@Override
public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) {
return new RosettaBeanSerializer(this, objectIdWriter, _propertyFilterId);
}

@Override
public BeanSerializerBase withFilterId(Object filterId) {
return new RosettaBeanSerializer(this, _objectIdWriter, filterId);
}

@Override // since 2.12
protected BeanSerializerBase withByNameInclusion(Set<String> toIgnore, Set<String> toInclude) {
return new RosettaBeanSerializer(this, toIgnore, toInclude);
}

@Override // since 2.11.1
protected BeanSerializerBase withProperties(BeanPropertyWriter[] properties,
BeanPropertyWriter[] filteredProperties) {
return new RosettaBeanSerializer(this, properties, filteredProperties);
}

@Override
public void serialize(Object bean, JsonGenerator g, SerializerProvider provider) throws IOException {
if (_substitutionMap != null && g instanceof ToXmlGenerator) {
String substitutedName = _substitutionMap.getSubstitutedName(bean);
if (substitutedName != null) {
((ToXmlGenerator) g).setNextName(new QName(substitutedName));
}
}
if (g instanceof ToXmlGenerator && ((ToXmlGenerator) g).inRoot()) {
serializeRootElement(bean, (ToXmlGenerator) g, provider);
} else {
super.serialize(bean, g, provider);
}
}

public void serializeRootElement(Object bean, ToXmlGenerator g, SerializerProvider provider) throws IOException {
if (_objectIdWriter != null) {
// TODO: also include schemaLocation
_serializeWithObjectId(bean, g, provider, true);
return;
}
g.writeStartObject();
if (_propertyFilterId != null) {
// TODO: also include schemaLocation
serializeFieldsFiltered(bean, g, provider);
} else {
serializeFieldsAndAddSchemaLocation(bean, g, provider);
}
g.writeEndObject();
}

// Serialize fields as usual, but add the `schemaLocation` attribute at the end of all XML attributes.
protected void serializeFieldsAndAddSchemaLocation(Object bean, ToXmlGenerator xgen, SerializerProvider provider)
throws IOException {
final BeanPropertyWriter[] props;
if (_filteredProps != null && provider.getActiveView() != null) {
props = _filteredProps;
} else {
props = _props;
}

final int attrCount = _attributeCount;
xgen.setNextIsAttribute(true);
final int textIndex = _textPropertyIndex;
final QName[] xmlNames = _xmlNames;
int i = 0;
final BitSet cdata = _cdata;

try {
if (props.length == 0) {
writeSchemaLocation(xgen, provider);
}
for (final int len = props.length; i < len; ++i) {
// 28-jan-2014, pascal: we don't want to reset the attribute flag if we are an unwrapping serializer
// that started with nextIsAttribute to true because all properties should be unwrapped as attributes too.
if (i == attrCount && !isUnwrappingSerializer()) {
writeSchemaLocation(xgen, provider);
xgen.setNextIsAttribute(false);
}
// also: if this is property to write as text ("unwrap"), need to:
if (i == textIndex) {
xgen.setNextIsUnwrapped(true);
}
xgen.setNextName(xmlNames[i]);
BeanPropertyWriter prop = props[i];
if (prop != null) { // can have nulls in filtered list
if ((cdata != null) && cdata.get(i)) {
xgen.setNextIsCData(true);
prop.serializeAsField(bean, xgen, provider);
xgen.setNextIsCData(false);
} else {
prop.serializeAsField(bean, xgen, provider);
}
}
// Reset to avoid next value being written as unwrapped,
// for example when property is suppressed
if (i == textIndex) {
xgen.setNextIsUnwrapped(false);
}
}
if (_anyGetterWriter != null) {
// For [#117]: not a clean fix, but with @JsonTypeInfo, we'll end up
// with accidental attributes otherwise
xgen.setNextIsAttribute(false);
_anyGetterWriter.getAndSerialize(bean, xgen, provider);
}
} catch (Exception e) {
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
wrapAndThrow(provider, e, bean, name);
} catch (StackOverflowError e) { // Bit tricky, can't do more calls as stack is full; so:
JsonMappingException mapE = JsonMappingException.from(xgen,
"Infinite recursion (StackOverflowError)");
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
mapE.prependPath(new JsonMappingException.Reference(bean, name));
throw mapE;
}
}

private void writeSchemaLocation(ToXmlGenerator xgen, SerializerProvider provider) throws IOException {
JavaType propType = provider.constructType(String.class);
PropertyName propertyName = PropertyName.construct(SCHEMA_LOCATION_ATTRIBUTE_PREFIXED_NAME);
AnnotatedMember member = new VirtualXMLAttribute(_beanType.getRawClass(), SCHEMA_LOCATION_ATTRIBUTE_NAME, propType);
SimpleBeanPropertyDefinition xmlPropertyDefinition = SimpleBeanPropertyDefinition.construct(provider.getConfig(), member, propertyName, PropertyMetadata.STD_OPTIONAL, JsonInclude.Include.NON_NULL);
AttributePropertyWriter attrWriter = AttributePropertyWriter.construct(SCHEMA_LOCATION_ATTRIBUTE_NAME, xmlPropertyDefinition, null, _beanType);

xgen.setNextName(new QName("", attrWriter.getName()));
try {
attrWriter.serializeAsField(null, xgen, provider);
} catch (Exception e) {
wrapAndThrow(provider, e, null, SCHEMA_LOCATION_ATTRIBUTE_PREFIXED_NAME);
}
}

/*
/**********************************************************
/* Standard methods
/**********************************************************
*/

@Override
public String toString() {
return "RosettaBeanSerializer for " + handledType().getName();
}
}
Loading
Loading