Hi Simon,
I was planning to use ArrayMap (new ArrayMap<String, String>) and
not the static methods, so I should be ok. I understood most of your
email. It's a clear email, and thank you for taking the time to write
it. I don't have a strong understanding of generics, so I'll have to
reread it while cross-referencing the generics book. :)
I'm changing the Style API to Map<String, String> getProperties()
instead of Iterator<Object> getProperyNames().
Also, I doubt we need removeProperty. The Style classes are for the
most part used in code that should be deleted (the Image generation
code).
I'm resurrecting some of the Style apis for two tasks:
emailable page where we need to write the css inline and for renderers
to be able to get the css properties given a css selector (we have
custom component developers that use Flash and need this).
Neither of these use cases need removeProperty.
(I'll send out an email soon regarding my api changes once I have it
firmed up)
Thanks!
Jeanne
Simon Lessard wrote, On 3/20/2009 8:46 AM PT:
Hi Jeanne,
Ok I checked the code back (and the comments) and here are the issues
and the meaning of the comment.
We have the following ArrayMap class that is used for different
purpose, most of the time as <String, String> or <String,
Object>
public class
ArrayMap<K, V> extends AbstractMap<K, V> implements
Cloneable
The implementation's strategy is to store everything in a single array
of length = 2 * size() with the format:
array[keyIndex] =
key;
array[keyIndex+1] =
value;
Therefore, the container array HAS to be able to contain both K and V
and since those two classes have nothing in common but Object, then the
container array MUST be Object[]. Now all those type handling are
hidden to end users who use ArrayMap so there's no big deal there.
However, BaseStyle don't use the ArrayMap directly, but rather its
various static method and that's the real problem. So ArrayMap expose
its internal behavior through the following static methods used by
BaseStyle:
public static
Object get(Object[] array, Object key)
public static
Iterator<Object> getKeys(Object[] array)
public static
Object[] put(Object[] array, Object key, Object value)
public static
Object[] remove(Object[] array, Object key)
The problem is with the getPropertyNames method that should return
Iterator<String>. However, it uses the getKeys(Object[]) which
returns an Iterator<Object> and it's not type-safe to cast that
implicitly to an Iterator<String> (although it would work with
explicit and a @SuppressWarnings("unchecked")). Or, we could enable
generics on the getKeys method:
public static
<T> Iterator<T> getKeys(T[] array)
However now you iether have to use a String[] in BaseStyle, or cast the
Object[] to String[] in the method call. The latter works, the former
is more complicated. If you change the Object[] to String[] at class
member level then setProperty method will start failing because of the
line:
_properties =
ArrayMap.remove(_properties, name);
since the remove method returns an Object[] that is actually
instanciated by the ArrayMap class, casting it to String[] wouldn't be
good to do at all since it's really just a real Object[]. Now why not
genericify remove as well? Well let try
public static
<T> T[] remove(T[] array, T key)
It seems good, but it's not as that method calls the genericified method
public static
<T> T[] remove(T[] array, T key, boolean reallocate)
And since that method does some reallocation, everything crumble
because new T[] is never a valid line in Java because generics came so
late and backward compatibility is so saint that generics are just an
illusion and are utterly crappily integrated with Java, hence the
dreaded type erasure. However, arrays does not suffer that shortcoming
so they're both covariant and typesafe (ArrayStoreException) so both
does NOT cohabit gracefully and you cannot create a generic array at
runtime because it has to be typesafe while at runtime generics are
not. Because of that, the remove method cannot be generic enabled, so
BaseStyle cannot use a String[]. That leaves you with two options, use
explicit cast or use an ArrayMap attribute rather than an array and
ArrayMap's static methods.
Do I make any sense?
~ Simon
On Thu, Mar 19, 2009 at 8:07 PM, Jeanne
Waldman <[email protected]>
wrote:
Hi Simon,
I have a question about your comment in the Style.java code.
/**
* Returns the names of the properties defined by this style.
*/
// -= Simon Lessard =-
// FIXME: This should be changed to <String> once the issues
// with ArrayMap are fixed. ATM (2006-08-04) ArrayMap
// have huge problem working with anything but Object
public Iterator<Object> getPropertyNames();
/**
* Returns the value of the property with the specified name.
*
* @param name The property name for the property to return
*/
public String getProperty(String name);
What issues about ArrayMap are you talking about?
I'm working on a task to make the Style object a public API,
and I was going to change the api to:
public Map<String, String> getProperties()
I am concerned about your comment because I don't understand it.
I see you have a comment in the ArrayMap code as well, and I see that
Adam added a comment in
response to your comment. If I use Map<String, String>
getProperties and the implementation
is using an ArrayMap do you think this won't work?
Thanks,
Jeanne
|