1 2 Previous Next 16 Replies Latest reply on Mar 6, 2008 4:03 PM by starksm64

    Using a CompositeMetaType for a Map with String keys?

    starksm64

      Right now MetaTypeFactory.resolve(Map[String,?].class) returns a TableMetaType. It seems more natural for this to be a CompositeMetaType that does not restrict the item names when the Map has String keys, for example:

       MutableCompositeMetaType expected = new MutableCompositeMetaType(HashMap.class.getName(), "HashMap<String,String>");
       expected.addItem("key1", "key1", SimpleMetaType.STRING);
       expected.addItem("key2", "key2", SimpleMetaType.STRING);
       expected.addItem("key3", "key3", SimpleMetaType.STRING);
       expected.freeze();
      
       String[] itemNames = {"key1", "key2", "key3"};
       MetaValue[] itemValues = {SimpleValueSupport.wrap("value1"), SimpleValueSupport.wrap("value3"), SimpleValueSupport.wrap("value3")};
       CompositeValueSupport mapValue = new CompositeValueSupport(expected, itemNames, itemValues);
       MetaValue value1 = mapValue.get("key1");
      


      A new MapValueSupport could implement this type of CompositeValue. The TableMetaType/TableValue seem very awkward for this type of map. Is there a reason not to support this and require all Maps to be TableMetaType/TableValue?


        • 1. Re: Using a CompositeMetaType for a Map with String keys?
          alesj

          I was just following Adrian's previous work.
          Previous as in MC and AS5 trunk on mbeans module.

          • 2. Re: Using a CompositeMetaType for a Map with String keys?

            Sure, just blame Adrian, that always works. ;)

            I think a TableMetaType/TableValue would be overkill for such a simple Map. I think the Table type/value is more for when you have rows of "records" where each row can be a totally different set of "columns". Now where that would come into play and be used is beyond me.

            • 3. Re: Using a CompositeMetaType for a Map with String keys?
              alesj

               

              "bytor99999" wrote:
              Sure, just blame Adrian, that always works. ;)

              Yeah, the easy way out. :-)

              But I could also blame it on you guys, for 'sleeping' for so long. ;-)

              "bytor99999" wrote:

              I think a TableMetaType/TableValue would be overkill for such a simple Map. I think the Table type/value is more for when you have rows of "records" where each row can be a totally different set of "columns". Now where that would come into play and be used is beyond me.


              OK, I have no problem supporting something simpler, e.g. Scott's MapValueSupport .
              But let the initial implementor speak.


              • 4. Re: Using a CompositeMetaType for a Map with String keys?
                starksm64

                Our metatype/values initially mirrored the jmx opentype stuff, so that is where the CompositeMetaType, TableMetaType come from. A map of string keys with metavalues is no different than a javabean of property names to values, so that type of map should have a CompositeMetaType representation. I'm testing a MapCompositeValueSupport impl as part of the ds property fixing.

                • 5. Re: Using a CompositeMetaType for a Map with String keys?

                   

                  "scott.stark@jboss.org" wrote:
                  Our metatype/values initially mirrored the jmx opentype stuff, so that is where the CompositeMetaType, TableMetaType come from


                  Correct but OpenMBeans or MetaTypes don't mandate that you should
                  use Tables to represent maps.

                  This is a property of the MXBean or MetaTypeFactory default mappings respectively.


                  A map of string keys with metavalues is no different than a javabean of property names to values, so that type of map should have a CompositeMetaType representation. I'm testing a MapCompositeValueSupport impl as part of the ds property fixing.


                  If you want to map (pun not intended :-) simple maps
                  e.g. String->Object to a composite data that is fine with me.

                  NOTE: Unless this is made configurable somehow (annotation?) then this
                  would also apply to all java.util.Properties.

                  The thing about things like java.util.Properties is that the number of possible key values
                  is potentially infiinite. ;-)

                  e.g.1 - jndi environment propreties (keys depend upon what the initial context supports)

                  e.g.2 - for a jca admin object the possible keys are determined by the
                  javabean properties on the implementation class (not shown in this config)
                   <mbean code="org.jboss.resource.deployment.AdminObject"
                   name="jca.test:name=TestInterface">
                   <attribute name="JNDIName">test/jca/TestInterface</attribute>
                   <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='testadminobject.rar'</depends>
                   <attribute name="Type">org.jboss.test.jca.adminobject.TestInterface</attribute>
                   <attribute name="Properties">
                   StringProperty=StringValue
                   IntegerProperty=123
                   </attribute>
                   </mbean>
                  


                  • 6. Re: Using a CompositeMetaType for a Map with String keys?
                    starksm64
                    • 7. Re: Using a CompositeMetaType for a Map with String keys?
                      starksm64

                      I update the DefaultMetaTypeFactory.generate(TypeInfo typeInfo) handling of map types to create a MapCompositeMetaType for String,? parameterized maps:

                       if (typeInfo.isMap())
                       {
                       // See if this is a Map<String,?> type
                       ClassInfo classInfo = (ClassInfo) typeInfo;
                       TypeInfo[] types = classInfo.getActualTypeArguments();
                       if (types != null)
                       {
                       TypeInfo keyType = types[0];
                       TypeInfo valueType = types[1];
                       if(keyType.getName().equals(String.class.getName()))
                       {
                       // Use MapCompositeMetaType
                       MetaType valueMetaType = resolve(valueType);
                       return new MapCompositeMetaType(valueMetaType);
                       }
                       }
                       // No, return the general map type
                       return generateMap(classInfo);
                       }
                      


                      but the following 4 tests fail because they all use types that fall into the Map(String, ?) pattern, and they are expecting TableMetaType/TableValues:
                      Failed tests:
                       testSimpleMap(org.jboss.test.metatype.values.factory.test.MapValueFactoryUnitT
                      estCase)
                       testCompositeValueMap(org.jboss.test.metatype.values.factory.test.MapValueFact
                      oryUnitTestCase)
                       testSimpleMap(org.jboss.test.metatype.types.factory.test.MapMetaTypeFactoryUni
                      tTestCase)
                       testCompositeValueMap(org.jboss.test.metatype.types.factory.test.MapMetaTypeFa
                      ctoryUnitTestCase)
                      


                      What do we want to change, tests or how the factory gets configured for MapCompositeMetaType?


                      • 8. Re: Using a CompositeMetaType for a Map with String keys?

                        I think the tests should change.

                        Here is why, I think, and I am assuming here, that TableMetaTypes were originally designed for "Maps" However, their actual implementations ended up being a hodgepodge MetaType.

                        Each row in the TableMetaType can have its own structure. So one row might have 5 columns and the next row might have 10 columns. TableMetaType is now a very powerful MetaType, but I think overkill for Maps.

                        Personally, while I see the power of TableMetaTypes, I think we should try to avoid using them. Anything we have, can be created combining the Map, List and Simple/Generic types to match our needs.

                        I will also add that my opinion is coming from how JON types are designed, and we just have Map, List and Simple properties and have yet to come across anything that we couldn't handle. like creating List of Maps with Simples for security domains in JMS and config properties for Connection Factories.

                        Thanks

                        • 9. Re: Using a CompositeMetaType for a Map with String keys?

                          You should fix the tests to use examples that generate table types.

                          On "not using table type", you still need them for more complicated maps,
                          e.g. those with composite keys.

                          Although I agree, a map is actually a redundant type since it is really just a

                          Set<Map.Entry>
                          with some additional api, e.g. get(key)

                          • 10. Re: Using a CompositeMetaType for a Map with String keys?

                            Adrian, I agree. The Table type is very powerful and will be needed for more complex types.

                            I meant more avoid it unless it is 100% necessary for a property (no other obvious choice), otherwise try to use the Map, List, Simple and Generic types.

                            I do know on our end, anytime a property will use a Table type, will require a custom adapter for it. Whereas, using the other types we have more generic adapters already created which will handle them. Again, don't code for us here, I was just pointing this out. :)

                            Thanks

                            • 11. Re: Using a CompositeMetaType for a Map with String keys?
                              starksm64

                              Ok, I'll update the table tests and I'm adding a mapping of java.util.Properties to MapCompositeMetaType(SimpleMetaType.STRING) as well.

                              • 12. Re: Using a CompositeMetaType for a Map with String keys?
                                starksm64

                                So I'm creating a proper test in CompositeValueFactoryUnitTestCase, and there is a descrepency with how the value TypeInfo is being obtained vs what is seen in CompositeMetaTypeFactoryUnitTestCase. There, the type is obtained from the field.getGenericType():

                                 /**
                                 * JBMICROCONT-238, Map<String,?> should map to a MapCompositeMetaType(MetaValue<?>)
                                 * @throws Exception
                                 */
                                 public void testMapWithStringKeyComposite() throws Exception
                                 {
                                 Field field = getClass().getField("compositeSignature");
                                 Type mapSignature = field.getGenericType();
                                 CompositeMetaType result = assertInstanceOf(resolve(mapSignature), CompositeMetaType.class);
                                 MapCompositeMetaType expected = new MapCompositeMetaType(SimpleMetaType.STRING);
                                
                                 testComposite(expected, result);
                                
                                 Map<String, MetaValue> itemValues = new HashMap<String, MetaValue>();
                                 itemValues.put("key1", SimpleValueSupport.wrap("value1"));
                                 itemValues.put("key2", SimpleValueSupport.wrap("value2"));
                                 itemValues.put("key3", SimpleValueSupport.wrap("value3"));
                                 MapCompositeValueSupport mapValue = new MapCompositeValueSupport(itemValues, expected);
                                 assertEquals(SimpleValueSupport.wrap("value1"), mapValue.get("key1"));
                                 assertEquals(SimpleValueSupport.wrap("value2"), mapValue.get("key2"));
                                 assertEquals(SimpleValueSupport.wrap("value3"), mapValue.get("key3"));
                                 }
                                


                                In the CompositeValueFactoryUnitTestCase case, the type has to be obtained from Configuration.getTypeInfo(value.getClass()), whcih relies on WeakTypeCache.get(Type). Somewhere along the lines the parameterized info on the HashMap is being lost, so the MetaType is not MapCompositeMetaType.

                                I guess this goes back to why the type test cannot be written as:
                                 public void testMapWithStringKeyComposite() throws Exception
                                 {
                                 Map<String,String> map = new HashMap<String,String>();
                                 CompositeMetaType result = assertInstanceOf(resolve(map.getClass()), CompositeMetaType.class);
                                 MapCompositeMetaType expected = new MapCompositeMetaType(SimpleMetaType.STRING);
                                ...
                                


                                This fails because the parameter types on the map are lost.


                                • 13. Re: Using a CompositeMetaType for a Map with String keys?

                                   

                                  "scott.stark@jboss.org" wrote:

                                  In the CompositeValueFactoryUnitTestCase case, the type has to be obtained from Configuration.getTypeInfo(value.getClass()),


                                  No it doesn't. "You pay your money and take your choice" ;-)

                                  From AbstractMetaValueFactoryTest:
                                  
                                   /**
                                   * Create a meta value
                                   *
                                   * @param value the value
                                   * @return the meta value
                                   */
                                   protected MetaValue createMetaValue(Object value)
                                   {
                                   return metaValueFactory.create(value);
                                   }
                                  
                                   /**
                                   * Create a meta value
                                   *
                                   * @param value the value
                                   * @param type the type
                                   * @return the meta value
                                   */
                                   protected MetaValue createMetaValue(Object value, Type type)
                                   {
                                   return metaValueFactory.create(value, type);
                                   }
                                  


                                  There's also one with TypeInfo on the real factory, but not in the test helper.
                                  I guess there should also be methods where you pass in the MetaType?????

                                  • 14. Re: Using a CompositeMetaType for a Map with String keys?
                                    starksm64

                                    well, I'll use the reflective type since that is what is being used in the CompositeMetaTypeFactoryUnitTestCase. I don't understand why you don't value.getClass() is not the same ParameterizedType that you get from the field/method getGenericType()/getGenericReturnType().

                                    1 2 Previous Next