reworked the sample in order to show a FactoryConfigurationAdapterService annotation usage example

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@947821 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/samples.annotation/README b/dependencymanager/samples.annotation/README
index 324098a..a8d97a4 100644
--- a/dependencymanager/samples.annotation/README
+++ b/dependencymanager/samples.annotation/README
@@ -3,17 +3,25 @@
 Sample description:
 
   This sample shows a basic "SpellChecker" application which provides a Felix "spellcheck" shell
-  command. The SpellChecker class is a Felix Shell command (it provides the "Command" service),
+  command. The SpellChecker class is a Felix Shell command (it provides a "Command" service),
   which accepts a string as parameter. So, when you type a string, the command just says if the
   specified string has been found from one of its injected dictionaries. The SpellChecker class has a
-  required/multiple dependency over any available DictionaryService. Currently, there is one
-  "EnglishDictionary" which implements the DictionaryService. The EnglishDictionary service uses
-  MetaType, allowing to configure english words through ConfigAdmin and WebConsole. 
+  required/multiple (1..N) dependency over any available DictionaryService.
+  
+  A DictionaryService is defined using a FactoryConfigurationAdapterService annotation, allowing to
+  instantiate many DictionaryService service instances from webconsole. This annotation actually registers
+  a ManagedServiceFactory into the Registry, and you can specify the meta type informations regarding
+  the properties metadata.
+   
   So, before testing, you first have to go to webconsole Configuration panel, and specify some
-  english words in the configuration for the "English Dictionary" PID. Then, go to the felix shell,
-  and you will then see the "spellcheck" command (when typing "help").
-  Notice that in the sample, you will also find an Aspect Service (DictionaryAspect.java), which
-  decorates the EnglishDictionary service, by adding an "aspect" word in the dictionary.
+  dictionaries (see the DictionaryService Factory PID). 
+  Then, go to the felix shell, and you will then see the "spellcheck" command (when typing "help").
+  
+  Notice that in the sample, you will also find a DictionaryAspect Service (DictionaryAspect.java), which
+  decorates the EnglishDictionary service, by adding some additional words to *all* provided 
+  DictionaryService services. The DictionaryAspect also show how to use a ConfigurationDependency annotation, 
+  allowing to configure the words from webconsole. A ConfigurationDependency actually registers a ManagedService object
+  in the Registry, which also implements a MetaTypeProvider service for metatype support.
 
 How to test:
 
@@ -31,15 +39,16 @@
 
   2) Start felix
   3) Go to web console, in the Configuration pannel
-  4) Edit the "English Dictionary" Configuration, add some words, then click on "save".
-     At this point, the "EnglishDictionary" service will be enabled and the SpellCheck component
-     will be injected with it. Then you should see the "spellcheck" command, when typing "help" on the shell.
+  4) Edit the "Dictionary Services" Configuration, add some dictionaries. By default, an English dictionary is 
+     displayed. Just click on "save", then click on your refresh web browser: you will see a new dictionary service
+     instance. At this point, a DictionaryService service will be enabled (with the service property "lang=en"), 
+     and the SpellCheck component will be injected with it. Then you should see the "spellcheck" command, when typing 
+     "help" on the shell.
 
   5) Just type "spellcheck hello", and the command should reply a fantastic message, like "word hello is correct".
-
-
-
-
-
   
-     
+  6) You can also click on the "Aspect Dictionary" button, in order to decorate *all* Dictionaries using some custom words.
+     By default, the "aspect" word is pre configured, but you can click on the "+" button in order to add more words. 
+     Then click on Save. At this point, all DictionaryService instances will be decorated with the aspect service.
+     So, now, if you type "spellcheck aspect", then the message: "word aspect is correct" should be displayed. 
+
diff --git a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryAspect.java b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryAspect.java
index 3eb2247..daa9f78 100644
--- a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryAspect.java
+++ b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryAspect.java
@@ -18,12 +18,18 @@
  */
 package org.apache.felix.dm.samples.annotation;
 
+import java.util.Dictionary;
+import java.util.concurrent.CopyOnWriteArrayList;
+
 import org.apache.felix.dm.annotation.api.AspectService;
+import org.apache.felix.dm.annotation.api.PropertyMetaData;
+import org.apache.felix.dm.annotation.api.dependency.ConfigurationDependency;
 import org.apache.felix.dm.annotation.api.dependency.ServiceDependency;
 import org.osgi.service.log.LogService;
 
 /**
- * This aspect wraps a Dictionary and checks the "aspect" word on behalf of it.
+ * This aspect applies to all available Dictionary Services, and checks some custom words, configurable from
+ * config admin.
  */
 @AspectService( ranking = 10 )
 public class DictionaryAspect implements DictionaryService
@@ -34,15 +40,51 @@
     private volatile DictionaryService m_originalDictionary;
 
     /**
+     * We store all configured words in a thread-safe data structure, because ConfigAdmin
+     * may invoke our updated method at any time.
+     */
+    private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+    
+    /**
      * We'll use the OSGi log service for logging. If no log service is available, then we'll use a NullObject.
      */
     @ServiceDependency(required = false)
     private LogService m_log;
 
+    /**
+     * Defines a configuration dependency for retrieving our custo words (by default, our PID is our full class name).
+     * This annotation actually provides a ManagedService into the registry, and you can specify meta information regarding
+     * all the configuration properties (required by webconsole).
+     */
+    @ConfigurationDependency(
+        heading="Aspect Dictionary", 
+        description="Declare here some words to check",
+        propagate=false,
+        metadata={
+            @PropertyMetaData(
+                heading="Dictionary aspect words",
+                description="Declare here the list of words supported by this dictionary aspect. ",
+                defaults={"aspect"},
+                id="words",
+                cardinality=Integer.MAX_VALUE)
+        }
+    )
+    protected void updated(Dictionary<String, ?> config) {
+        m_words.clear();
+        String[] words = (String[]) config.get("words");
+        for (String word : words) {
+            m_words.add(word);
+        }
+    }
+
+    /**
+     * Checks if a word is found from our custom word list. if not, delegate to the decorated
+     * dictionary.
+     */
     public boolean checkWord(String word)
     {
         m_log.log(LogService.LOG_DEBUG, "DictionaryAspect: checking word " + word);
-        if (word.equals("aspect")) {
+        if ("aspect".equals(word)) {
             return true;
         }
         return m_originalDictionary.checkWord(word);
diff --git a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryImpl.java b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryImpl.java
new file mode 100644
index 0000000..449ee57
--- /dev/null
+++ b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/DictionaryImpl.java
@@ -0,0 +1,87 @@
+/*
+ * 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.dm.samples.annotation;
+
+import java.util.Dictionary;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.felix.dm.annotation.api.PropertyMetaData;
+import org.apache.felix.dm.annotation.api.adapter.FactoryConfigurationAdapterService;
+
+/**
+ * A Dictionary Service. This service uses a FactoryConfigurationAdapterService annotation, 
+ * allowing to instantiate this service from webconsole. This annotation will actually register
+ * a ManagedServiceFactory in the registry, and also support meta types for describing metadata of
+ * all configuration properties.
+ * 
+ * You must configure at least one Dictionary from web console, since the SpellCheck won't start if no Dictionary
+ * Service is available.
+ */
+@FactoryConfigurationAdapterService(
+    factoryPid="DictionaryServiceFactory", 
+    propagate=true, 
+    updated="updated",
+    heading="Dictionary Services",
+    description="Declare here some Dictionary instances, allowing to instantiates some DictionaryService services for a given dictionary language",
+    metadata={
+        @PropertyMetaData(
+            heading="Dictionary Language",
+            description="Declare here the language supported by this dictionary. " +
+                "This property will be propagated with the Dictionary Service properties.",
+            defaults={"en"},
+            id="lang",
+            cardinality=1),
+        @PropertyMetaData(
+            heading="Dictionary words",
+            description="Declare here the list of words supported by this dictionary. " +
+                "This property is private and won't be propagated along with the dictionary service property.",
+            defaults={"hello", "world"},
+            id="words",
+            cardinality=Integer.MAX_VALUE)
+    }
+)  
+public class DictionaryImpl implements DictionaryService
+{
+    /**
+     * We store all configured words in a thread-safe data structure, because ConfigAdmin
+     * may invoke our updated method at any time.
+     */
+    private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+    
+    /**
+     * Our service will be initialized from ConfigAdmin, so we define here a configuration dependency
+     * (by default, our PID is our full class name).
+     * @param config The configuration where we'll lookup our words list (key="words").
+     */
+    protected void updated(Dictionary<String, ?> config) {
+        m_words.clear();
+        String[] words = (String[]) config.get("words");
+        for (String word : words) {
+            m_words.add(word);
+        }
+    }
+           
+    /**
+     * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole.
+     */
+    public boolean checkWord(String word)
+    {
+        return m_words.contains(word);
+    }
+}
diff --git a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/EnglishDictionary.java b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/EnglishDictionary.java
deleted file mode 100644
index 3580bb1..0000000
--- a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/EnglishDictionary.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.dm.samples.annotation;
-
-import java.util.Dictionary;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.felix.dm.annotation.api.dependency.ConfigurationDependency;
-import org.apache.felix.dm.annotation.api.Property;
-import org.apache.felix.dm.annotation.api.PropertyMetaData;
-import org.apache.felix.dm.annotation.api.Service;
-
-/**
- * An English Dictionary Service. We provide here our Properties MetaData in order to let webconsole configure us.
- * You must configure the PID that corresponds to this class through web console in order to activate this service.
- */
-@Service(properties={@Property(name="language", value="en")})
-public class EnglishDictionary implements DictionaryService
-{
-    /**
-     * The id of our Configuration Admin property key.
-     */
-    public final static String WORDS = "words";
-    
-    /**
-     * We store all configured words in a thread-safe data structure, because ConfigAdmin
-     * may invoke our updated method at any time.
-     */
-    private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
-    
-    /**
-     * Our service will be initialized from ConfigAdmin, so we define here a configuration dependency
-     * (by default, our PID is our full class name).
-     * @param config The configuration where we'll lookup our words list (key="words").
-     */
-    @ConfigurationDependency(
-        heading="English Dictionary", 
-        description = "Configuration for the EnglishDictionary Service",
-        metadata={
-            @PropertyMetaData(
-                heading="English Words",
-                description="Declare here some valid english words",
-                defaults={"hello", "world"},
-                id=EnglishDictionary.WORDS,
-                cardinality=Integer.MAX_VALUE)
-        }
-    )
-    protected void updated(Dictionary<String, ?> config) {
-        m_words.clear();
-        String[] words = (String[]) config.get(WORDS);
-        for (String word : words) {
-            m_words.add(word);
-        }
-    }
-           
-    /**
-     * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole.
-     */
-    public boolean checkWord(String word)
-    {
-        return m_words.contains(word);
-    }
-}
diff --git a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/SpellChecker.java b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/SpellChecker.java
index 0c50406..f962acf 100644
--- a/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/SpellChecker.java
+++ b/dependencymanager/samples.annotation/src/main/java/org/apache/felix/dm/samples/annotation/SpellChecker.java
@@ -22,9 +22,9 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.apache.felix.dm.annotation.api.Service;
-import org.apache.felix.dm.annotation.api.dependency.ServiceDependency;
 import org.apache.felix.dm.annotation.api.Start;
 import org.apache.felix.dm.annotation.api.Stop;
+import org.apache.felix.dm.annotation.api.dependency.ServiceDependency;
 import org.apache.felix.shell.Command;
 import org.osgi.service.log.LogService;