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

    Using a CompositeMetaType for a Map with String keys?

    Scott Stark Master

      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?
          Ales Justin Master

          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?
            Mark Spritzler Apprentice

            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?
              Ales Justin Master

               

              "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?
                Scott Stark Master

                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?
                  Adrian Brock Master

                   

                  "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>
                  


                  • 7. Re: Using a CompositeMetaType for a Map with String keys?
                    Scott Stark Master

                    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?
                      Mark Spritzler Apprentice

                      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?
                        Adrian Brock Master

                        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?
                          Mark Spritzler Apprentice

                          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?
                            Scott Stark Master

                            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?
                              Scott Stark Master

                              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?
                                Adrian Brock Master

                                 

                                "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?
                                  Scott Stark Master

                                  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