Is it possible to convert a List to a Map using Orika? - orika

I am looking convert a List of custom objects to a Map of custom objects. I have a mapping defined with a custom method, but I keep getting a "cannot be cast to ma.glasnost.orika.MapEntry" exception. What is the proper way to go about converting a List to a Map in Orika?
mapperFactory.classMap(new TypeBuilder<List<com.printable.pti.NameValuePairType>>(){}.build(), new TypeBuilder<Map<String, com.kinetic.entity.TemplateField>>() {}.build())
.customize(new CustomMapper<List<com.printable.pti.NameValuePairType>,Map<String, com.kinetic.entity.TemplateField>>() {
#Override
public void mapAtoB(List<com.printable.pti.NameValuePairType> nameValuePairTypes,
Map<String, com.kinetic.entity.TemplateField> stringTemplateFieldMap, MappingContext context) {
Map<String, com.kinetic.entity.TemplateField> toObject = new HashMap<String, com.kinetic.entity.TemplateField>();
for(com.printable.pti.NameValuePairType nameValuePairType : nameValuePairTypes) {
toObject.put(nameValuePairType.getName(),(com.kinetic.entity.TemplateField)map(nameValuePairType,com.kinetic.entity.TemplateField.class));
}
}
}
)
.register();

Here is a good example of how to map a list of elements to Map using Orika

Related

Is there a complete JUnit 5 extension example that demonstrates the proper way to maintain state (e.g. WebServerExtension.java from guide)

The main WebServerExtension example from the JUnit5 manual is incomplete and it doesn't fully show how to properly store the configuration (e.g. enableSecurity, server url).
https://github.com/junit-team/junit5/blob/master/documentation/src/main/java/example/registration/WebServerExtension.java
The example ignores or hard codes the values. The manual (section 5.11. Keeping State in Extensions) implies that the "Store" should be used but the ExtensionContext is not yet available yet when the object is constructed -- its not clear how to handle migrating this data to the Store as the ExtensionContext is not yet available in the constructor.
Also its not clear to me that using the Store API for the WebServerExtension programmatic example is even desirable and perhaps it could work just using the internal state (e.g. this.serverUrl, this.enableSecurity, etc.).
Maybe the Store is more applicable to Extensions which don't use this "programmatic" style where multiple instances of the custom extension may exist (appropriately)? In other words its not clear to me from the guide if this a supported paradigm or not?
Other JUnit 5 extension examples online (e.g. org.junit.jupiter.engine.extension.TempDirectory) show how to leverage annotations to handle passing configuration info to the Store but it would be nice if there were a complete programmatic builder type example like WebServerExtension too.
Examples like TempDirectory clearly have access to the ExtensionContext from the beforeXXX() methods whereas the WebServerExtension example does not.
Using the following approach below seems to work fine but I wanted confirmation that this is a supported paradigm (i.e. using fields instead of Stores when using this programmatic approach).
public class WebServerExtension implements BeforeAllCallback {
private final boolean securityEnabled;
private final String serverUrl;
public WebServerExtension(Builder builder) {
this.securityEnabled = builder.enableSecurity;
this.serverUrl = build.serverUrl;
}
#Override
public void beforeAll(ExtensionContext context) {
// is it ok to use this.securityEnabled, this.serverUrl instead of Store API???
}
public String getServerUrl() {
return this.serverUrl;
}
public boolean isSecurityEnabled() {
return this.securityEnabled;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private boolean enableSecurity;
private String serverUrl;
public Builder enableSecurity(boolean b) {
this.enableSecurity = b;
return this;
}
public Builder serverUrl(String url) {
this.serverUrl = url;
return this;
}
public WebServerExtension build() {
return new WebServerExtension(this);
}
}
}
Thanks!

Orika - how to map inheritance and flattening?

I have been struggling with a task how to tell Orika to map an inherited structure that is flattened to DTO so that it may correctly resolve the implementation on reconstruction of an object. Here is an example of a simple structure with many nested objects:
abstract class Document {
// common values
}
class LegalDocument extends Document {
// complex object with many nested objects
}
class PersonalDocument extends Document {
// complex object with many nested objects
}
And let's say I have a reason to have an object flattened of the structure above:
class FlattenedDocument {
private String documentType = "LEGAL"; // "LEGAL" or "PERSONAL"
// flattened properties of Document and both its subclasses
}
I am able to tell Orika via CustomMapper<Document, FlattenedDocument> to map correctly the property documentType with a correct value based on an actual type (class) of the input document, but what I don't know how to do is the reverse situation. I need to tell Orika that when it converts from FlattenedDocument to one of the implementations of abstract Document, whether it should create the former or the latter by the value of documentType property. I can do that via CustomConverter or ObjectFactory but in both cases I am losing the benefit of byDefault().
Is there any way how to use the standard ClassMap with byDefault() option
factory.classMap(Document.class, FlattenedDocument.class).byDefault().register();
but with the possibility to tell Orika that it should re-instantiate the object based on the value of documentType field?
Thanks.
You can create a CustomConverter, that decides the type based on your field:
public class ShapeReverseConverter extends CustomConverter<ShapeDTO, Shape> {
#Override
public Shape convert(ShapeDTO source, Type<? extends Shape> destinationType, MappingContext mappingContext) {
if (Circle.class.getSimpleName().equals(source.type)) {
return mapperFacade.map(source, Circle.class);
} else {
return mapperFacade.map(source, Rectangle.class);
}
}
}
In Config you can map setting the type:
DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Shape.class, ShapeDTO.class).byDefault()
.field("class.simpleName", "type")
.register();
mapperFactory.getConverterFactory().registerConverter(new ShapeReverseConverter());

How to write a List of a specific type using kryo serializer

I am trying to write a List of a specific type using Kryo serializer but I am getting errors when I try to read/write it. I am using source provided by apache spark for KryoRegistrator
List I am trying to write is of type List<A> which could be an ArrayList or any other type of list
Code
Class FakeRegsitrator implements KryoRegistrator{
#Override
public void registerClasses(Kryo kryo) {
CollectionSerializer listSerializer = new CollectionSerializer();
listSerializer.setElementClass(A.class, kryo.getSerializer(A.class));
listSerializer.setElementsCanBeNull(false);
kryo.register(A.class, new Serializer<A>(true, true) {
public void write(Kryo kryo, Output output, A a) {
output.writeLong(a.getFieldA)
output.WriteString(a.getFieldB)
}
public A read(Kryo kryo, Input input, Class type) {
return new A(input.readLong(), input.readString())
}
}
}
What am I missing here?
I was able to get it working by registering Arraylist.class
code :
kryo.register(ArrayList.class);
in read method use
kryo.readObject(input, ArrayList.class);
in write method use
kryo.writeObject(output, entry.getArchivePortions());

Serialize class based on one interface it implements with Jackson or Gson

I have the following:
An interface I1 extends Ia, Ib, Ic
An interface I2.
A class C implements I1, I2. And this class has its own setters and getters as well.
C cInstance = new C():
//Jackson
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(new File("somefile.json"), cInstance);
//Gson
Gson gson = new Gson();
String json = gson.toJson(cInstance);
The output will be cInstance serialized according to the properties of C and what it inherited.
However, I like the properties are being serialized to be according to the setters/getters in I1 (only the cInstance properties represented in the I1 interface).
How can I do this with Jackson knowing that I have too many classes with the same problem and I can't modify the class definition or add annotations.
And the same issue applies to Deserialization (Deserializing according to an interface)
Thanks
First of all, you can always attach "mix-in annotations" even without adding annotations directly (see wiki page). With this, annotation to use would be:
#JsonSerialize(as=MyInterface.class)
but if you do not want to use mix-ins, you can force specific type to use with
objectMapper.typedWriter(MyInterface.class).writeValue(....)
Jackson's VisibilityChecker provides an easy way for filtering certain properties, especially because it allows you to test for visibility (equals "will be serialized or not") for each method/field individually.
At least this helps for the serialization phase.
Here is what I did (using Jackson version 1.9.11):
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;
import org.codehaus.jackson.map.introspect.VisibilityChecker;
public static class InterfaceVisibilityChecker extends VisibilityChecker.Std {
private final Set<Method> visibleMethods;
public InterfaceVisibilityChecker(Class<?>... clazzes) {
super(JsonAutoDetect.Visibility.PUBLIC_ONLY);
this.visibleMethods = new HashSet<>();
for (Class<?> clz : clazzes) {
this.visibleMethods.addAll(Arrays.asList(clz.getMethods()));
}
}
#Override
public boolean isGetterVisible(Method m) {
return super.isGetterVisible(m) && isVisible(m);
}
#Override
public boolean isGetterVisible(AnnotatedMethod m) {
return isGetterVisible(m.getAnnotated());
}
private boolean isVisible(Method m) {
for (Method visiMthd : visibleMethods) {
if (isOverwriteMethod(m, visiMthd)) return true;
}
return false;
}
private boolean isOverwriteMethod(Method subMethod, Method superMethod) {
// names must be equal
if (! subMethod.getName().equals(superMethod.getName())) return false;
// return types must be assignable
if (! superMethod.getReturnType().isAssignableFrom(subMethod.getReturnType())) return false;
// parameters must be equal
if (! Arrays.equals(subMethod.getParameterTypes(), superMethod.getGenericParameterTypes())) return false;
// classes must be assignable
return superMethod.getDeclaringClass().isAssignableFrom(subMethod.getDeclaringClass());
}
}
The main idea is to use the standard VisibilityChecker and extend it by a check whether the method is declared in one of the given interfaces.
The checker is applied to an ObjectMapper instance using the following snippet:
ObjectMapper om = new ObjectMapper();
om.setVisibilityChecker(new InterfaceVisibilityChecker(
I1.class,
I2.class,
Ia.class,
Ib.class,
Ic.class
));
Some comments on the solution above:
The checker is not complete, methods like isIsGetterVisible or isFieldVisible can be handled in a similar manner if needed.
isOverwriteMethod is not optimized at all, it's checks could be cached.

Converting javafx.util.Properties to a HashMap

I was wondering if there is an easy way to convert the javafx.util.Properties object to a java.util.HashMap.
There is the obvious way of getting each value from the Properties object and putting it in a Map. But with a large number of properties it seems like there should be a way of just getting the Map that backs javafx.util.Properties (if it is a Map).
Thanks in advance for any suggestions.
I don't really know if javafx.util.Properties are backed by Java Map, but since public API does not mention any way to get this map you probably shouldn't try to do it - even if it was possible (e.g. by extending Properties class) it might change in future versions.
I would stay with copying every element.
+1 for pazabos answer. But I would go the other way around: extend HashMap or java.util.Properties which then could export javafx.util.Properties (or hold an instance) sth. like:
class MyProperties extends HashMap {
HashSet<String> keys = new HashSet<String>();
javafx.util.Properties p = new Properties();
public String get(String str) {
return p.get(str);
}
public Map creatHashMap() {
Map map = new HashMap();
for (String k : keys) {
map.put(k, p.get(k));
}
return map;
}
public void put() {
//...
}