blob: 19e52840fe7b113f4c9ee0ae137ef439429deccc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.util;
import java.util.Map;
/**
* Default {@link MapChangeTracker}.
*
* @author Abe White
*/
public class MapChangeTrackerImpl
extends AbstractChangeTracker
implements MapChangeTracker {
private final Map _map;
private boolean _keys = true;
/**
* Constructor; supply delegate map.
*/
public MapChangeTrackerImpl(Map map, boolean autoOff) {
_map = map;
this.setAutoOff(autoOff);
}
@Override
public boolean getTrackKeys() {
return _keys;
}
@Override
public void setTrackKeys(boolean keys) {
_keys = keys;
}
@Override
public void added(Object key, Object val) {
if (_keys)
super.added(key);
else
super.added(val);
}
@Override
public void removed(Object key, Object val) {
if (_keys)
super.removed(key);
else
super.removed(val);
}
@Override
public void changed(Object key, Object oldVal, Object newVal) {
if (_keys)
super.changed(key);
else {
super.removed(oldVal);
super.added(newVal);
}
}
@Override
protected void add(Object obj) {
// if the key was previously removed and now added back, mark
// it as a change; otherwise it's a new addition
if (rem != null && rem.remove(obj)) {
if (change == null)
change = newSet();
change.add(obj);
} else {
// after a point it becomes inefficient to track changes
if (getAutoOff() && getAdded().size() + getChanged().size()
+ getRemoved().size() >= _map.size())
stopTracking();
else {
if (add == null)
add = newSet();
add.add(obj);
}
}
}
@Override
protected void remove(Object obj) {
// no longer a change, if it was before
if (change != null)
change.remove(obj);
// if it was a new addition, just forget it; otherwise remember
// that it was removed
if (add == null || !add.remove(obj)) {
// after a point it becomes inefficient to track changes
if (getAutoOff() && getAdded().size() + getChanged().size()
+ getRemoved().size() >= _map.size())
stopTracking();
else {
if (rem == null)
rem = newSet();
rem.add(obj);
}
}
}
@Override
protected void change(Object key) {
// if the key is already changed or the key is newly added, nothing
// to do
if ((change != null && change.contains(key))
|| (add != null && add.contains(key)))
return;
// after a point it becomes inefficient to track changes
if (getAutoOff() && getAdded().size() + getChanged().size()
+ getRemoved().size() >= _map.size())
stopTracking();
else {
// record the change
if (change == null)
change = newSet();
change.add(key);
}
}
}