I need to connect a Boolean and a String. I also need a getter and a setter for each Boolean.
For example:
boolean errorFlag1;
private static final String errorMessage1 = "...";
boolean errorFlag2;
private static final String errorMessage2 = "...";
...
public Messages[] getErrorMessages()
{
if(errorFlag1)
Add errorMessage1 to Messages[]
if(errorFlag2)
Add errorMessage2 to Messages[]
...
}
public boolean getErrorFlag1()
{
return errorFlag1;
}
public setErrorFlag1( ef1 )
{
this.errorFlag1 = ef1;
}
...
Could I use Map here? Is there a better way of "connecting" flag with a message?
Another solution (I hope i did not misunderstood your goal ):
enum ErrorMessage
{
ERROR_ONE("First message"), ERROR_TWO("Second message");
private String message;
ErrorMessage(String str)
{
message = msg;
}
public String getMessage()
{
return message;
}
}
This way you have constant error messages which contain a String as "message". Their type is ErrorMessage, and when you pass one like ErrorMessage.ERROR_ONE you can get their message by the getter method.
If you wish to have a class, which contains your errors, then you can create a collection of errors, and add or remove errors as they occured.
I'm not sure how your error messages are being set, but I would suggest storing an Integer representing each error in a List<Integer>. Errors would be added to the List through an addError method which allows manipulation of the encapsulated list.
Then place the definition of your error messages within a Map<Integer,String>, whose key corresponds with the appropriate error message. This will allow you to create new errors simply by adding a new entry in the map.
private List<Integer> errors = new ArrayList<Errors>();
private static Map<Integer> errorLookup = new HashMap<Integer,String>();
static{
errorLookup.put(1, "Error Message 1");
errorLookup.put(2, "Error Message 2");
}
public void addError(Integer errorKey){
errors.add(errorKey);
}
public List<String> getErrors(){
List<String> errorMsgs = new ArrayList<String>();
for(Integer key: errors){
errorMsgs.add(this.errorLookup.get(key).value);
}
return errorMsgs;
}
You can use a Map for sure,so that number of error messages are runtime determined. Use errormessage as key and boolean as value.
Related
I setup a javax.xml.bind.ValidationEventHandler which listens for xml validation errors when unmarshalling an xml document.
Is there really a need to check if the List of errors isEmpty()?
Or should I remove it and just have the for loop?
I'm not sure if the for loop is any way more expensive than a simple if statement.
T instance = (T) unmarshaller.unmarshal(..);
if (!eventHandler.getErrors().isEmpty()) {
for (XSDValidationEventHandler.Error error : eventHandler.getErrors()) {
// extract error, and log it
}
}
XSDValidationEventHandler.java, custom ValidationEventHandler implementation:
public class XSDValidationEventHandler implements javax.xml.bind.ValidationEventHandler {
private List<Error> errors = new ArrayList<Error>();
#Override
public boolean handleEvent(ValidationEvent event) {
final Error error = new Error(event.getLocator().getLineNumber(), event.getMessage());
errors.add(error);
return true;
}
..
public class Error {
private int lineNumber;
private String message;
public Error(int lineNumber, String message) {
this.lineNumber = lineNumber;
this.message = message;
}
}
}
You don't need it in that particular scenario because the enhanced for loop won't do anything if is empty.
For other situations it might be needed, but I think that's extremely premature optimization, checking if for a boolean to be true or false is almost negligible.
You don't need to check the list is empty before starting the loop.
It ignore when the list size is zero. In this case, you need to check null for the list to prevent NullPointerException.
Here is my code
public class Validator {
private String message = "ok";
public String mainValidate(String value) {
if(!isAccept1()) {
message = "fail1";
return message;
}
if(!isAccept2()) {
message = "fail2";
return message;
}
if(!isAccept3()) {
message = "fail3";
return message;
}
return message;
}
public boolean isAccept1() {}
public boolean isAccept2() {}
public boolean isAccept3() {}
Requirement is: If the code meet any error, return message immediately.
As you can see, with current code, I repeat myself very much.
How can I structure the code and still keep requirement. If any error occur, the code skip other validate and return error message
Many thanks!
You can put all the checks in one method:
public String mainValidate(String value) {
String message = isAccept();
if(!message.equalsIgnoreCase("ok")) {
return message;
}
}
private String isAccept() {
String returnString = "ok";
//check1 - change returnString to whatever message if check fails
//check2 - change returnString to whatever message if check fails
//check3 - change returnString to whatever message if check fails
//etc...
return returnString;
}
You could store the actions / messages in a map and iterate over it:
private static final Map<Predicate<String>, String> VALIDATIONS = new LinkedHashMap<> ();
static {
VALIDATIONS.put(Validator::isAccept1, "fail1");
VALIDATIONS.put(Validator::isAccept2, "fail2");
//etc.
}
public String mainValidate(String value) {
for (Entry<Predicate<String>, String> v : VALIDATIONS.entrySet()) {
Predicate<String> validator = v.getKey();
String errorMsg = v.getValue();
if (!validator.test(value)) return errorMsg;
}
return "ok";
}
public static boolean isAccept1(String value) { return /* ... */; }
This is known as:
Design by Contract
or Precondition
or Method Argument Validation
See also A good Design-by-Contract library for Java?
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 a class
class Message
{
public String message, sender;
public Message (String msg, String from)
{
// check here that msg and from are not null. If so, use a default value or throw an NullPointerException
message = msg;
sender = from;
}
// Just a utility method for printing out the Message to System.out
public String toString () { return sender+":"+message; }
}
I am defining in main activity
Hashtable<String, ArrayList<Message>> table = new Hashtable<String, ArrayList<Message>>();
I want to pass this table variable to another fragment.How can I do this ?
Use Interface & have custom listeners.
Communicating with Other Fragments
I am using the Oval validation framework to validate fields that HTML fields cannot hold malicious javascript code. For the malicious code detection, I am using an external framework that returns me a list of errors that I would like to use as error messages on the field. The problem I am running into is that I can only setMessage in the check implementation, while I would rather do something like setMessages(List). So while I am currently just joining the errors with a comma, I would rather pass them back up as a list.
Annotation
#Target({ ElementType.METHOD, ElementType.FIELD})
#Retention( RetentionPolicy.RUNTIME)
#Constraint(checkWith = HtmlFieldValidator.class)
public #interface HtmlField {
String message() default "HTML could not be validated";
}
Check
public class HtmlFieldValidator extends AbstractAnnotationCheck<HtmlDefaultValue> {
public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
if (o1 == null) {
return true;
} else {
CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
if (cleanResults.getErrorMessages().size() > 0) {
String errors = StringUtils.join(cleanResults.getErrorMessages(), ", ");
this.setMessage(errors);
return false;
} else {
return true;
}
}
}
}
Model class
class Foo {
#HtmlField
public String bar;
}
Controller code
Validator validator = new Validator(); // use the OVal validator
Foo foo = new Foo();
foo.bar = "<script>hack()</script>";
List<ConstraintViolation> violations = validator.validate(bo);
if (violations.size() > 0) {
// inform the user that I cannot accept the string because
// it contains invalid html, using error messages from OVal
}
If setMessage(String message) is a method created by a superclass, you can override it and once it receives the data, simply split the string into a list and call a second function in which you would actually place your code. On a side note, I would also recommend changing the separating string to something more unique as the error message itself could include a comma.
Your question doesn't really make much sense though. If you are "passing them back up" to a method implemented in a superclass, then this voids the entire point of your question as the superclass will be handling the data.
I am going to assume the setError methods is a simple setter that sets a String variable to store an error message that you plan to access after checking the data. Since you want to have the data in your preferred type, just create a new array of strings in your class and ignore the superclass. You can even use both if you so desire.
public class HtmlFieldValidator extends AbstractAnnotationCheck<HtmlDefaultValue> {
public String[] errorMessages = null;
public void setErrorMessages(String[] s) {
this.errorMessages = s;
}
public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
if (o1 == null) {
return true;
} else {
CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
if (cleanResults.getErrorMessages().size() > 0) {
//String errors = StringUtils.join(cleanResults.getErrorMessages(), ", ");
//this.setMessage(errors);
this.setErrorMessages(cleanResults.getErrorMessages());
return false;
} else {
return true;
}
}
}
}
Elsewhere:
HtmlFieldValidator<DefaultValue> hfv = new HtmlFieldValidator<DefaultValue>();
boolean satisfied = hfv.isSatisfied(params);
if (!satisfied) {
String[] errorMessages = hfv.errorMessages;
//instead of using their error message
satisfy(errorMessages);//or whatever you want to do
}
EDIT:
After you updated your code I see what you mean. While I think this is sort of overdoing it and it would be much easier to just convert the string into an array later, you might be able to do it by creating a new class that extends Validator its setMessage method. In the method, you would call super.setMethod as well as splitting and storing the string as an array in its class.
class ValidatorWithArray extends Validator {
public String[] errors;
public final static String SPLIT_REGEX = ";&spLit;";// Something unique so you wont accidentally have it in the error
public void setMessage(String error) {
super.setMessage(error);
this.errors = String.split(error, SPLIT_REGEX);
}
}
In HtmlFieldValidator:
public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
if (o1 == null) {
return true;
} else {
CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
if (cleanResults.getErrorMessages().size() > 0) {
String errors = StringUtils.join(cleanResults.getErrorMessages(), ValidatorWithArray.SPLIT_REGEX);
this.setMessage(errors);
return false;
} else {
return true;
}
}
}
And now just use ValidatorWithArray instead of Validator
The situation in which I want to achieve this was different from yours, however what I found was best in my case was to create an annotation for each error (rather than having one that would return multiple errors). I guess it depends on how many errors you are likely to be producing in my case it was only two or three.
This method makes also makes your code really easy to reuse as you can just add the annotations wherenever you need them and combine them at will.