Merry Christmas to the server CPUs. It occurred to me that we could
accomplish our "previous value" support in the distributed object system without using reflection and could also avoid using reflection in the case where we have already applied the event on the server (which is generally the case on the server). Rather than hacking up the gendobj script, I took this opportunity also to rewrite the DObject generation script as an Ant task and in doing so, implemented another recent idea which is that we can just augment the FooObject.java file instead of having a separate .dobj and .java file. You'd think it was spring there's so much cleaning going on. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3284 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: AttributeChangedEvent.java,v 1.16 2004/08/27 02:20:20 mdb Exp $
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
@@ -32,26 +32,6 @@ import com.samskivert.util.StringUtil;
|
||||
*/
|
||||
public class AttributeChangedEvent extends NamedEvent
|
||||
{
|
||||
/**
|
||||
* Constructs a new attribute changed event on the specified target
|
||||
* object with the supplied attribute name and value.
|
||||
*
|
||||
* @param targetOid the object id of the object whose attribute has
|
||||
* changed.
|
||||
* @param name the name of the attribute (data member) that has
|
||||
* changed.
|
||||
* @param value the new value of the attribute (in the case of
|
||||
* primitive types, the reflection-defined object-alternative is
|
||||
* used).
|
||||
*/
|
||||
public AttributeChangedEvent (int targetOid, String name,
|
||||
Object value, Object oldValue)
|
||||
{
|
||||
super(targetOid, name);
|
||||
_value = value;
|
||||
_oldValue = oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a blank instance of this event in preparation for
|
||||
* unserialization from the network.
|
||||
@@ -128,15 +108,41 @@ public class AttributeChangedEvent extends NamedEvent
|
||||
public boolean applyToObject (DObject target)
|
||||
throws ObjectAccessException
|
||||
{
|
||||
// grab the previous value (if we're on the client)
|
||||
// if we have no old value, that means we're not running on the
|
||||
// master server and we have not already applied this attribute
|
||||
// change to the object, so we must grab the previous value and
|
||||
// actually apply the attribute change
|
||||
if (_oldValue == UNSET_OLD_VALUE) {
|
||||
_oldValue = target.getAttribute(_name);
|
||||
// pass the new value on to the object (this uses reflection
|
||||
// and is slow)
|
||||
target.setAttribute(_name, _value);
|
||||
}
|
||||
// pass the new value on to the object
|
||||
target.setAttribute(_name, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new attribute changed event on the specified target
|
||||
* object with the supplied attribute name and value. <em>Do not
|
||||
* construct these objects by hand.</em> Use {@link
|
||||
* DObject#changeAttribute} instead.
|
||||
*
|
||||
* @param targetOid the object id of the object whose attribute has
|
||||
* changed.
|
||||
* @param name the name of the attribute (data member) that has
|
||||
* changed.
|
||||
* @param value the new value of the attribute (in the case of
|
||||
* primitive types, the reflection-defined object-alternative is
|
||||
* used).
|
||||
*/
|
||||
protected AttributeChangedEvent (
|
||||
int targetOid, String name, Object value, Object oldValue)
|
||||
{
|
||||
super(targetOid, name);
|
||||
_value = value;
|
||||
_oldValue = oldValue;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void notifyListener (Object listener)
|
||||
{
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
//
|
||||
// $Id: AttributesChangedEvent.java,v 1.12 2004/08/27 02:20:20 mdb Exp $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.presents.dobj;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* An attribute<em>s</em> changed event is dispatched when multiple
|
||||
* attributes of a distributed object have been changed in a single
|
||||
* transaction.
|
||||
*
|
||||
* @see DObjectManager#postEvent
|
||||
*/
|
||||
public class AttributesChangedEvent extends DEvent
|
||||
{
|
||||
/**
|
||||
* Constructs a new attribute changed event on the specified target
|
||||
* object with the supplied attribute name and value.
|
||||
*
|
||||
* @param targetOid the object id of the object whose attribute has
|
||||
* changed.
|
||||
* @param count the number of attributes that have changed (the length
|
||||
* of the <code>names</code> and <code>values</code> arrays need not
|
||||
* be exactly equal to the number of attributes changed, there can be
|
||||
* extra space at the end).
|
||||
* @param names the names of the attributes (data members) that have
|
||||
* changed.
|
||||
* @param values the new values of the attributes (in the case of
|
||||
* primitive types, the reflection-defined object-alternative is
|
||||
* used).
|
||||
*/
|
||||
public AttributesChangedEvent (int targetOid, int count,
|
||||
String[] names, Object[] values)
|
||||
{
|
||||
super(targetOid);
|
||||
_count = count;
|
||||
_names = names;
|
||||
_values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a blank instance of this event in preparation for
|
||||
* unserialization from the network.
|
||||
*/
|
||||
public AttributesChangedEvent ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of attributes that have changed.
|
||||
*/
|
||||
public int getCount ()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the index<em>th</em> attribute that has
|
||||
* changed. This value is not range checked, so be sure it is between
|
||||
* <code>0</code> and <code>getCount()-1</code>. You may not receive
|
||||
* an <code>ArrayIndexOutOfBounds</code> exception if you exceed
|
||||
* <code>getCount()</code> but rather get a null name.
|
||||
*/
|
||||
public String getName (int index)
|
||||
{
|
||||
return _names[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new value of the index<em>th</em> attribute. This value
|
||||
* is not range checked, so be sure it is between <code>0</code> and
|
||||
* <code>getCount()-1</code>. You may not receive an
|
||||
* <code>ArrayIndexOutOfBounds</code> exception if you exceed
|
||||
* <code>getCount()</code> but rather get a null value.
|
||||
*/
|
||||
public Object getValue (int index)
|
||||
{
|
||||
return _values[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new value of the index<em>th</em> attribute as a
|
||||
* short. This will fail if the attribute in question is not a short.
|
||||
* The <code>index</code> parameter is not range checked, so be sure
|
||||
* it is between <code>0</code> and <code>getCount()-1</code>. You may
|
||||
* not receive an <code>ArrayIndexOutOfBounds</code> exception if you
|
||||
* exceed <code>getCount()</code> but rather get a
|
||||
* <code>NullPointerException</code>.
|
||||
*/
|
||||
public short getShortValue (int index)
|
||||
{
|
||||
return ((Short)_values[index]).shortValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new value of the index<em>th</em> attribute as an
|
||||
* int. This will fail if the attribute in question is not an int.
|
||||
* The <code>index</code> parameter is not range checked, so be sure
|
||||
* it is between <code>0</code> and <code>getCount()-1</code>. You may
|
||||
* not receive an <code>ArrayIndexOutOfBounds</code> exception if you
|
||||
* exceed <code>getCount()</code> but rather get a
|
||||
* <code>NullPointerException</code>.
|
||||
*/
|
||||
public int getIntValue (int index)
|
||||
{
|
||||
return ((Integer)_values[index]).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new value of the index<em>th</em> attribute as a
|
||||
* long. This will fail if the attribute in question is not a long.
|
||||
* The <code>index</code> parameter is not range checked, so be sure
|
||||
* it is between <code>0</code> and <code>getCount()-1</code>. You may
|
||||
* not receive an <code>ArrayIndexOutOfBounds</code> exception if you
|
||||
* exceed <code>getCount()</code> but rather get a
|
||||
* <code>NullPointerException</code>.
|
||||
*/
|
||||
public long getLongValue (int index)
|
||||
{
|
||||
return ((Long)_values[index]).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new value of the index<em>th</em> attribute as a
|
||||
* float. This will fail if the attribute in question is not a float.
|
||||
* The <code>index</code> parameter is not range checked, so be sure
|
||||
* it is between <code>0</code> and <code>getCount()-1</code>. You may
|
||||
* not receive an <code>ArrayIndexOutOfBounds</code> exception if you
|
||||
* exceed <code>getCount()</code> but rather get a
|
||||
* <code>NullPointerException</code>.
|
||||
*/
|
||||
public float getFloatValue (int index)
|
||||
{
|
||||
return ((Float)_values[index]).floatValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new value of the index<em>th</em> attribute as a
|
||||
* double. This will fail if the attribute in question is not a
|
||||
* double. The <code>index</code> parameter is not range checked, so
|
||||
* be sure it is between <code>0</code> and <code>getCount()-1</code>.
|
||||
* You may not receive an <code>ArrayIndexOutOfBounds</code> exception
|
||||
* if you exceed <code>getCount()</code> but rather get a
|
||||
* <code>NullPointerException</code>.
|
||||
*/
|
||||
public double getDoubleValue (int index)
|
||||
{
|
||||
return ((Double)_values[index]).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this attribute change to the object.
|
||||
*/
|
||||
public boolean applyToObject (DObject target)
|
||||
throws ObjectAccessException
|
||||
{
|
||||
// pass the new values on to the object
|
||||
for (int i = 0; i < _count; i++) {
|
||||
target.setAttribute(_names[i], _values[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
buf.append("CHANGES:");
|
||||
super.toString(buf);
|
||||
buf.append(", names=");
|
||||
StringUtil.toString(buf, _names);
|
||||
buf.append(", values=");
|
||||
StringUtil.toString(buf, _values);
|
||||
}
|
||||
|
||||
protected int _count;
|
||||
protected String[] _names;
|
||||
protected Object[] _values;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: DObject.java,v 1.79 2004/10/23 17:36:32 mdb Exp $
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
@@ -23,11 +23,14 @@ package com.threerings.presents.dobj;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.samskivert.util.ListUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
@@ -292,8 +295,13 @@ public class DObject extends TrackedObject
|
||||
*/
|
||||
public void addToSet (String setName, DSet.Entry entry)
|
||||
{
|
||||
getSet(setName); // validate the set
|
||||
requestEntryAdd(setName, entry);
|
||||
String mname = "addTo" + StringUtils.capitalize(setName);
|
||||
try {
|
||||
Method m = getClass().getMethod(mname, ENTRY_CLASS_ARGS);
|
||||
m.invoke(this, new Object[] { entry });
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("No such set: " + setName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,8 +309,13 @@ public class DObject extends TrackedObject
|
||||
*/
|
||||
public void updateSet (String setName, DSet.Entry entry)
|
||||
{
|
||||
getSet(setName); // validate the set
|
||||
requestEntryUpdate(setName, entry);
|
||||
String mname = "update" + StringUtils.capitalize(setName);
|
||||
try {
|
||||
Method m = getClass().getMethod(mname, ENTRY_CLASS_ARGS);
|
||||
m.invoke(this, new Object[] { entry });
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("No such set: " + setName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,8 +323,13 @@ public class DObject extends TrackedObject
|
||||
*/
|
||||
public void removeFromSet (String setName, Comparable key)
|
||||
{
|
||||
getSet(setName); // validate the set
|
||||
requestEntryRemove(setName, key);
|
||||
String mname = "removeFrom" + StringUtils.capitalize(setName);
|
||||
try {
|
||||
Method m = getClass().getMethod(mname, KEY_CLASS_ARGS);
|
||||
m.invoke(this, new Object[] { key });
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("No such set: " + setName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -502,6 +520,28 @@ public class DObject extends TrackedObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified attribute be changed to the specified
|
||||
* value. Normally the generated setter methods should be used but in
|
||||
* rare cases a caller may wish to update distributed fields in a
|
||||
* generic manner.
|
||||
*/
|
||||
public void changeAttribute (String name, Object value)
|
||||
throws ObjectAccessException
|
||||
{
|
||||
try {
|
||||
Field f = getField(name);
|
||||
requestAttributeChange(name, value, f.get(this));
|
||||
f.set(this, value);
|
||||
|
||||
} catch (Exception e) {
|
||||
String errmsg = "changeAttribute() failure [name=" + name +
|
||||
", value=" + value +
|
||||
", vclass=" + value.getClass().getName() + "].";
|
||||
throw new ObjectAccessException(errmsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the named attribute to the specified value. This is only used
|
||||
* by the internals of the event dispatch mechanism and should not be
|
||||
@@ -512,39 +552,10 @@ public class DObject extends TrackedObject
|
||||
throws ObjectAccessException
|
||||
{
|
||||
try {
|
||||
// for values that contain other values (arrays and DSets), we
|
||||
// need to clone them before putting them in the object
|
||||
// because otherwise a subsequent event might come along and
|
||||
// modify these values before the networking thread has had a
|
||||
// chance to propagate this event to the clients
|
||||
|
||||
// i wish i could just call value.clone() but Object declares
|
||||
// clone() to be inaccessible, so we must cast the values to
|
||||
// their actual types to gain access to the widened clone()
|
||||
// methods
|
||||
if (value instanceof DSet) {
|
||||
value = ((DSet)value).clone();
|
||||
} else if (value instanceof int[]) {
|
||||
value = ((int[])value).clone();
|
||||
} else if (value instanceof String[]) {
|
||||
value = ((String[])value).clone();
|
||||
} else if (value instanceof byte[]) {
|
||||
value = ((byte[])value).clone();
|
||||
} else if (value instanceof long[]) {
|
||||
value = ((long[])value).clone();
|
||||
} else if (value instanceof float[]) {
|
||||
value = ((float[])value).clone();
|
||||
} else if (value instanceof short[]) {
|
||||
value = ((short[])value).clone();
|
||||
} else if (value instanceof double[]) {
|
||||
value = ((double[])value).clone();
|
||||
}
|
||||
|
||||
// now actually set the value
|
||||
getField(name).set(this, value);
|
||||
|
||||
} catch (Exception e) {
|
||||
String errmsg = "Attribute setting failure [name=" + name +
|
||||
String errmsg = "setAttribute() failure [name=" + name +
|
||||
", value=" + value +
|
||||
", vclass=" + value.getClass().getName() + "].";
|
||||
throw new ObjectAccessException(errmsg, e);
|
||||
@@ -564,7 +575,7 @@ public class DObject extends TrackedObject
|
||||
return getField(name).get(this);
|
||||
|
||||
} catch (Exception e) {
|
||||
String errmsg = "Attribute getting failure [name=" + name + "].";
|
||||
String errmsg = "getAttribute() failure [name=" + name + "].";
|
||||
throw new ObjectAccessException(errmsg, e);
|
||||
}
|
||||
}
|
||||
@@ -812,36 +823,23 @@ public class DObject extends TrackedObject
|
||||
* Called by derived instances when an attribute setter method was
|
||||
* called.
|
||||
*/
|
||||
protected void requestAttributeChange (String name, Object value)
|
||||
protected void requestAttributeChange (
|
||||
String name, Object value, Object oldValue)
|
||||
{
|
||||
try {
|
||||
// dispatch an attribute changed event
|
||||
postEvent(new AttributeChangedEvent(
|
||||
_oid, name, value, getAttribute(name)));
|
||||
|
||||
} catch (ObjectAccessException oae) {
|
||||
Log.warning("Unable to request attributeChange [name=" + name +
|
||||
", value=" + value + ", error=" + oae + "].");
|
||||
}
|
||||
// dispatch an attribute changed event
|
||||
postEvent(new AttributeChangedEvent(_oid, name, value, oldValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by derived instances when an element updater method was
|
||||
* called.
|
||||
*/
|
||||
protected void requestElementUpdate (String name, Object value, int index)
|
||||
protected void requestElementUpdate (
|
||||
String name, int index, Object value, Object oldValue)
|
||||
{
|
||||
try {
|
||||
// dispatch an attribute changed event
|
||||
Object oldValue = Array.get(getAttribute(name), index);
|
||||
postEvent(new ElementUpdatedEvent(
|
||||
_oid, name, value, oldValue, index));
|
||||
|
||||
} catch (ObjectAccessException oae) {
|
||||
Log.warning("Unable to request elementUpdate [name=" + name +
|
||||
", value=" + value + ", index=" + index +
|
||||
", error=" + oae + "].");
|
||||
}
|
||||
// dispatch an attribute changed event
|
||||
postEvent(new ElementUpdatedEvent(
|
||||
_oid, name, value, oldValue, index));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -865,72 +863,48 @@ public class DObject extends TrackedObject
|
||||
/**
|
||||
* Calls by derived instances when a set adder method was called.
|
||||
*/
|
||||
protected void requestEntryAdd (String name, DSet.Entry entry)
|
||||
protected void requestEntryAdd (String name, DSet set, DSet.Entry entry)
|
||||
{
|
||||
try {
|
||||
DSet set = (DSet)getAttribute(name);
|
||||
// if we're on the authoritative server, we update the set
|
||||
// immediately
|
||||
boolean alreadyApplied = false;
|
||||
if (_omgr != null && _omgr.isManager(this)) {
|
||||
if (!set.add(entry)) {
|
||||
Thread.dumpStack();
|
||||
}
|
||||
alreadyApplied = true;
|
||||
// if we're on the authoritative server, we update the set immediately
|
||||
boolean alreadyApplied = false;
|
||||
if (_omgr != null && _omgr.isManager(this)) {
|
||||
if (!set.add(entry)) {
|
||||
Thread.dumpStack();
|
||||
}
|
||||
// dispatch an entry added event
|
||||
postEvent(new EntryAddedEvent(_oid, name, entry, alreadyApplied));
|
||||
|
||||
} catch (ObjectAccessException oae) {
|
||||
Log.warning("Unable to request entryAdd [name=" + name +
|
||||
", entry=" + entry + ", error=" + oae + "].");
|
||||
alreadyApplied = true;
|
||||
}
|
||||
// dispatch an entry added event
|
||||
postEvent(new EntryAddedEvent(_oid, name, entry, alreadyApplied));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls by derived instances when a set remover method was called.
|
||||
*/
|
||||
protected void requestEntryRemove (String name, Comparable key)
|
||||
protected void requestEntryRemove (String name, DSet set, Comparable key)
|
||||
{
|
||||
try {
|
||||
DSet set = (DSet)getAttribute(name);
|
||||
// if we're on the authoritative server, we update the set
|
||||
// immediately
|
||||
DSet.Entry oldEntry = null;
|
||||
if (_omgr != null && _omgr.isManager(this)) {
|
||||
oldEntry = set.get(key);
|
||||
set.removeKey(key);
|
||||
}
|
||||
// dispatch an entry removed event
|
||||
postEvent(new EntryRemovedEvent(_oid, name, key, oldEntry));
|
||||
|
||||
} catch (ObjectAccessException oae) {
|
||||
Log.warning("Unable to request entryRemove [name=" + name +
|
||||
", key=" + key + ", error=" + oae + "].");
|
||||
// if we're on the authoritative server, we update the set immediately
|
||||
DSet.Entry oldEntry = null;
|
||||
if (_omgr != null && _omgr.isManager(this)) {
|
||||
oldEntry = set.get(key);
|
||||
set.removeKey(key);
|
||||
}
|
||||
// dispatch an entry removed event
|
||||
postEvent(new EntryRemovedEvent(_oid, name, key, oldEntry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls by derived instances when a set updater method was called.
|
||||
*/
|
||||
protected void requestEntryUpdate (String name, DSet.Entry entry)
|
||||
protected void requestEntryUpdate (String name, DSet set, DSet.Entry entry)
|
||||
{
|
||||
try {
|
||||
DSet set = (DSet)getAttribute(name);
|
||||
// if we're on the authoritative server, we update the set
|
||||
// immediately
|
||||
DSet.Entry oldEntry = null;
|
||||
if (_omgr != null && _omgr.isManager(this)) {
|
||||
oldEntry = set.get(entry.getKey());
|
||||
set.update(entry);
|
||||
}
|
||||
// dispatch an entry updated event
|
||||
postEvent(new EntryUpdatedEvent(_oid, name, entry, oldEntry));
|
||||
|
||||
} catch (ObjectAccessException oae) {
|
||||
Log.warning("Unable to request entryUpdate [name=" + name +
|
||||
", entry=" + entry + ", error=" + oae + "].");
|
||||
// if we're on the authoritative server, we update the set immediately
|
||||
DSet.Entry oldEntry = null;
|
||||
if (_omgr != null && _omgr.isManager(this)) {
|
||||
oldEntry = set.get(entry.getKey());
|
||||
set.update(entry);
|
||||
}
|
||||
// dispatch an entry updated event
|
||||
postEvent(new EntryUpdatedEvent(_oid, name, entry, oldEntry));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1004,4 +978,12 @@ public class DObject extends TrackedObject
|
||||
return ((Field)o1).getName().compareTo(((Field)o2).getName());
|
||||
}
|
||||
};
|
||||
|
||||
/** Used when calling set methods dynamically. */
|
||||
protected static final Class[] ENTRY_CLASS_ARGS =
|
||||
new Class[] { DSet.Entry.class };
|
||||
|
||||
/** Used when calling set methods dynamically. */
|
||||
protected static final Class[] KEY_CLASS_ARGS =
|
||||
new Class[] { Comparable.class };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user