FELIX-3338 implemented support for optional attributes, and added a test case for it

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1240689 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/metatype/src/main/java/org/apache/felix/metatype/AD.java b/metatype/src/main/java/org/apache/felix/metatype/AD.java
index 82482c8..4e88897 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/AD.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/AD.java
@@ -19,7 +19,10 @@
 package org.apache.felix.metatype;
 
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.felix.metatype.internal.Activator;
 import org.osgi.service.log.LogService;
@@ -32,7 +35,7 @@
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class AD
+public class AD extends OptionalAttributes
 {
 
     /**
diff --git a/metatype/src/main/java/org/apache/felix/metatype/Attribute.java b/metatype/src/main/java/org/apache/felix/metatype/Attribute.java
index dcf1de5..6458e6d 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/Attribute.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/Attribute.java
@@ -24,7 +24,7 @@
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class Attribute
+public class Attribute extends OptionalAttributes
 {
 
     private String adRef;
diff --git a/metatype/src/main/java/org/apache/felix/metatype/Designate.java b/metatype/src/main/java/org/apache/felix/metatype/Designate.java
index b78efdb..cece465 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/Designate.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/Designate.java
@@ -25,7 +25,7 @@
  * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class Designate
+public class Designate extends OptionalAttributes
 {
 
     private String pid;
diff --git a/metatype/src/main/java/org/apache/felix/metatype/DesignateObject.java b/metatype/src/main/java/org/apache/felix/metatype/DesignateObject.java
index 71c0222..0fc2655 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/DesignateObject.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/DesignateObject.java
@@ -29,7 +29,7 @@
  * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class DesignateObject
+public class DesignateObject extends OptionalAttributes
 {
 
     private String ocdRef;
diff --git a/metatype/src/main/java/org/apache/felix/metatype/MetaData.java b/metatype/src/main/java/org/apache/felix/metatype/MetaData.java
index e24e195..e7d69d4 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/MetaData.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/MetaData.java
@@ -31,7 +31,7 @@
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class MetaData
+public class MetaData extends OptionalAttributes
 {
 
     private String localePrefix;
@@ -39,7 +39,6 @@
     private Map designates;
     private URL source;
 
-
     public String getLocalePrefix()
     {
         return localePrefix;
diff --git a/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java b/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
index 690f1c1..b3ce2b6 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
@@ -22,8 +22,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.felix.metatype.internal.Activator;
 import org.kxml2.io.KXmlParser;
@@ -74,6 +77,14 @@
     /** The XML parser used to read the XML documents */
     private KXmlParser parser = new KXmlParser();
 
+    /** Sets of attributes belonging to XML elements. */
+    private final Set AD_ATTRIBUTES = new HashSet(Arrays.asList(new String[] { "name", "description", "id", "type", "cardinality", "min", "max", "default", "required" }));
+    private final Set ATTRIBUTE_ATTRIBUTES = new HashSet(Arrays.asList(new String[] { "adref", "content" }));
+    private final Set DESIGNATE_ATTRIBUTES = new HashSet(Arrays.asList(new String[] { "pid", "factoryPid", "bundle", "optional", "merge" }));
+    private final Set DESIGNATEOBJECT_ATTRIBUTES = new HashSet(Arrays.asList(new String[] { "ocdref" }));
+    private final Set METADATA_ATTRIBUTES = new HashSet(Arrays.asList(new String[] { "localization" }));
+    private final Set OCD_ATTRIBUTES = new HashSet(Arrays.asList(new String[] { "name", "description", "id" }));
+    
 
     /**
      * Parses the XML document provided by the <code>url</code>. The XML document
@@ -185,11 +196,27 @@
         return mti;
     }
 
+    
+    private void readOptionalAttributes(OptionalAttributes entity, Set attributes) {
+        int count = this.parser.getAttributeCount();
+        for (int i = 0; i < count; i++)
+        {
+            String name = this.parser.getAttributeName(i);
+            if (!attributes.contains(name))
+            {
+                String value = this.parser.getAttributeValue(i);
+                entity.addOptionalAttribute(name, value);
+            }
+        }
+    }
+    
 
     private MetaData readMetaData() throws IOException, XmlPullParserException
     {
         MetaData mti = this.createMetaData();
         mti.setLocalePrefix( this.getOptionalAttribute( "localization" ) );
+        
+        readOptionalAttributes(mti, METADATA_ATTRIBUTES);
 
         int eventType = this.parser.next();
         while ( eventType != XmlPullParser.END_DOCUMENT )
@@ -231,6 +258,8 @@
         ocd.setId( this.getRequiredAttribute( "id" ) );
         ocd.setName( this.getRequiredAttribute( "name" ) );
         ocd.setDescription( this.getOptionalAttribute( "description" ) );
+        
+        readOptionalAttributes(ocd, OCD_ATTRIBUTES);
 
         int eventType = this.parser.next();
         while ( eventType != XmlPullParser.END_DOCUMENT )
@@ -287,6 +316,8 @@
         designate.setBundleLocation( this.getOptionalAttribute( "bundle" ) );
         designate.setOptional( this.getOptionalAttribute( "optional", false ) );
         designate.setMerge( this.getOptionalAttribute( "merge", false ) );
+        
+        readOptionalAttributes(designate, DESIGNATE_ATTRIBUTES);
 
         int eventType = this.parser.next();
         while ( eventType != XmlPullParser.END_DOCUMENT )
@@ -331,6 +362,8 @@
         ad.setDefaultValue( this.getOptionalAttribute( "default" ) );
         ad.setRequired( this.getOptionalAttribute( "required", true ) );
 
+        readOptionalAttributes(ad, AD_ATTRIBUTES);
+        
         Map options = new LinkedHashMap();
         int eventType = this.parser.next();
         while ( eventType != XmlPullParser.END_DOCUMENT )
@@ -372,6 +405,8 @@
     {
         DesignateObject oh = this.createDesignateObject();
         oh.setOcdRef( this.getRequiredAttribute( "ocdref" ) );
+        
+        readOptionalAttributes(oh, DESIGNATEOBJECT_ATTRIBUTES);
 
         int eventType = this.parser.next();
         while ( eventType != XmlPullParser.END_DOCUMENT )
@@ -408,6 +443,8 @@
         ah.setAdRef( this.getRequiredAttribute( "adref" ) );
         ah.addContent( this.getOptionalAttribute( "content" ), true );
 
+        readOptionalAttributes(ah, ATTRIBUTE_ATTRIBUTES);
+
         int eventType = this.parser.next();
         while ( eventType != XmlPullParser.END_DOCUMENT )
         {
diff --git a/metatype/src/main/java/org/apache/felix/metatype/OCD.java b/metatype/src/main/java/org/apache/felix/metatype/OCD.java
index b9b21ca..5764bf9 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/OCD.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/OCD.java
@@ -30,7 +30,7 @@
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class OCD
+public class OCD extends OptionalAttributes
 {
 
     private String id;
diff --git a/metatype/src/main/java/org/apache/felix/metatype/OptionalAttributes.java b/metatype/src/main/java/org/apache/felix/metatype/OptionalAttributes.java
new file mode 100644
index 0000000..365643c
--- /dev/null
+++ b/metatype/src/main/java/org/apache/felix/metatype/OptionalAttributes.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.metatype;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class OptionalAttributes {
+    private Map optionalAttributes;
+    
+    public void addOptionalAttribute(String name, String value)
+    {
+        if (optionalAttributes == null)
+        {
+            optionalAttributes = new HashMap();
+        }
+        optionalAttributes.put(name, value);
+    }
+    
+    public Map getOptionalAttributes() {
+        return optionalAttributes;
+    }
+}
diff --git a/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java b/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java
index 7a9ae02..f5d497f 100644
--- a/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java
+++ b/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java
@@ -66,6 +66,20 @@
         assertNull( mti.getObjectClassDefinitions() );
     }
 
+    public void testOptionalAttributesInMetaData() throws IOException, XmlPullParserException
+    {
+        String name = "myattribute";
+        String value = "working";
+        String localization = "test";
+        String empty = "<MetaData " + name + "=\"" + value + "\" localization=\"" + localization + "\" />";
+        MetaData mti = read( empty );
+
+        assertEquals( localization, mti.getLocalePrefix() );
+        assertNull( mti.getObjectClassDefinitions() );
+        assertNotNull( mti.getOptionalAttributes() );
+        assertEquals( 1, mti.getOptionalAttributes().size() );
+        assertEquals( value, mti.getOptionalAttributes().get(name) );
+    }
 
     public void testWithNamespace_1_0_0() throws IOException, XmlPullParserException
     {