Java: Swing: Structure: Mappings
This isn't too complete. Also, the Swing-specific part is almost completely missing.
A mapping is a one-argument function. It maps an object (called key or item here) to its value.
The fundamental feature of a Mapping is thus:
Object value(Object item);
A mapping may be defined only a specific set of items, for example those of a certain type or on everything except null. In a specific case, this may be clear from the context or ensured by having a different signature for the value method, but in general one needs a method to test this before calling value():
boolean isValid(Object item);
(The set of items may not be easily enumerable, so it cannot always be offered as a Set data structure).
A mapping may yield only a specific set of items. It may offer a query whether a certain value occurs at all.
In the following "equal" means determined by the "equals" method. "same" means the same reference (compared by ==).
It is reasonable to assume that mappings will map equal items to equal values (everything else will cause confusion), and map (unless it or theitem is changed) the same item repeatedly at least to an equal value (maybe not the same), i.e. unless changes happen, it is like a function the mathematical sense. This is not required: it also make sense not to require that equal (but not the same) items map maybe to different values. But if you then also don't require that it repeated values are the same (and not only equal) for the same item, already two notions of equality are involved.
Often, the keys (as suggested by the name) will be immutable.
Two mappings are considered equal if they:
accept the same items.
map the same item to (at least) an equal value.
Two degrees of equality:
transient equality ("at the moment"), but not necessarily if items or mappings are changed
permanent equality: no matter how things are changed, the mappings will remain equal (if the mapping is mutable, it will then only compare equal to itself).
Which to use for equals?
Often even single methods are mappings, with isValid() always true (maybe except 'null') or clear from the context.
Mappings need not be injective, so there need not be an inverse mapping. If there is one, it could be offered.
If not, the Mapping may at least offer a method to access all keys that map to certain value, or one representative.
Collection values(Collection items);
boolean allValid(Collection items);
or even:
boolean anyValid(Collection items);
Collection validItems(Collection items);
void setValid(Object item, boolean valid);
void setValue(Object item, Object value);
with meta-validity methods, for example some items may not be made (in-)valid or some values are not allowed.
maybe also with more convenience methods.
Method | Map | (Mutable)AttributeSet | InputMap | ActionMap | Keymap |
|---|---|---|---|---|---|
value | get | getAttribute | get | get | getAction |
valid | none (get even may throw exception) | all except null are valid (or only HTML.Attribute and String after all, LOL) | all KeyStrokes except null are valid | all (except null???) are valid | all KeyStrokes (except null???) are valid |
isValue | containsValue (not for null) | ||||
transientEquals | equals | (isEqual?) | |||
permanentEquals | equals (if both Maps are known to be immutable) | ||||
setValid | |||||
setValue | addAttribute (null values???) | put (without null values) | put (without null values) | addActionForKeyStroke | |
(valid) items | |||||
(occuring) value | |||||
items(value) | getKeyStrokesForAction | ||||
pairs |
Ad Map:
keySet() returns all keys that don't map to null and those that map explicitly to null. It doesn't contain those items that are valid but map implicitly to null.
values() is a multiset and doesn't contain 'null' (at least not the right number of times) although "most" keys will map to null.
entries() contains only the explicit entries.
Table explicitly contain pairs (item, value), much like a table written on paper. Unlike mapping, they have a notion of whether a item is contained ornot. They can enumerate the items they contain.
They may allow (at least a subset of) items that they don't contain, but map these to a special value (most often, 'null'), i.e. can be regarded as a mapping as well.
Typically, tables are finite (unless there is some law to create the pairs on demand).
java.util.Map is more like a table, since many, wide-going ways of enumeration are provided.
A mapping may have a notion of 'no value' for an item. Often 'null' is given as value for that purpose, but that way is quite limiting.
One may build a ordered tree of mappings, each delegating to its children if it doesn't have a value itself until one is found.
At least four different (though very similar) resolving Mappings are used in Swing, see above. All only allow a linked list of resolvers, not a tree (the additional effort would have been minimal). One implementation (AbstractDocument.AbstractElement) doesn't handle resolving correctly.
Problems with 'null' as marker:
No difference between explicit 'null' value and 'no value', so 'null' isn't a normal value anymore.
Major problems in resolving with that: 'null' will be interpreted as 'no value' and the next resolver will be used.
(C) 2001-2009 Christian Kaufhold (swing@chka.de)