I have a List field in a class managed by a little-known proprietary framework.
The annotation #BindMagic is managed by the framework, so the underlying list mutates sometimes: it could be recreated or its elements could change.
class SharedEntity{
#BindMagic // this annotation does a magic that we cannot control
private List<Map<String,Object>> values;
public boolean isChangedSincePreviousCall(){
// check if "values" have changed since the previous call of this method
}
}
I'm agree that it is a poor design, but let's suppose there's no possibility to affect it.
Time to time (not on every mutation) it's needed to check if the list is changed. For instance, I want do it with the method isChangedSincePreviousCall.
Probably, something like a hash sum would be good. But I'm curious are there better ways.
What is the best practice to detect if the list is changed?
Using a hash is not definitive, because the same hash can be produced from different inputs, albeit with a very small chance.
"Being changed" and "being different" mean different things. Consider an entry in one of the maps that is changed from "A" -> 1 to "A" -> 2 then back to "A" -> 1 again between calls to your method - it was changed but isn't different. I'll assume you mean "different".
Make a copy when checking and compare that with the current state. Assuming that the map values are immutable:
class SharedEntity {
#BindMagic
private List<Map<String, Object>> values;
private List<Map<String, Object>> valuesCopy;
public boolean isChangedSincePreviousCall() {
newCopy = new ArrayList<>(values);
boolean result = !Objects.equals(valuesCopy, newCopy);
valuesCopy = newCopy;
return result;
}
}
If the Map values are (or contain) mutable objects, you'll have to make a deep copy of them when creating the copy.
FYI Objects#equals() returns true if both parameters are null.
The problem is probably the Thread accessing the list. It is most likely not supposed to be caught up in some kind of Listener-resolution, which is why there is no proper way of attaching a listener to the list.
However, if you have control over the SharedEntiry class, you could 'hack' into the list's access by using synchronized. However you expressly stated, that the list could be recreated, so I assume the instance stored behind values can actually be replaced.
Basically you have three cases:
1 The values-List is replaced by a new List:
Solve this by making a second reference on List:
private List<Map<String,Object>> valuesPrevious;
Whenever you check for change, check for identity of the lists first. If they are a mismatch, you can be sure the list changed (at least the instance, if not the content).
if (values != valuesPrevious) {
// handle change.
}
Yes, you still need to periodically check, but an identity-comparison is relatively cheap, and therefore an affordable thread to run in the background.
2 The values-List is replaced by a new List (of a type you did not set):
If that occures, move all values from the API's list to an instance of your observable list (described below), set values to that instance and wait for the next change to occure.
3 The values changed, but the instance is the same:
Solve this by using an ObservableList (if you are implementing in Java10+ https://docs.oracle.com/javase/10/docs/api/javafx/collections/ObservableList.html) or by implementing such a List yourself (probably by extending an existing List type).
Then, that listener only sets a 'dirty' flag, and your method knows that a change occured (and resets the flag).
In any way, my suggestion would be to ensure, that the Thread handling the change only triggers another Thread to handle the change, rather than lock the accessing thread, since I suspect, that your #BindMagic-API has some sort of runtime-relevant factor (for example, it is a network or database related shadow of something).
If you simply lock the thread, until you have handled your reaction, you might get weird effects, disconnects or end up accidentally blocking the server you are accessing.
I would try to use PropertyChangeListener objects. Here is an example for SharedEntity class. You can apply the same for the objects stored in list.
class SharedEntity {
private List<Map<String,Object>> values;
private PropertyChangeSupport pcs = new PropertyChangeSupport();
public void setValues(List<Map<String,Object>> values) {
List<Map<String,Object>> oldValues = this.values;
this.values= values;
pcs.firePropertyChange("values",oldValues, values);
}
public void addValue(Map<String, Object> value) {
// store old
// add new element
// fire change
}
public void removeValue(Map<String, Object> value) {
// store old
// remove value
// fire change
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}
You can use Observer Pattern to detect change in values.
You need to create Observable.
package com.psl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
public class MyList extends Observable{
private List<Map<String,Object>> values;
public List<Map<String, Object>> getValues() {
return values;
}
public void setValues(List<Map<String, Object>> values) {
if(getValues()==null && values!=null){
setChanged();
notifyObservers();
}
else if( !this.values.equals(values)){
setChanged();
notifyObservers();
}
this.values = values;
}
public static void main(String[] args) {
MyList myList = new MyList();
List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
Notify notify = new Notify();
myList.addObserver(notify);
Map<String, Object> map = new HashMap<String, Object>();
map.put("string_value", null);
myList.setValues(values);
}
}
You have to create observer which will observe changes in MyList
package com.psl;
import java.util.Observable;
import java.util.Observer;
public class Notify implements Observer{
#Override
public void update(Observable o, Object arg) {
System.out.println("List has been changed");
}
}
For more information about Observable Pattern https://springframework.guru/gang-of-four-design-patterns/observer-pattern/
Related
In a web application I want to execute some methods, that belong to different classes. Method calls will be made in a chain (1st method calls 2nd, 2nd calls 3rd... and so on). Each method is going to make some entries or updates in some hashmaps or other data structures. After all the methods are executed, I have to make some updates in my database. Based on values stored in hashmaps.
As per my understanding, I have below options to achieve this:
Keep passing the hashmaps, from one method to other.
I think it's a bad approach.
Keep those hashmaps in separate class. Create an object of that class and keep that object passing from one method to other and so on.
This approach looks better than 1st to me but it still involves passing an object from one object to other leading to a tightly coupled design.
Using static hashmaps
(or hashtables) or static object of the seperate class made as in option 2.
(This I think is worse approach because static variables will be shared aming different users).
Please help me in understanding the best approach.
You can apply builder pattern to avoid passing parameters between methods. It gives the opportunity of building all your necessary operations in one class and calling them in chain.
Assuming you have 3 operations on the map, I have demonstrated the use of builder design pattern in this scenario
public class MyMap {
Map<String, String> map;
public MyMap(MyMapBuilder builder) {
this.map = builder.map;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public static class MyMapBuilder {
Map<String, String> map;
public MyMapBuilder() {
this.map = new HashMap<String,String>();
}
public MyMapBuilder doOperationOne() {
new OperationOne().run(map);
return this;
}
public MyMapBuilder doOperationTwo() {
new OperationTwo().run(map);
return this;
}
public MyMapBuilder doOperationThree() {
new OperationThree().run(map);
return this;
}
public MyMap build() {
return new MyMap(this);
}
}
}
Here is your operation classes (dummy operations as example)
public class OperationOne {
public void run(Map<String, String> map) {
map.put("OpOne", "1");
}
}
public class OperationThree {
public void run(Map<String, String> map) {
map.put("OpThree", "3");
}
}
public class OperationTwo {
public void run(Map<String, String> map) {
map.put("OpTwo", "2");
}
}
And here is how it is called at final
MyMap resultMap = new MyMap.MyMapBuilder().doOperationOne().doOperationTwo().doOperationThree().build();
The resultMap object keeps the result Map.
If you want to go the OO route, you shouldn't think about the problem as "data" going through transformations.
Think about what all of that means. Make it a collaboration between objects that mean something in your domain. What is the thing that you want in the end? A Report? A Chart? A Price? Call it by name and create it.
Similarly, do not have transformations. You can name (and create) intermediary results, if that makes sense from the domain's point of view. For example to create a Report, you might need a Template first, or whatever.
In short, neither of those solutions look particularly object-oriented to me. But, you can call it functional (if the methods are pure functions), in which case solution #1 or #2 both could work.
Changing multiple internal data structures (belonging to different classes) makes the processing of the incoming web request as fully stateful. It might lead into concurrency issues OR slowness (if you take care of all locks). If the final goal is to make some updates to a database, then either you make them synchronously within the flow OR 'queue' up those events (internally/externally) and process them asynchronously. Each queue record, can hold the info about the DB update. To me, your use case is very similar to 'logging'. A logging framework also needs to make updates to a log file from multiple methods (while processing a single request).
I have an object with several lists
public class Contribution<T extends MovieRequest> {
private Set<T> elementsToAdd;
private Set<T> elementsToUpdate;
private Set<Integer> numbersToDelete;
}
This object is sent to the method. There I operate on these lists.
public void correctOtherTitle(
final Contribution<OtherTitle> contribution
) throws ResourceNotFoundException {
contribution.getElementsToAdd().forEach(otherTitle -> {
...
});
contribution.getNumbersToDelete().forEach(number -> {
...
});
contribution.getElementsToUpdate().forEach(otherTitleToUpdate -> {
...
});
}
The problem is that there is no need to complete all the lists and some of them may be null. And then throws a NullPointerException exception.
Of course, it is possible to make a condition if, but it does not look aesthetically.
if(contribution.getElementsToAdd() !- null) {
contribution.getElementsToAdd().forEach(otherTitle -> {
...
});
}
It looks fatal. Do you have an idea how to do it better?
To avoid not null check with explicit if , you could change the types of the Contribution class fields to Optional that wrap the actual data :
public class Contribution<T extends MovieRequest> {
private Optional<Set<T>> elementsToAdd;
private Optional<Set<T>> elementsToUpdate;
private Optional<Set<Integer>> numbersToDelete;
}
and adapt getters consequently.
In this way, you could use Optional.ifPresent(Consumer<? super T> consumer) that spares an explicit not null check :
contribution.getElementsToAdd().ifPresent(otherTitle -> {
otherTitle.forEach(m -> ...);
});
It is not necessary very elegant either. However, it reduces code duplication without introducing intermediary variables (that may create side effect).
Getter methods are indeed invoked once.
The problem is that there is no need to complete all the lists and some of them may be null.
I'd argue that you should fix the root problem, rather than work around it. Why can these sets be null? You already have a "safe" way to indicate that there's nothing to add/delete/update - an empty set. So if these sets are under your control (the fact that they are private and you have getters implies this), then you should enforce that invariant.
For example, maybe your Contribution class could look like this:
public class Contribution<T extends MovieRequest> {
private Set<T> elementsToAdd = new HashSet<>();
// ... same for elementsToUpdate / numbersToDelete ...
public Set<T> getElementsToAdd() {
return Collections.ummodifiableSet(elementsToAdd);
}
public void addElementToAdd(T element) {
elementsToAdd.add(element);
}
}
This pattern involves a fair amount of boilerplate. But code generators such as Immutables help a great deal with that.
There is no shortcut to check for not null, but you could implement a constructor on the Contribution class and initialize the sets to empty sets.
Also, if the code matters to you, I may suggest you to invest your efforts in trying to push the logic of the correctOtherTitle function into the Contribution class, because passing and object to a method that manipulates the object smells like an anemic domain.
I have existing codebase that sometimes uses ArrayList or LinkedList and I need to find a way to log whenever add or remove is called to track what has been either added or removed.
What is the best way to make sure I have logging in place?
So for example.
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(123);
and
LinkedList<Integer> anotherNewList = new LinkedList<Integer>();
anotherNewList.add(333);
Not sure if I can intercept add method to achieve this or create overriding class that implements java.util.List interface then use it instead. Either way I'm looking for a good solution that requires minimum intervention and prefrerrably without using any third party packages...
I would use the so called Decorator Pattern to wrap your lists.
This would be a simple example code just to give you an idea:
private static class LogDecorator<T> implements Collection<T> {
private final Collection<T> delegate;
private LogDecorator(Collection<T> delegate) {this.delegate = delegate;}
#Override
public int size() {
return delegate.size();
}
#Override
public boolean isEmpty() {
return delegate.isEmpty();
}
#Override
public boolean contains(Object o) {
return delegate.contains(o);
}
#Override
public Iterator<T> iterator() {
return delegate.iterator();
}
#Override
public Object[] toArray() {
return delegate.toArray();
}
#Override
public <T1> T1[] toArray(T1[] a) {
return delegate.toArray(a);
}
#Override
public boolean add(T t) {
// ADD YOUR INTERCEPTING CODE HERE
return delegate.add(t);
}
#Override
public boolean remove(Object o) {
return delegate.remove(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
#Override
public boolean addAll(Collection<? extends T> c) {
return delegate.addAll(c);
}
#Override
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
#Override
public void clear() {
delegate.clear();
}
}
There is not really a simple way to get there.
Those classes are part of the "standard libraries"; so you can't change their behavior. You could create your own versions of them; and use class path ordering to get them used; but this really dirty hack.
The only other option: extend those classes; #Override the methods you want to be logged; and make sure all your sources use your own versions of those classes. Or if you prefer composition over inheritance you go for the decorator pattern; as suggested by JDC's answer.
The "third" option is really different - you turn to aspect oriented programming (for example using AspectJ) and use such tools to manipulate things on a bytecode level. But that adds a whole new layer of "complexity" to your product; thus I am not counting it as real option.
EDIT on your answer: it seems that you don't understand the difference between interface and implementation?! An interface simply describes a set of method signatures; but in order to have real code behind those methods, there needs to be an implementing class. You see, when you do
List<X> things = new ArrayList<>();
the real type of things is ArrayList; but you rarely care about that real type; it is good enough to know that you can all those List methods on things. So, when you create some new implementation of the List interface ... that doesn't affect any existing
... = new ArrayList ...
declarations at all. You would have to change all assignments to
List<X> things = new YourNewListImplementation<>();
JDC has given a good way to follow.
I would like bring important precisions.
The decorator pattern allows to create a class which decorates another class by adding or removing dynamically a new responsibility to an instance.
In your case, you want to add responsibility.
Decorator is not an intrusive pattern but the decorator class have to conform to the class that it decorates.
So in your case, having a decorator which derives from the Collection interface is not conform to the decorated object since List has methods that Collection has not.
Your need is decorating List instances, so decorator should derive from the List type.
Besides, the decorator class can do, according its needs, a processing before and or after the operation of the class that it decorates but it is also responsible to call the original operation of the decorated class.
In your case, you want to know if an element was added or in or removed from the List. To achieve it, as the method result has consequences on whether you log or not the information, it is preferable to delegate first the processing to the decorated object and then your decorator can perform its processings.
Sometimes, you don't need to decorate a method, don't do it but don't forget to delegate suitably to the decorated object.
import java.util.Iterator;
import java.util.List;
public class DecoratorList<T> implements List<T> {
private static final Tracer tracer = ....;
private List<T> decorated;
private DecoratorList(List<T> decorated) {
this.decorated=decorated;
}
// no decorated methods
....
#Override
public int size() {
return this.decorated.size();
}
#Override
public boolean isEmpty() {
return this.decorated.isEmpty();
}
#Override
public boolean contains(Object o) {
return this.decorated.contains(o);
}
#Override
public Iterator<T> iterator() {
return this.decorated.iterator();
}
....
// end no decorated methods
// exemple of decorated methods
#Override
public void add(int index, T element) {
tracer.info("element " + element + " added to index " + index);
this.decorated.add(index,element);
}
#Override
public boolean remove(Object o) {
final boolean isRemoved = this.decorated.remove(o);
if (isRemoved){
tracer.info("element " + o + " removed");
}
return isRemoved;
}
}
As explained, a decorator is not intrusive for the decorated objects.
So the idea is not changing your code that works but add the decorating operation just after the list be instantiated.
If don't program by interface when you declare your list variables, that is you declare ArrayList list = new ArrayList() instead of List list = new ArrayList() , of course you should change the declared type to List but it doesn't break the code, on the contrary.
Here is your example code :
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(123);
LinkedList<Integer> anotherNewList = new LinkedList<Integer>();
anotherNewList.add(333);
Now, you could do it :
List<Integer> list = new ArrayList<Integer>();
list = new DecoratorList<Integer>(list); // line added
list.add(123);
List<Integer> anotherNewList = new LinkedList<Integer>();
anotherNewList = new DecoratorList<Integer>(anotherNewList); // line added
anotherNewList.add(333);
To ease the task and make it safer, you could even create a util method to apply the decoration on the list :
private static <T> List<T> decorateList(List<T> list) {
list = new DecoratorList<T>(list);
return list;
}
and call it like that :
List<Integer> list = new ArrayList<Integer>();
list = decorateList(list); // line added
list.add(123);
You can use Aspects - but it will log every add and remove call:
#Aspect
public class ListLoggerAspect {
#Around("execution(* java.util.List.add(..))")
public boolean aroundAdd(ProceedingJoinPoint joinPoint) throws Throwable {
boolean result = (boolean) joinPoint.proceed(joinPoint.getArgs());
// do the logging
return result;
}
}
You'll need to configure the aspect in META-INF/aop.xml :
<aspectj>
<aspects>
<aspect name="com.example.ListLoggerAspect"/>
</aspects>
</aspectj>
An easy way to accomplish this is wrapping your source list in a ObservableList and use that as base list. You can simply add an listener to this list to catch every modification (and log out if you wish)
Example:
List obs = FXCollections.observableList(myOriginalList);
obs.addListener(c -> {
for(Item it : c.getRemoved())
System.out.println(it);
for(Item it : c.getAddedSubList())
System.out.println(it);
});
See the javafx documentation on how to add a good listener
Your List is the source here. You need to keep track of the changes to the source. This is a good and natural example of the Observer pattern. You can create an Observable which is your list. Then create some Observers and register them to the Observable. When the Observable is changed, notify all the registered Observers. Inside the Observer you can log the changes using the input event. You should literally implement some ObservableCollection here. You can use Java Rx to get this work done. Please find the sample code given below.
package com.test;
import java.util.ArrayList;
import java.util.List;
import rx.Observable;
import rx.subjects.PublishSubject;
public class ObservableListDemo {
public static class ObservableList<T> {
protected final List<T> list;
protected final PublishSubject<T> onAdd;
public ObservableList() {
this.list = new ArrayList<T>();
this.onAdd = PublishSubject.create();
}
public void add(T value) {
list.add(value);
onAdd.onNext(value);
}
public Observable<T> getObservable() {
return onAdd;
}
}
public static void main(String[] args) throws InterruptedException {
ObservableList<Integer> observableList = new ObservableList<>();
observableList.getObservable().subscribe(System.out::println);
observableList.add(1);
Thread.sleep(1000);
observableList.add(2);
Thread.sleep(1000);
observableList.add(3);
}
}
Hope this helps. Happy coding !
We need a little more information to find the right solution. But I see a number of options.
You can track changes, using a decorator.
You can copy the collection and calculate the changes
You can use aspects to 'decorate' every List in the JVM
Change the existing codebase (a little bit)
1) works if you know exactly how the list is used, and once it is returned to your new code, you are the only user. So the existing code can't have any methods that add to the original list (because would invoke add/remove on the delegate instead of the decorated collection).
2) This approach is used when multiple classes can modify the list. You need to be able to get a copy of the list, before any modifications begin, and then calculate what happened afterwards. If you have access to Apache Collections library you can use CollectionUtils to calculate the intersection and disjunction.
3) This solution requires some for of weaving (compile or load time) as this will create a proxy for every List, so it can add callback code around the method calls. I would not recommend this option unless you have a good understanding of how aspects work, as this solution has a rather steep learning curve, and if something goes wrong and you need to debug you code, it can be a bit tricky.
4) You say existing codebase, which leads me to believe, that you could actually change the code if you really wanted. If this is at all possible, that is the approach I would choose. If the user of the List needs to be able to track changes, then the best possible solution is that the library returns a ChangeTrackingList (interface defining methods from tracking), which you could build using decoration.
One thing you have to be aware of when decorating, is that List has a removeAll() and a addAll(), these methods may or may not call the add() and remove(), this depends on the list implementation. If you are not aware of how these methods are invoked internally you could end up seeing an object as removed twice (unless you can use a set).
I often see lists of objects in java holding beans whose objects are picked by inspecting an ID field, i.e.
List<BeanObj> list = …
BeanObj myObj = null;
for(BeanObj b : list)
if(b.getId().equals(whatIAmLookingFor)){
myObj = b;
break;
}
(The second variant of this is storing the objects in Hibernate and retrieve them by SQL.)
Using a Map interface would really be sensible here, but there are difficulties, i.e.
the key field may be changed (in general, or even concurrently)
the key may be non-trivial to reach (think of b.getRoot().getAttribute("id").equals(…)
Have there been approaches to address this in a more efficient way, like implementing a
SpecialMap<String, BeanObj>("id") // use String getId() on BeanObj
or even
SpecialMap<String, BeanObj>("getRoot().getAttribute({0})", "id")
// use String getAttribute("id") on result of getRoot()
with add() instead put() which makes use of the id getter function to build its internal map? Probably this map will require the mapped objects to implement some interface to allow the map being notified of updates on the id field.
Perhaps the map could also take care that changing the ID of an object to an ID of an existing object is either not possible or results in dropping the object that previously had that ID.
You can manage the functionnal aspect of adding element to your map by using guava utilities:
import com.google.common.base.Function;
public class SpecialMap<K, V> extends HashMap<K, V>{
private Function<V, K> function;
public SpecialMap(Function<V, K> function) {
this.function = function;
}
public void add(V value) {
K key = function.apply(value);
this.put(key, value);
}
public static void main(String[] args) {
SpecialMap<String, BeanObj> specialMap = new SpecialMap<String, BeanObj>(new Function<BeanObj, String>() {
#Override
public String apply(BeanObj arg) {
return arg.getRoot().getAttribute("id");
}
});
specialMap.add(new BeanObj());
}
}
In this example, the function will map your bean type to a string key.
All,
Hopefully a simple question. I am thinking of the best way to implement a class which holds a number of collections and HashMaps where the class needs to know about when they have been modified outside of the class - i.e. added/removed/changed items. Each collection/hashmap needs to be exposed as a public getter in my class at the moment.
So my basic class looks like as follows...
public class MyClass {
protected final HashMap<String, String> _values = new HashMap<String, String>();
protected final ArrayList<MyOtherClass> _other = new ArrayList<MyOtherClass>();
protected final ArrayList<MyOtherClass2> _other2 = new ArrayList<MyOtherClass2>();
// ... implementation
public HashMap<String, String> getValues() {
return _values;
}
public ArrayList<MyOtherClass> getMyOtherClassList() {
return _other;
}
public ArrayList<MyOtherClass2> getMyOtherClassList2() {
return _other2;
}
public String getContent() {
// build the content based on other/other2...
StringBuilder sb = new StringBuilder();
// iterate through both collections to build content...
// ...
return sb.toString();
}
}
public getMyOtherClass {
public String name; // has getter and setter
public String value; // has getter and setter
}
public getMyOtherClass2 {
public String name; // has getter and setter
public String value; // has getter and setter
public String somethingElse; // has getter and setter
}
I want to add a key/value to the _values based on the length of the content i.e.-
_values.add("Length", getContent().length);
So the Length value is dynamic based on what gets added to the _other and _other2.
The problem with this is exposing the _values and _other with public getters is that anything outside the class can modify them. The class will not know if items have been modified.
A couple of solutions I can think of is to make the collection/hashmap readonly - but this throws a runtime exception - if this was the case I'd like the compiler to indicate that they are read-only and throw an exception but I don't know if this is possible.
The other way would be to add a add/remove for each of the collections/maps and update the Length property accordingly - but again, if the values change in the MyOtherClass, MyClass will still not know about it.
Alternatively write my own Hashmap/List/Collection to determine when items are added/removed, and possibly have a property change listener on the getMyOtherClass, getMyOtherClass2.
Any nice solutions to this?
Thanks,
Andez
Overide the map/list implementations and insert a call-back into the add/update/remove methods that triggers an update function on the parent.
Also it's bad form to create references directly to the implementations - this is better (read up on polymorphism for reasoning):
private Map<String,String> myMap = new HashMap<String,String>();
private List<String> myList = new List<String>();
In this case you can make use of some fundamentals of the Observer design pattern to have an Object "watching" the Maps and registering each change is made to them.
Create an object contains a Map and another object that contains a List, so since you have 1 map and 2 lists you'll have 3 of those "Observable" objects. Let's name the classes "ObservableMap" and "ObservableList". You can even create an abstract class "ObservableObject" and extend it with the previously mentioned classes.
These objects won't override the Map/List implementation, they'll only act as a wrapper by wrapping the methods you'll want to track to register the state and derive the call to modify the collection. For example, I'll post some code of the ObservableMap class (I'm instantiating the map with <String,String> but you can use generics here too if it suits you).
public Class ObservableMap extends ObservableObject{
private Map<String,String> map = new LinkedHashMap<String,String>();
private Watcher observer = new Watcher();
//Example of one of the wrapper methods (the other ones are like this one)
public void putObject(String key, String value) {
watcher.notifyPut(); //You can name the method the way you like and even pass
//the new key/value pair to identify what has been added.
map.put(key,value);
}
}
Here, the Watcher class is the one that registers the canges. It can either be a completely new Object (like in this case) or you can make an Interface and implement it in an existing class of yours to be able to set it as a watcher on your Observable objects.
Not 100% sure what you are asking. If you are trying to track changes to attributes to two classes you may wish, as other people have mentioned implement the observer pattern and raise notifications in the set methods. An alternative, that I have used successfully for implementing an undo mechanism is to use aspectJ or some other AOP (Aspect Orientated Programming) tool to intercept the set methods and perform the required notifications/updates that way.
Alternatively define an interface that only provides access to the getXXX operations and return those from your model, that way nothing can change the data.