Already referred few question here and there.
Use Case -
1.) Given any Two objects, compare both of them property by property.
2.) It will contains Collections also, now compare collections of both the objects, now inside collection same data can be upside down, meaning say i have List<Address>, it contains two entries in both (say Residential Address, Office Address), but in both list the data may be at different indexes.
3.) Need to create 3rd Object of same type, with similar data copied, and properties set to null with different data.
4.) It might have reference classes as well.
I tired many solutions but stuck somewhere or the other, i am thinking of writing some generic solution. Though of generating two xml's out of the two objects and then comparing node by node, but just want to get more options.
Or How much Java reflection is stronger in this case.
answer to #markspace question.
To access a private field you will need to call the Class.getDeclaredField(String name) or Class.getDeclaredFields() method. The methods Class.getField(String name) and Class.getFields() methods only return public fields, so they won't work.
To access a private method you will need to call the Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods() method. The methods Class.getMethod(String name, Class[] parameterTypes) and Class.getMethods() methods only return public methods.
XMLUnit will work, it compares the list references recursively, also it has option to exclude fields which you do not wish to compare.
String expectedXML = "some xml";
String actualXML = "some xml";
DetailedDiff diff1 = new DetailedDiff(XMLUnit.compareXML(expectedXML, actualXML));
diff1.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
System.out.println("Differences found: " + diff1.getAllDifferences().toString());
RecursiveElementNameAndTextQualifier
Compares all Element and Text nodes in two pieces of XML. Allows
elements of complex, deeply nested types that are returned in
different orders but have the same content to be recognized as
comparable.
Related
This is either a Java coding design question, or a domain modelling question, I'm not sure yet!
Background, simplified as I can't share all the detail:
The system I'm working on is deployed in multiple instances (e.g. at different customers, and at one customer there may be development, test, preprod, prod instances)
The system configuration is a list of ConfigArtefact<T>, where T indicates that it might be a database connection configuration, or a predefined-query, or....
ConfigArtefacts are named. The names are semantically meaningful/well-known (e.g there could be an object for "Console.translations.en", "Console.translations.fr") or "Application.Database.connection.credentials", "Reporting.Database.connection.credentials") and are distinct for each deployment- no two different ConfigArtefacts will have the same name for a given deployment
ConfigArtefacts have other attributes (e.g. for the database, username and password) depending on the type used for <T>. The value of the attributes could be different in different deployments of this system.
There's no natural ordering of artefacts, even ones of the same type <T>. Where some arbitrary ordering is needed, I use the name.
Goal:
I need to write something that compares the configuration of two deployments of this system and identify Artifacts that have been added, removed, or changed. In order to find the same artefact on each deployment, I need to compare by name only (I always know what type of artefact I'm working with). In order to say if they've changed, I need to compare by all other attributes.
So, two kinds of comparison. One can be modelled with equals/hashcode, but not the other. Which should use equals()? (I think the one by name, as then added and deleted are just set subtraction, using one of the many collection libraries).
Would that be the normal choice? And if so, is there a conventional name for the other ("full compare") one? I'm considering identicalTo() (so two objects are changed if one.identicalTo(two) is false)
Your design is flawed - you have misused equals() by only comparing name.
If all attributes must be compared to know if the object has changed, then it is not true that objects with the same name are “equal”, because the use of the word “changed” implies there’s a difference, and if there’s a difference they’re not equal.
Finding something by using an identifier is different to two objects being equal if they have the same identifier.
Implement equals() and hashCode() using all attributes that matter for determining if an object is “different”.
To facilitate convenience and performance, populate a Map<String, ConfigArtefact<?>> for each environment using the name as the key.
Finding differences between 2 such maps is a fairly trivial O(n) task.
I have a Java Object, Record . It represents a single record as a result of SQL execution. Can CQEngine index collection of Record ?
My class is of the form
public class Record {
private List<String> columnNames;
private List<Object> values;
... Other getters
}
I have looked through some examples, but I have no luck there.
I want to index only specific column(s) with its name and corresponding value. Can this be achived using cqengine or is there any other alternatives to achieve the same.
Thanks.
That seems to be a strange way to model data, but you can use CQEngine with that model if you wish.
(First off, CQEngine will have no use for your column names so you can remove that field.)
To do this, you will need to define a CQEngine virtual attribute for each of the indexes in your list of values.
Each attribute will need to be declared with the data type which will be stored in that column/index, and will need to be able to cast the object at that index in your list of values, to the appropriate data type (String, Double, Integer etc.).
So let's say your Record has a column called 'price', which is of type Double, and is stored at index 5 in the list of values. You could define an attribute which reads it as follows:
public static final Attribute<Record, Double> PRICE =
attribute("PRICE", record -> ((Double) record.values.get(5));
If this sounds complicated, it's because that way of modelling data makes things a bit complicated :) It's usually easier to work with a data model which leverages the Java type system (which your model does not). As such, you will need to keep track of the data types etc. of each field programmatically yourself.
CQEngine itself will work fine with that model though, because at the end of the day CQEngine attributes don't need to read fields, the attributes are just functions which are programmed to fetch values.
There's a bunch of stuff not covered above. For example can your values be null? (if so, you should use the nullable variety of attributes as discussed in the CQEngine docs. Or, might each of your Record objects have different sets of columns? (if so, you can create attributes on-the-fly when you encounter a new column, but you should probably cache the attributes you have created somewhere).
Hope that helps,
Niall (CQEngine author)
In unit tests I usually use something like
assertThat(someObject).isEqualTo(someOtherObject);
to make sure these two objects have identical content. But what to do in case objects have identical content except certain fields?
Normally it would be like that:
assertThat(someObject.getFirstField()).isNotEqualTo(someOtherObject.getFirstField());
assertThat(someObject.getLastField()).isNotEqualTo(someOtherObject.getLastFieldd());
// and then gazilion fields that should be equal
assertThat(someObject.getNthField()).isEqualTo(someOtherObject.getNthField());
// ...
For obvious reasons, it is very unwieldy for bigger classes with a lot of fields. Is there way to specify that you expect certain fields to be not equal, but rest equal?
Both someObject and someOtherObject are same class that is Lomboked, so equals() is automatically handled.
If you are open to using assertJ then there is a very simple solution to your problem. Use
assertThat(someObject).isEqualToIgnoringGivenFields(someObjectOther, "firstField", "lastField")
Bear in mind that this uses reflection internally and failures can happen if you change the name of your fields inside the class which you want to ignore.
More on this Field by field comparisons
I have two types of java beans that can be associated with a User java bean:
PrivateTeacher and CompanyTeacher.
These two java beans are similar, only for one of their properties, say "subject", the PrivateTeacher will always have one while the CompanyTeacher can have several.
Would it make more sense to have a single java bean for both of these types of users where the "subject" field will be an ArrayList and the PrivateTeacher will only fill one element of the ArrayList whereas the CompanyTeacher can fill several?
Or should I have two separate java beans: one with an int field and another with an ArrayList<Integer> field (for the subject id's field)?
On one hand, the latter way is more precise. On the other, I don't want to limit methods that I have such as say, "findTeachers", which could satisfy both types of java beans (pass a parameter saying the bean type: "company" or "private" and then the User bean will be different but the Teacher bean will be the same).
Any suggestions or explanations?
Thank you
It depends...
If you want to treat both PrivateTeacher and CompanyTeacher in the same manner (polymorphicaly) then List<Integer> (not ArrayList) would be a better approach. But if this is not the case then - use the more precise way to describe them.
You can have a PrivateTeacher that supports both methods:
public String getSubject(int index) {
return index < subjects.size() ? subjects.get(index) : subjects.get(subjects.size()-1);
}
public String getSubject() {
return getSubject(0);
}
I've got loads of the following to implement.
validateParameter(field_name, field_type, field_validationMessage, visibleBoolean);
Instead of having 50-60 of these in a row, is there some form of nested hashmap/4d array I can use to build it up and loop through them?
Whats the best approach for doing something like that?
Thanks!
EDIT: Was 4 items.
What you could do is create a new Class that holds three values. (The type, the boolean, and name, or the fourth value (you didn't list it)). Then, when creating the HashMap, all you have to do is call the method to get your three values. It may seem like more work, but all you would have to do is create a simple loop to go through all of the values you need. Since I don't know exactly what it is that you're trying to do, all I can do is provide an example of what I'm trying to do. Hope it applies to your problem.
Anyways, creating the Class to hold the three(or four) values you need.
For example,
Class Fields{
String field_name;
Integer field_type;
Boolean validationMessageVisible;
Fields(String name, Integer type, Boolean mv) {
// this.field_name = name;
this.field_type = type;
this.validationMessageVisible = mv;
}
Then put them in a HashMap somewhat like this:
HashMap map = new HashMap<String, Triple>();
map.put(LOCAL STRING FOR NAME OF FIELD, new Field(new Integer(YOUR INTEGER),new Boolean(YOUR BOOLEAN)));
NOTE: This is only going to work as long as these three or four values can all be stored together. For example if you need all of the values to be stored separately for whatever reason it may be, then this won't work. Only if they can be grouped together without it affecting the function of the program, that this will work.
This was a quick brainstorm. Not sure if it will work, but think along these lines and I believe it should work out for you.
You may have to make a few edits, but this should get you in the right direction
P.S. Sorry for it being so wordy, just tried to get as many details out as possible.
The other answer is close but you don't need a key in this case.
Just define a class to contain your three fields. Create a List or array of that class. Loop over the list or array calling the method for each combination.
The approach I'd use is to create a POJO (or some POJOs) to store the values as attributes and validate attribute by attribute.
Since many times you're going to have the same validation per attribute type (e.g. dates and numbers can be validated by range, strings can be validated to ensure they´re not null or empty, etc), you could just iterate on these attributes using reflection (or even better, using annotations).
If you need to validate on the POJO level, you can still reuse these attribute-level validators via composition, while you add more specific validations are you´re going up in the abstraction level (going up means basic attributes -> pojos -> pojos that contain other pojos -> etc).
Passing several basic types as parameters of the same method is not good because the parameters themselves don't tell much and you can easily exchange two parameters of the same type by accident in the method call.