public ModelAdaptor getModelAdaptor(Class attributeType) {
    ModelAdaptor a = typeToAdaptorCache.get(attributeType);
    if (a != null) return a;

    // System.out.println("looking for adaptor for "+attributeType);
    // Else, we must find adaptor that fits;
    // find last fit (most specific)
    for (Class t : adaptors.keySet()) {
      // t works for attributeType if attributeType subclasses t or implements
      // System.out.println("checking "+t.getSimpleName()+" against "+attributeType);
      if (t.isAssignableFrom(attributeType)) {
        // System.out.println(t.getName()+" = "+attributeType.getName());
        a = adaptors.get(t);
      }
    }
    // System.out.println("adaptor for "+attributeType+" is "+a);
    typeToAdaptorCache.put(attributeType, a); // cache it for next time
    return a;
  }
  public AttributeRenderer getAttributeRenderer(Class attributeType) {
    if (renderers == null) return null;
    AttributeRenderer r = null;
    if (typeToRendererCache != null) {
      r = typeToRendererCache.get(attributeType);
      if (r != null) return r;
    }

    // Else look up, finding first first
    for (Class t : renderers.keySet()) {
      // t works for attributeType if attributeType subclasses t or implements
      if (t.isAssignableFrom(attributeType)) {
        r = renderers.get(t);
        if (typeToRendererCache == null) {
          typeToRendererCache =
              Collections.synchronizedMap(new LinkedHashMap<Class, AttributeRenderer>());
        }
        typeToRendererCache.put(attributeType, r);
        return r;
      }
    }
    return null;
  }