Data Weave Pojo to Pojo Mappings - mule

I am trying to do a Pojo to Pojo transformation as below( each Pojo has a List of objects) - the output is transformed but is skipping an object - sample code below.
public class Pojo1 implements Serializable {
private List<Foo> fooList =new ArrayList<Foo>(1);
public Pojo1() {
}
public List<Foo> getFooList() {
return fooList ;
}
public void setFooList(List<Foo> fooList) {
this.fooList= fooList;
}
}
public class Pojo2 implements Serializable {
private List<Bar> barList =new ArrayList<Bar>(1);
public Pojo2() {
}
public List<Bar> getBarList() {
return barList ;
}
public void setBarList(List<Bar> barList) {
this.barList= barList;
}
}
DataWeave transformation as follows - this works fine but only one object in the List gets transformed and I'm missing the second one.
barList: [{
(
payload.fooList map {
item1:$.item1
}
)
} as :object {
class :"com.fooClass"
}]
} as :object {
class : "com.barClass"
}
Thanks in advance !

Try with
{
barList: in1.fooList map {
item1: $.item1
} as :object {class : "com.fooClass"}
} as :object {class : "com.barClass"}
Note: as :object {class : "com.fooClass"} should be optional, as it can be inferred
The problem seems to be that you defined an array with only one object and filled that object with the result of:
payload.fooList map {
item1:$.item1
}
Which is an array of objects:
[
{
item1: "value1"
},
{
item1: "value2"
}
]
After filling the object with that, it ends up like:
{
item1: "value1",
item1: "value2",
item1: ...
}
So, you are filling the array with an object with a lot of duplicated fields (with different values) and when that output is written (since it's java) each one of those fields only get one value.

Related

How to get a message sent from View Model using a sealed class?

I have an app that uses Kotlin with an MVVM approach. My goal here is to send the state (SUCCESS, FAIL, ERROR, EXCEPTION.VM_INSERT...) from View Model to activity. In my activity, I observe the state and based on that I will inform the user about the state. The SUCCESS, FAIL, ERROR state works as expected, unfortunately, I struggle to find out how show in Activity the exception message send by EXCEPTION.VM_INSERT.
ViewModel State:
sealed class ViewModelState {
sealed class EXCEPTION : ViewModelState() {
class VM_INSERT(val exception: String) : ViewModelState()
class VM_UPDATE(val exception: String) : ViewModelState()
class VM_DELETE(val exception: String) : ViewModelState()
class VM_QUERY(val exception: String) : ViewModelState()
}
object SUCCESS : ViewModelState()
object FAIL : ViewModelState()
object ERROR : ViewModelState()
}
ViewModel:
...
private val _insertWordStatus = MutableLiveData<ViewModelState>()
val insertWordStatus: LiveData<ViewModelState> = _insertWordStatus
fun insertWord(word: Word) = viewModelScope.launch {
try {
val insertedRowId = repository.insertWord(word)
if (insertedRowId > -1) {
_insertWordStatus.value = ViewModelState.SUCCESS
} else {
_insertWordStatus.value = ViewModelState.FAIL
}
} catch (ex: Exception) {
_insertWordStatus.value = ViewModelState.ERROR
_insertWordStatus.value =
ex.localizedMessage.toString()?.let { ViewModelState.EXCEPTION.VM_INSERT(it) }
}
...
Activity:
...
wordViewModel.insertWordStatus.observe(this, Observer { viewModelState ->
if (viewModelState == ViewModelState.SUCCESS ) {
} else if (viewModelState == ViewModelState.FAIL) {
} else if (viewModelState == ViewModelState.ERROR) {
} else {
}
})
...
You forgot to make all the intended children of EXCEPTION subclasses of EXCEPTION. Also, you should move their shared property into the superclass so you take advantage of inheritance to, for example, log the error without having to check the specific type of EXCEPTION.
sealed class EXCEPTION(val exception: String) : ViewModelState() {
class VM_INSERT(exception: String) : EXCEPTION(exception)
class VM_UPDATE(exception: String) : EXCEPTION(exception)
class VM_DELETE(exception: String) : EXCEPTION(exception)
class VM_QUERY(exception: String) : EXCEPTION(exception)
}
In my opinion, you should refactor it as follows. I don't think the complexity of a sealed class is justified if every one of its children has identical class structure. That's really fighting against the basic principles of object oriented programming. Example:
class EXCEPTION(val exception: String, val type: EXCEPTION.Type) : ViewModelState() {
enum class Type { VM_INSERT, VM_UPDATE, VM_DELETE, VM_QUERY }
}
By the way, you should look up how to use when statements in Kotlin. It is much cleaner than a chain of else ifs when they're all checking against the same argument. Example:
wordViewModel.insertWordStatus.observe(this) { viewModelState ->
when(viewModelState) {
ViewModelState.SUCCESS - > {
}
ViewModelState.FAIL -> {
}
ViewModelState.ERROR -> {
}
ViewModelState.EXCEPTION -> {
}
}
}

tinder state machine - working with lists

Im trying to implement state machine with some complicated business logic
I'm holding a list of objects that I need to iterate and send each object to the state machine
sealed class State {
object PendingForAction: State()
object ActionFailed : State()
object ActionCompleted : State()
object PendingNextAction : State()
}
sealed class Event() {
object OnPendingForAction : Event()
object OnActionFailed : Event()
object OnActionCompleted : Event()
}
sealed class SideEffect() {
object UpdateStatusPendingForAction : SideEffect()
object UpdateStatusActionFailed : SideEffect()
object UpdateStatusCompleted : SideEffect()
}
#Component
class StateMachine #Autowired constructor(
) {
#Autowired
lateinit var repository: SomeRepository
val stateMachine = StateMachine.create<State, Event, SideEffect> {
initialState(State.PendingForAction)
state<State.PendingForAction> {
on<Event.OnActionFailed> {
transitionTo(State.ActionFailed, SideEffect.UpdateStatusActionFailed)
}
on<Event.ActionCompleted> {
transitionTo(State.PendingNextAction, SideEffect.UpdateStatusCompleted)
}
// so on with next actions
}
onTransition() {
val validTransition = it as? StateMachine.Transition.Valid ?: return#onTransition
when (validTransition.sideEffect) {
SideEffect.UpdateStatusPendingForAction -> {
//here i want to do complicated code that use the data object from the list
//but i can't access it
}
// and so on ...
}
}
}
}
now trigger somehow the state machine with my data:
val data = listOf(obj,obj,obj...)
// each object is in a different state and I want it to be generic enough to know the
state and perform the transition automatically
data.forEach{
stateMachine.transition(it)
}
please note that transition function only accept sideEffect but i want it to accept the object and it's state

Kotlin parse 2 type of field(string, object) like on Swift

on IOS i have a code for parsing nested json. This json can contains string and object. It looks like this(Swift):
struct Place: Codable {
let value: [Dependent]?
}
enum Dependent: Codable {
case object(Place)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
let objectVal = try container.decode(Place.self)
self = .object(objectVal)
} catch DecodingError.typeMismatch {
let stringVal = try container.decode(String.self)
self = .string(stringVal)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .object(let value):
try container.encode(value)
case .string(let value):
try container.encode(value)
}
}
}
But its to hard understand how i can create the same parser for Kotlin, i did code like this:
data class Place(
val value: List<Dependent>
)
sealed class Dependent {
data class OBJECT(val value: Place): Dependent()
data class STRING(val value: String): Dependent()
}
It doesnt work, i feel i missed something
UPD:
The josn looks like this:
{
"value": [
"123123123",
{"value": ["123123", "123123", {"value":["123"]}, "123"]}
]
}

Kotlin Enum with String Room TypeConverter

I'm fetching json that has a 'type' field that contains a string, and I want to store this in my model object as an Enum with a string value.
The API I'm working with doesn't return all the information in one fetch, so once I have all the data I call my setProperties method.
All of my primitives are stored correctly in memory & my room db, but my Type class isn't converted. Any idea whats wrong with my type converter?
// Enum
enum class Type(var value: String) {
ARTICLE("article"),
COMMENT("comment"),
UNKNOWN("unknown")
}
// data class
data class FeedItem(#PrimaryKey override var id: Int) : Item(id) {
#TypeConverters(TypeConverter::class)
var type: Type? = Type.UNKNOWN
// other props...
fun setProperties(itemToCopy: FeedItem) {
this.type = itemToCopy.type
// set other props
}
}
// TypeConverter
class TypeConverter {
#TypeConverter
fun toString(type: Type?): String? {
return type?.value
}
#TypeConverter
fun toType(value: String?): Type? {
return when(value) {
Type.ARTICLE.value ->Type.ARTICLE
Type.COMMENT.value -> Type.COMMENT
else -> Type.UNKNOWN
}
}
}

How to unwrap single item array and extract value field into one simple field?

I have a JSON document similar to the following:
{
"aaa": [
{
"value": "wewfewfew"
}
],
"bbb": [
{
"value": "wefwefw"
}
]
}
I need to deserialize this into something more clean such as:
public class MyEntity{
private String aaa;
private String bbb;
}
What's the best way to unwrap each array and extract the "value" field on deserialization? Just custom setters? Or is there a nicer way?
For completeness, if you use jackson, you can enable the deserialization feature UNWRAP_SINGLE_VALUE_ARRAYS.
To do that, you have to enable it for the ObjectMapper like so:
ObjectMapper objMapper = new ObjectMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
With that, you can just read the class as you are being used to in Jackson.
For example, assuming the class Person:
public class Person {
private String name;
// assume getter, setter et al.
}
and a json personJson:
{
"name" : [
"John Doe"
]
}
We can deserialize it via:
ObjectMapper objMapper = new ObjectMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
Person p = objMapper.readValue(personJson, Person.class);
Quick solution with Gson is to use a JsonDeserializer like this:
package stackoverflow.questions.q17853533;
import java.lang.reflect.Type;
import com.google.gson.*;
public class MyEntityDeserializer implements JsonDeserializer<MyEntity> {
public MyEntity deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
String aaa = json.getAsJsonObject().getAsJsonArray("aaa").get(0)
.getAsJsonObject().get("value").getAsString();
String bbb = json.getAsJsonObject().getAsJsonArray("bbb").get(0)
.getAsJsonObject().get("value").getAsString();
return new MyEntity(aaa, bbb);
}
}
and then use it when parsing:
package stackoverflow.questions.q17853533;
import com.google.gson.*;
public class Q17853533 {
public static void main(String[] arg) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(MyEntity.class, new MyEntityDeserializer());
String testString = "{ \"aaa\": [{\"value\": \"wewfewfew\" } ], \"bbb\": [ {\"value\": \"wefwefw\" } ] }";
Gson gson = builder.create();
MyEntity entity= gson.fromJson(testString, MyEntity.class);
System.out.println(entity);
}
}