I've two classes I need to map (one way at the moment).
class Order1 {
int number;
String status;
}
class Order2 {
int number;
boolean canceled;
boolean confirmed;
}
I would like to do something like:
mapperFactory.classMap(Order1.class, Order2.class)
.map("status == 'Canceled'", "canceled")
.map("status == 'Confirmed'", "confirmed")
.byDefault().register();
Is there a way to do something like this?
Edit: I tried using a CustomMapper like this:
.customize(new CustomMapper<Order1, Order1>() {
#Override
public void mapAtoB(final Order1 a, final Order1 b, final MappingContext context) {
String status = a.getStatus();
b.setCanceled("Canceled".equals(status));
b.setConfirmed("Confirmed".equals(status));
}
})
This works, but it doesn't seem possible to add many customized mappers for the same pair of classes.
Instead, I used custom converters as Sidi's answer explains.
Thanks.
Can you just add public boolean isCanceled() and boolean isConfirmed() to class Order1 ?
Orika will auto map it
Or
Use you can create a converter StatusConverter taking String parameter, register it
converterFactory.registerConverter("canceled", new StatusConverter("Canceled"));
converterFactory.registerConverter("confirmed", new StatusConverter("Confirmed"));
Then
mapperFactory.classMap(Order1.class, Order2.class)
.fieldMap("status", "canceled").converter("canceled").add()
.fieldMap("status", "confirmed") .converter("confirmed").add()
.byDefault().register();
this converter should convert String to Boolean, return true if the given parameter is equals to the value.
Related
suppose I have defined a List as
private BlockingQueue<MyDelayed> DelayedIds = new DelayQueue<>();
class MyDelayed is like:
private class MyDelayed implements Delayed {
private String myId;
private Long creationTime;
MyDelayed (String myId) {
this.myId= myId;
this.creationTime = System.currentTimeMillis();
}
String getMyId() {
return this.myId;
}
#Override
public long getDelay(TimeUnit unit) {
//TODO
}
#Override
public int compareTo(Delayed o) {
//TODO
}
}
Now suppose that I want to add an Object of class MyDelayed in DelayedIds list.
I can do it by using add function.
But If I want to add obbject in list only if list does not contain an object of class MyDelayed which has the same myId attribute which I am trying to insert.
Obviously DelayedIds .contains(new MyDelayed(myId)) will not work.
Is there any easy way to check this thing ?
Am I missing something ?
You could write something like this and compare every element in the list to see if it contains your id. If at any point you find a matching one you return true, if the loop finished having found none it returns false.
public boolean contains(String id){
for (MyDelayed md : DelayedIds){
if(md.getMyId().equals(id)){
return true;
}
}
return false;
}
Now to check before adding you would do something like:
if(!contains(myNewObject.getMyId())){
DelayedIds.add(myNewObject)
}
Also, I'd suggest that you rename DelayedIds to delayedIds in order to follow coding standards (see Variables).
Can someone get me out of LambdaJ pit I fell into please?
let's assume I have a list of objects of this class:
private class TestObject {
private String A;
private String B;
//gettters and setters
}
Let's say I want to select the objects from the list where A.equals(B)
I tried this:
List<TestObject> theSameList = select(testList, having(on(TestObject.class).getA(), equalTo(on(TestObject.class).getB())));
but this returns an empty list
And this:
List<TestObject> theSameList = select(testList, having(on(TestObject.class).getA().equals(on(TestObject.class).getB())));
but that throws an exception [EDIT: due to known limitations of proxying final classes]
Note, One way of getting around this is to have a method that compares the two fields inside the TestObject, but let's assume I cannot do this for a reason of your choice.
What am I missing?
After poking and fiddling with LambdaJ to match on the fields of the same object, the only solution that is working for me is writing a custom matcher. Here's quick and dirty implementation of one that would do the job:
private Matcher<Object> hasPropertiesEqual(final String propA, final String propB) {
return new TypeSafeMatcher<Object>() {
public void describeTo(final Description description) {
description.appendText("The propeties are not equal");
}
#Override
protected boolean matchesSafely(final Object object) {
Object propAValue, propBValue;
try {
propAValue = PropertyUtils.getProperty(object, propA);
propBValue = PropertyUtils.getProperty(object, propB);
} catch(Exception e) {
return false;
}
return propAValue.equals(propBValue);
}
};
}
The PropertyUtils is the class from org.apache.commons.beanutils
The way to use this matcher:
List<TestObject> theSameList = select(testList, having(on(TestObject.class), hasPropertiesEqual("a", "b")));
I have the following code:
sshCPList.add(new SSHParameter("ssh root#io1", "Password:", "(yes/no)?"));
sshCPList.add(new SSHParameter(rootpwd, rootPrompt, null));
sshCPList.add(new SSHParameter("ssh root#io1", "Password:", "(yes/no)?"));
sshCPList.add(new SSHParameter(rootpwd, rootPrompt, null));
if(!ssh2.sendSshShellCommandToUnknownHost(sshCPList)){
theLogger.error("Failed to Authorize the PMF function to login as root");
result = false;
}
I want to define the following:
when(ssh2.sendSshShellCommandToUnknownHost(*a specific List which contains the four SSHParameter object or has 4 items or sonmething*).thenReturn(false);
The problem is I can not define that List as a proper input.
Any advice or solution?
You can use eq(T value) where value is that specific list.
Something like:
List<SSHParameter> expectedList = prepareExpectedList();
when(ssh2.sendSshShellCommandToUnknownHost(eq(expectedList)).thenReturn(false)
prepareExpectedList(); returns a list that is equals to the input that you are going to supply in the test.
see http://docs.mockito.googlecode.com/hg/latest/org/mockito/Matchers.html
In order to generate a custom Matcher you can use:
private static class MyListMatcher extends ArgumentMatcher<List<SSHParameter>> {
private List<SSHParameter> expectedList;
private MyListMatcher (List<SSHParameter> expectedList) {
this.expectedList= expectedList;
}
#Override
public boolean matches(Object obj) {
List<SSHParameter> listToMatch = (List<SSHParameter>) obj;
boolean result = true;// check whatever you want between listToMatch and expectedList (size, elements etc.);
return result;
}
}
and use it:
when(ssh2.sendSshShellCommandToUnknownHost(argThat(new MyListMatcher(expectedList))).thenReturn(false);
I don't understand how I can retrieve the Enum values in an annotation processor.
My annotation is a custom Java Bean Validation annotation:
#StringEnumeration(enumClass = UserCivility.class)
private String civility;
On my annotation processor, I can access to instances of these:
javax.lang.model.element.AnnotationValue
javax.lang.model.type.TypeMirror
javax.lang.model.element.TypeElement
I know it contains the data about my enum since I can see that in debug mode. I also see ElementKind == Enum
But I want to get all the names for that Enum, can someone help me please.
Edit: I don't have access to the Class object of this Enum, because we are in an annotation processor, and not in standart Java reflection code. So I can't call Class#getEnumConstants() or EnumSet.allOf(MyEnum.class) unless you tell me how I can get the Class object from the types mentioned above.
I found a solution (this uses Guava):
class ElementKindPredicate<T extends Element> implements Predicate<T> {
private final ElementKind kind;
public ElementKindPredicate(ElementKind kind) {
Preconditions.checkArgument(kind != null);
this.kind = kind;
}
#Override
public boolean apply(T input) {
return input.getKind().equals(kind);
}
}
private static final ElementKindPredicate ENUM_VALUE_PREDICATE = new ElementKindPredicate(ElementKind.ENUM_CONSTANT);
public static List<String> getEnumValues(TypeElement enumTypeElement) {
Preconditions.checkArgument(enumTypeElement.getKind() == ElementKind.ENUM);
return FluentIterable.from(enumTypeElement.getEnclosedElements())
.filter(ENUM_VALUE_PREDICATE)
.transform(Functions.toStringFunction())
.toList();
}
The answer given by Sebastian is correct, but if you're using Java 8 or above, you can use the following (cleaner) approach than using Google Guava.
List<String> getEnumValues(TypeElement enumTypeElement) {
return enumTypeElement.getEnclosedElements().stream()
.filter(element -> element.getKind().equals(ElementKind.ENUM_CONSTANT))
.map(Object::toString)
.collect(Collectors.toList());
}
Here's a complete example. Note the use of getEnumConstants on the enum values.
public class Annotate {
public enum MyValues {
One, Two, Three
};
#Retention(RetentionPolicy.RUNTIME)
public #interface StringEnumeration {
MyValues enumClass();
}
#StringEnumeration(enumClass = MyValues.Three)
public static String testString = "foo";
public static void main(String[] args) throws Exception {
Class<Annotate> a = Annotate.class;
Field f = a.getField("testString");
StringEnumeration se = f.getAnnotation(StringEnumeration.class);
if (se != null) {
System.out.println(se.enumClass());
for( Object o : se.enumClass().getClass().getEnumConstants() ) {
System.out.println(o);
}
}
}
}
This will print out:
Three
One
Two
Three
I am validating the status of a record retrieved from the DB by defining an ENUM as below
public enum RecordStatusEnum {
CREATED("CREATED"),
INSERTED("INSERTED"),
FAILED("FAILED");
private String recordStatusValue;
RecordStatusEnum (String status) {
recordStatusValue= status;
}
public boolean isSuccess() {
return (this.equals(CREATED) || this.equals(INSERTED));
}
}
The method isSuccess() is being used to check the status of the retrieved record ( column status from employee)
if (!(employee.getStatus().isSuccess())) {
// return error
}
As per the new requirement, there are a set of conditions introduced say A,B and C; and for them there is a column in the Employee table 'condition'.
So I need to retrieve the status as well as the condition and see if it belongs to a set which has the combination of both.
For eg : isSuccess() should check if in the following:
CREATED and A
CREATED and B
INSERTED and C
This must be achieved such that it is easy for me to add a new combination say 'INSERTED and B' into the list easily.
What is the best approach for the above problem?
Note : in the actual business scenario there are a whole lot more statuses and checks (eg isFailed() canBeModified() etc) with many different combinations
And any method can be suggested even if it doesn't use ENUMS. I mentioned ENUMS, because I dont want to deviate much from the existing implementation
There are many possibilities, but you could do like this (I removed the String status, which doesn't add any value since it's equal to the name of the enum):
public enum RecordStatusEnum {
CREATED(Condition.A, Condition.B),
INSERTED(Condition.C),
FAILED();
private Set<Condition> successConditions;
RecordStatusEnum(Condition... successConditions) {
this.successConditions = EnumSet.copyOf(Arrays.asList(successConditions));
}
public boolean isSuccess(Condition c) {
return successConditions.contains(c);
}
}
EDIT:
Example with two sets of conditions:
public enum RecordStatusEnum {
CREATED(EnumSet.of(Condition.A, Condition.B),
EnumSet.of(Condition.C)),
INSERTED(EnumSet.of(Condition.C),
EnumSet.of(Condition.B),
FAILED(EnumSet.noneOf(Condition.class),
EnumSet.noneOf(Condition.class));
private Set<Condition> successConditions;
private Set<Condition> modificationConditions;
RecordStatusEnum(Set<Condition> successConditions,
Set<Condition> modificationConditions) {
this.successConditions = successConditions;
this.modificationConditions = modificationConditions;
}
public boolean isSuccess(Condition c) {
return successConditions.contains(c);
}
public boolean canBeModified(Condition c) {
return modificationConditions.contains(c);
}
}
You could also compare the ordinal values, like so:
public enum RecordStatusEnum {
CREATED,
INSERTED,
UPDATED,
NEW,
FAILED,
FAILED_NO_DB,
FAILED_CONSTRAINT_VIOLATION;
public boolean isPersisted(RecordStatusEnum status) {
return status.ordinal < NEW.ordinal;
}
public boolean isError(RecordStatusEnum status){
return status.ordinal >= FAILED.ordinal;
}
}