📄 propertymapimpl.java
字号:
/*
* Copyright (C) 2004 NNL Technology AB
* Visit www.infonode.net for information about InfoNode(R)
* products and how to contact NNL Technology AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
// $Id: PropertyMapImpl.java,v 1.28 2005/12/04 13:46:06 jesper Exp $
package net.infonode.properties.propertymap;
import net.infonode.properties.base.Property;
import net.infonode.properties.base.exception.InvalidPropertyException;
import net.infonode.properties.propertymap.ref.*;
import net.infonode.properties.propertymap.value.PropertyRefValue;
import net.infonode.properties.propertymap.value.PropertyValue;
import net.infonode.properties.propertymap.value.ValueDecoder;
import net.infonode.properties.util.PropertyChangeListener;
import net.infonode.properties.util.PropertyPath;
import net.infonode.util.Printer;
import net.infonode.util.Utils;
import net.infonode.util.ValueChange;
import net.infonode.util.collection.map.ConstVectorMap;
import net.infonode.util.collection.map.MapAdapter;
import net.infonode.util.collection.map.SingleValueMap;
import net.infonode.util.collection.map.base.ConstMap;
import net.infonode.util.collection.map.base.ConstMapIterator;
import net.infonode.util.collection.map.base.MapIterator;
import net.infonode.util.collection.notifymap.AbstractConstChangeNotifyMap;
import net.infonode.util.collection.notifymap.ChangeNotifyMapWrapper;
import net.infonode.util.collection.notifymap.ConstChangeNotifyMap;
import net.infonode.util.collection.notifymap.ConstChangeNotifyVectorMap;
import net.infonode.util.signal.Signal;
import net.infonode.util.signal.SignalListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.*;
/**
* @author $Author: jesper $
* @version $Revision: 1.28 $
*/
public class PropertyMapImpl implements PropertyMap {
private static final int SERIALIZE_VERSION = 1;
private class PropertyObjectMap extends AbstractConstChangeNotifyMap implements SignalListener {
private boolean listenerActive;
PropertyObjectMap() {
}
protected void listenerAdded() {
if (!listenerActive) {
listenerActive = true;
addInheritedReferences();
superMap.getChangeSignal().add(this);
}
}
public void signalEmitted(Signal signal, Object object) {
ConstMap changes = (ConstMap) object;
MapAdapter m = new MapAdapter();
for (ConstMapIterator iterator = changes.constIterator(); iterator.atEntry(); iterator.next()) {
Property property = (Property) iterator.getKey();
if (propertyGroup.hasProperty(property)) {
PropertyValue currentValue = (PropertyValue) values.get(property);
if (currentValue == null || currentValue.getParent() != null) {
ValueChange vc = (ValueChange) iterator.getValue();
PropertyValue superValue = (PropertyValue) vc.getNewValue();
PropertyValue newValue = superValue == null ? null : superValue.getSubValue(PropertyMapImpl.this);
internalSetValue(property, newValue);
m.put(property, new ValueChange(currentValue != null ? currentValue : vc.getOldValue(),
newValue != null ? newValue : vc.getNewValue()));
}
}
}
if (!m.isEmpty())
fireEntriesChanged(m);
}
protected void lastListenerRemoved() {
if (listenerActive) {
listenerActive = false;
superMap.getChangeSignal().remove(this);
removeInheritedReferences();
}
}
public boolean checkListeners(Set visited) {
for (Iterator it = getChangeSignalInternal().iterator(); it.hasNext();) {
Object l = it.next();
if (l instanceof PropertyRefValue) {
PropertyRefValue v = (PropertyRefValue) l;
if (v.getMap().checkListeners(visited))
return true;
}
}
return false;
}
public void updateListeners() {
for (Iterator it = getChangeSignalInternal().iterator(); it.hasNext();) {
if (!(it.next() instanceof PropertyRefValue)) {
return;
}
}
for (Iterator it = getChangeSignalInternal().iterator(); it.hasNext();) {
Object l = it.next();
if (l instanceof PropertyRefValue) {
PropertyRefValue v = (PropertyRefValue) l;
if (v.getMap().checkListeners(new HashSet())) {
return;
}
}
}
lastListenerRemoved();
}
private void addInheritedReferences() {
for (ConstMapIterator iterator = values.constIterator(); iterator.atEntry(); iterator.next()) {
Property property = (Property) iterator.getKey();
PropertyValue currentValue = (PropertyValue) values.get(property);
currentValue.updateListener(true);
}
for (ConstMapIterator iterator = superMap.constIterator(); iterator.atEntry(); iterator.next()) {
Property property = (Property) iterator.getKey();
if (propertyGroup.hasProperty(property)) {
PropertyValue currentValue = (PropertyValue) values.get(property);
if (currentValue == null || currentValue.getParent() != null) {
PropertyValue superValue = (PropertyValue) iterator.getValue();
PropertyValue newValue = superValue == null ? null : superValue.getSubValue(PropertyMapImpl.this);
internalSetValue(property, newValue);
}
}
}
}
private void removeInheritedReferences() {
ArrayList toBeRemoved = new ArrayList();
for (ConstMapIterator iterator = values.constIterator(); iterator.atEntry(); iterator.next()) {
Property property = (Property) iterator.getKey();
PropertyValue currentValue = (PropertyValue) values.get(property);
if (currentValue.getParent() != null) {
currentValue.unset();
toBeRemoved.add(property);
}
else {
currentValue.updateListener(false);
}
}
for (int i = 0; i < toBeRemoved.size(); i++) {
values.remove(toBeRemoved.get(i));
}
}
public Object get(Object key) {
return vectorMap.get(key);
}
public boolean containsKey(Object key) {
return vectorMap.containsKey(key);
}
public boolean containsValue(Object value) {
return vectorMap.containsValue(value);
}
public boolean isEmpty() {
return vectorMap.isEmpty();
}
public ConstMapIterator constIterator() {
return vectorMap.constIterator();
}
protected void fireEntriesChanged(ConstMap changes) {
super.fireEntriesChanged(changes);
}
}
private PropertyMapGroup propertyGroup;
private PropertyMapImpl parent;
private PropertyMapProperty property;
private ChangeNotifyMapWrapper values = new ChangeNotifyMapWrapper(new MapAdapter());
private ConstChangeNotifyVectorMap superMap = new ConstChangeNotifyVectorMap();
private ConstVectorMap vectorMap = new ConstVectorMap();
private PropertyObjectMap map = new PropertyObjectMap();
private ArrayList superMaps = new ArrayList(1);
private MapAdapter childMaps = new MapAdapter();
private HashMap propertyChangeListeners;
private ArrayList listeners;
private ArrayList treeListeners;
private SignalListener mapListener;
public PropertyMapImpl(PropertyMapGroup propertyGroup) {
this(propertyGroup, null);
}
public PropertyMapImpl(PropertyMapImpl inheritFrom) {
this(inheritFrom.getPropertyGroup(), inheritFrom);
}
public PropertyMapImpl(PropertyMapGroup propertyGroup, PropertyMapImpl superObject) {
this(propertyGroup, null, null);
if (superObject != null)
addSuperMap(superObject);
}
public PropertyMapImpl(PropertyMapImpl parent, PropertyMapProperty property) {
this(property.getPropertyMapGroup(), parent, property);
}
public PropertyMapImpl(PropertyMapGroup propertyGroup, PropertyMapImpl parent, PropertyMapProperty property) {
this.parent = parent;
this.property = property;
this.propertyGroup = propertyGroup;
Property[] properties = this.propertyGroup.getProperties();
for (int i = 0; i < properties.length; i++) {
if (properties[i] instanceof PropertyMapProperty) {
PropertyMapProperty p = (PropertyMapProperty) properties[i];
PropertyMapImpl propertyObject = new PropertyMapImpl(this, p);
childMaps.put(p, propertyObject);
}
}
vectorMap.addMap(values);
vectorMap.addMap(superMap);
}
private boolean hasTreeListener() {
return (treeListeners != null && treeListeners.size() > 0) || (parent != null && parent.hasTreeListener());
}
private boolean hasListener() {
return hasTreeListener() ||
(listeners != null && listeners.size() > 0) ||
(propertyChangeListeners != null && propertyChangeListeners.size() > 0);
}
private void updateListenerRecursive() {
updateListener();
for (ConstMapIterator iterator = childMaps.constIterator(); iterator.atEntry(); iterator.next())
((PropertyMapImpl) iterator.getValue()).updateListenerRecursive();
}
private void updateListener() {
if (hasListener()) {
if (mapListener == null) {
mapListener = new SignalListener() {
public void signalEmitted(Signal signal, Object object) {
PropertyMapManager.getInstance().addMapChanges(PropertyMapImpl.this, (ConstMap) object);
}
};
map.getChangeSignal().add(mapListener);
}
}
else {
if (mapListener != null) {
map.getChangeSignal().remove(mapListener);
mapListener = null;
map.updateListeners();
}
}
}
private boolean checkListeners(Set visited) {
if (visited.contains(this))
return false;
visited.add(this);
return hasListener() || map.checkListeners(visited);
}
public ConstChangeNotifyMap getMap() {
return map;
}
public PropertyMap getSuperMap() {
return superMaps.size() == 0 ? null : (PropertyMap) superMaps.get(0);
}
public Object removeValue(Property property) throws InvalidPropertyException {
checkProperty(property);
PropertyValue value = (PropertyValue) values.get(property);
// Can't removeValue not set values or inherited reference values
if (value == null || value.getParent() != null)
return null;
values.remove(property);
PropertyMapManager.getInstance().beginBatch();
try {
firePropertyValueChanged(property, new ValueChange(value, getValue(property)));
}
finally {
PropertyMapManager.getInstance().endBatch();
}
return value.get(this);
}
private PropertyMapRef getPathFrom(PropertyMapImpl parentObject) {
if (parent == null)
return null;
if (parent == parentObject)
return new PropertyMapPropertyRef(property);
PropertyMapRef parentRef = parent.getPathFrom(parentObject);
return parentRef == null ? null : new CompositeMapRef(parentRef, new PropertyMapPropertyRef(property));
}
private PropertyMapRef getRelativePathTo(PropertyMapImpl propertyObject) {
PropertyMapRef ref = propertyObject == this ? ThisPropertyMapRef.INSTANCE : propertyObject.getPathFrom(this);
return ref == null ?
parent == null ?
null : new CompositeMapRef(ParentMapRef.INSTANCE, parent.getRelativePathTo(propertyObject)) :
ref;
}
public Object createRelativeRef(Property fromProperty, PropertyMap toObject, Property toProperty) {
PropertyValue value = setValue(fromProperty,
new PropertyRefValue(this,
fromProperty,
getRelativePathTo((PropertyMapImpl) toObject),
toProperty,
null));
return value == null ? null : value.getWithDefault(this);
}
public int getSuperMapCount() {
return superMaps.size();
}
public void addSuperMap(PropertyMap superMap) {
PropertyMapImpl superMapImpl = (PropertyMapImpl) superMap;
/* if (!propertyObjectImpl.propertyGroup.isA(propertyGroup))
throw new RuntimeException("Property group '" + propertyObjectImpl.propertyGroup + "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -