
I was 
recently asked whether 
Metawidget could inspect, load and save business objects based not on a JavaBean (or GroovyBean, ScalaBean etc) but on a 
Map of names and attributes. The answer is 
yes!
I've 
sort of covered this before but last time I only blogged about 
inspecting the 
Map, not loading and saving the values.We already have a GWT version of this in the Metawidget distribution (see the 
GWT Client Side example) but now 
I've put together a Swing project you can download too. It's very similar to the 
previous blog but adds a 
MapWidgetProcessor that loads and saves values back into a 
Map.
An important point to grok is that the 'Map of properties' (used by 
MapInspector) is different to the 'Map of values' (used by 
MapWidgetProcessor). This is in the same way that a 'Class' is different to an 'Object': one defines the type, one defines the instance values. So in the code you will see:
metawidget.setToInspect( values );
metawidget.setPath( "person" );
We call both 
setToInspect (to tell Metawidget where the values are coming from) 
and setPath (to tell Metawidget what the type is). Normally when using a JavaBean (or GroovyBean, ScalaBean etc) you don't need to do this, because Metawidget will internally call...
metawidget.setPath( metawidget.getToInspect().getClass() )
...on your behalf. But if you want to start using 
Maps, these two concepts need to be explictly separate.
Take a 
look for yourself here. Or, for the impatient, here's the most important piece of code:
/**
 * MapWidgetProcessor uses the Metawidget's <code>toInspect</code> to retrieve/store values.
 */
public class MapWidgetProcessor
   implements AdvancedWidgetProcessor<JComponent, SwingMetawidget> {
   //
   // Public methods
   //
   @Override
   public void onStartBuild( SwingMetawidget metawidget ) {
      getWrittenComponents( metawidget ).clear();
   }
   /**
    * Retrieve the values from the Map and put them in the Components.
    */
   @Override
   public JComponent processWidget( JComponent component, String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {
      String attributeName = attributes.get( NAME );
      getWrittenComponents( metawidget ).put( attributeName, component );
      // Fetch the value...
      Map<String, Object> toInspect = metawidget.getToInspect();
      Object value = toInspect.get( attributeName );
      if ( value == null ) {
         return component;
      }
      // ...and apply it to the component. For simplicity, we won't worry about converters
      String componentProperty = metawidget.getValueProperty( component );
      ClassUtils.setProperty( component, componentProperty, value );
      return component;
   }
   @Override
   public void onEndBuild( SwingMetawidget metawidget ) {
      // Do nothing
   }
   /**
    * Store the values from the Components back into the Map.
    */
   public void save( SwingMetawidget metawidget ) {
      Map<String, Object> toInspect = metawidget.getToInspect();
      for ( Map.Entry<String,JComponent> entry : getWrittenComponents( metawidget ).entrySet() ) {
         JComponent component = entry.getValue();
         String componentProperty = metawidget.getValueProperty( component );
         Object value = ClassUtils.getProperty( component, componentProperty );
         toInspect.put( entry.getKey(), value );
      }
   }
   //
   // Private methods
   //
   /**
    * During load-time we keep track of all the components. At save-time we write them all back
    * again.
    */
   private Map<String,JComponent> getWrittenComponents( SwingMetawidget metawidget ) {
      @SuppressWarnings( "unchecked" )
      Map<String,JComponent> writtenComponents = (Map<String,JComponent>) metawidget.getClientProperty( MapWidgetProcessor.class );
      if ( writtenComponents == null ) {
         writtenComponents = CollectionUtils.newHashMap();
         metawidget.putClientProperty( MapWidgetProcessor.class, writtenComponents );
      }
      return writtenComponents;
   }
}