2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.scripting.php.dbginterface.models;
44
import java.beans.Customizer;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
47
import java.util.ArrayList;
48
import java.util.Collection;
49
import java.util.HashMap;
50
import java.util.HashSet;
51
import java.util.Iterator;
52
import java.util.List;
55
import org.netbeans.modules.scripting.php.dbginterface.api.VariableNode;
56
import org.netbeans.spi.viewmodel.ModelEvent;
57
import org.openide.util.NbBundle;
63
public class Variable implements VariableNode, PropertyChangeListener, Customizer, Cloneable {
64
public static final String PROP_VALUE = "value"; // NOI18N
65
public static enum Type {
77
private static final Map<Type, String> typeStringMap;
79
typeStringMap = new HashMap<Type, String>();
80
typeStringMap.put(Type.UNDEFINED, NbBundle.getBundle(Variable.class).getString("TYPE_undefined")); // NOI18N
81
typeStringMap.put(Type.LONG, NbBundle.getBundle(Variable.class).getString("TYPE_long")); // NOI18N
82
typeStringMap.put(Type.DOUBLE, NbBundle.getBundle(Variable.class).getString("TYPE_double")); // NOI18N
83
typeStringMap.put(Type.STRING, NbBundle.getBundle(Variable.class).getString("TYPE_string")); // NOI18N
84
typeStringMap.put(Type.ARRAY, NbBundle.getBundle(Variable.class).getString("TYPE_array")); // NOI18N
85
typeStringMap.put(Type.OBJECT, NbBundle.getBundle(Variable.class).getString("TYPE_object")); // NOI18N
86
typeStringMap.put(Type.BOOLEAN, NbBundle.getBundle(Variable.class).getString("TYPE_boolean")); // NOI18N
87
typeStringMap.put(Type.RESOURCE, NbBundle.getBundle(Variable.class).getString("TYPE_resource")); // NOI18N
88
typeStringMap.put(Type.REFERENCE, NbBundle.getBundle(Variable.class).getString("TYPE_reference")); // NOI18N
89
typeStringMap.put(Type.SOFT_REFERENCE, NbBundle.getBundle(Variable.class).getString("TYPE_soft_reference")); // NOI18N
92
// private DbgDebugger debugger; // Something like that, need to listen on state changes and needed to set values!
94
private String longName; // including possible parents
95
private Variable parent;
97
private String typeString;
98
private String value; // String value
99
private Variable ref; // XXX Reference for now?
100
private List<Variable> children;
101
private Set<PropertyChangeListener> listeners = new HashSet<PropertyChangeListener>();
103
/** Creates a new instance of Variable */
104
public Variable(Variable parent, String name, Type type, String typeString) {
105
this.parent = parent;
107
this.typeString = typeString;
110
if (typeString == null || typeString.length() == 0) {
111
this.typeString = typeStringMap.get(type);
114
if (parent != null) {
115
addPropertyChangeListener(parent);
119
public Variable(Variable parent, String name, Type type, String typeString, String value) {
120
this(parent, name, type, typeString);
125
public String getValue() {
129
public void setValue(String str) {
132
if (type == Type.STRING) {
133
v = longName + "=\"" + str + "\"";
136
v = longName + "=" + str;
139
List<Variable> ret = new ArrayList<Variable>();
140
// ret = debugger.eval(evalString);
142
for (Variable va : ret) {
143
if (va.longName.equals(longName)) {
146
fireValueChanged(this);
153
public void setChildren(List<Variable> cList) {
154
this.children = cList;
157
public VariableNode[] getChildren(int from, int to) {
158
Variable[] ret = new Variable[to - from];
160
for (int i = from; i < to; i++) {
161
ret[i - from] = children.get(i);
167
public boolean isLeaf() {
168
return children == null || children.size() == 0;
171
public int getChildrenCount() {
172
if (children == null) {
176
return children.size();
179
public String getTypeName() {
183
public void setRef(Variable ref) {
187
public void setName(String name) {
188
if (parent == null || parent.name == null || parent.name.length() == 0) {
190
this.longName = name;
193
switch (parent.type) {
195
this.name = "[" + name + "]";
196
this.longName = parent.longName + this.name;
200
this.longName = parent.longName + "->" + this.name;
204
this.longName = name;
209
public void setObject(Object bean) {
210
if (bean instanceof String) {
211
setValue((String)bean);
214
throw new IllegalArgumentException("" + bean);
218
public String toString() {
219
return longName + " = " + getTooltipValue();
223
public void addPropertyChangeListener(PropertyChangeListener l) {
224
synchronized (listeners) {
229
public void removePropertyChangeListener(PropertyChangeListener l) {
230
synchronized (listeners) {
235
public void propertyChange(PropertyChangeEvent e) {
236
if (children.contains(e.getSource())) {
237
fireValueChanged(e.getSource());
241
throw new UnsupportedOperationException("Not supported yet.");
244
private void fireValueChanged(Object value) {
245
PropertyChangeEvent evt = new PropertyChangeEvent(this, PROP_VALUE, null, value);
246
PropertyChangeListener[] ls;
248
synchronized (listeners) {
249
ls = listeners.toArray(new PropertyChangeListener[listeners.size()]);
252
for (int i = 0; i < ls.length; i++) {
253
ls[i].propertyChange(evt);
257
public String getName() {
261
public String getDisplayName() {
265
public String getShortDescription() {
269
public String getIconBase() {
271
return LOCAL_VARIABLE_ICON;
275
public boolean isReadOnly() {
276
return type != Type.BOOLEAN && type != Type.DOUBLE && type != Type.LONG && type != Type.STRING ;
279
public String getTooltipValue() {
282
if (children != null) {
283
boolean first = true;
287
for (Variable child : children) {
291
ret += child.toString();
297
else if (ref != null) {
298
ret += " -> " + ref.longName;
307
public void collectUpdates(Object source,
308
Collection<ModelEvent> events,
310
Variable newVar = (Variable)n;
311
boolean hasChanged = false;
313
assert name.equals(newVar.getName());
315
if (type != newVar.type) {
320
if (!typeString.equals(newVar.typeString)) {
321
typeString = newVar.typeString;
325
if (value == null && newVar.value != null ||
326
newVar.value != null && !newVar.value.equals(value)) {
327
value = newVar.value;
331
if (ref == null && newVar.ref != null ||
332
newVar.ref != null && !newVar.ref.longName.equals(ref.longName)) {
337
if (children == null && newVar.children != null) {
338
children = newVar.children;
341
else if (children != null) {
342
Iterator<Variable> it = children.iterator();
344
while (it.hasNext()) {
345
Variable child = it.next();
346
Variable newChild = newVar.findChild(child.name);
348
if (newChild != null) {
349
newVar.removeChild(newChild);
350
child.collectUpdates(source, events, newChild);
358
if (newVar.children != null && newVar.children.size() > 0) {
359
it = newVar.children.iterator();
361
while (it.hasNext()) {
362
Variable newChild = it.next();
372
events.add(new ModelEvent.NodeChanged(source, this));
376
private Variable findChild(String n) {
377
if (children == null || n == null || n.length() == 0) {
381
for (Variable child : children) {
382
if (child.name.equals(n)) {
390
private void removeChild(Variable child) {
391
if (child == null || children == null) {
395
children.remove(child);
397
// XXX Change events?
400
private void addChild(Variable child) {
405
if (children == null) {
406
children = new ArrayList<Variable>();
411
// XXX Change events?
414
public int getType() {
415
return TYPE_LOCAL_FIELD;