-
Notifications
You must be signed in to change notification settings - Fork 2
Spell Checker
| Tutorial Level | Goals | Prerequisites |
|---|---|---|
| Beginners |
|
This tutorial introduces the properties. You will also create a small application composed by several ApAM Components.
This component provide a very simple service defined with this interface (SpellDico.java) :
package fr.imag.adele.apam.tutorials.spell.dico.spec;
public interface SpellDico {
/**
* @param word
* @return true if word is defined in the dictionary
*/
public boolean check(String word);
}<apam xmlns="fr.imag.adele.apam" xmlns:ipojo="org.apache.felix.ipojo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="fr.imag.adele.apam http://repository-apam.forge.cloudbees.com/release/schema/ApamCore.xsd" >
<specification name="SpellDico"
interfaces="fr.imag.adele.apam.tutorials.spell.dico.spec.SpellDico">
<definition name="Language" type="French, English, German, Italian" />
</specification>
</apam>In this case we have an enumeration of predefined string values, but we can also define type="int" or type="string" or even an array using type="{int}" type="{string}"...
As an example we have a very simple implementation of the service (SpellDicoFr.java) : (Feel free to implement more complex dictionaries, or other languages)
package fr.imag.adele.apam.tutorials.spell.dico.impl;
import java.util.HashSet;
import java.util.Set;
import fr.imag.adele.apam.tutorials.spell.dico.spec.SpellDico;
public class SpellDicoFr implements SpellDico{
private Set<String> FrenchDictionary;
public SpellDicoFr() {
FrenchDictionary = new HashSet<String>();
// Adding a few words for testing purpose
FrenchDictionary.add("le");
FrenchDictionary.add("petit");
FrenchDictionary.add("chat");
FrenchDictionary.add("est");
FrenchDictionary.add("mort");
}
/**
* @param word is supposed to be a word in french
* @return true if word is defined in the dictionary
*/
public boolean check(String word) {
return FrenchDictionary.contains(word);
}
}In the descriptor for this component, we will define the property corresponding to the specification (metadata.xml) :
<apam xmlns="fr.imag.adele.apam" xmlns:ipojo="org.apache.felix.ipojo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="fr.imag.adele.apam http://repository-apam.forge.cloudbees.com/release/schema/ApamCore.xsd" >
<implementation name="SpellDicoFr"
specification="SpellDico"
classname="fr.imag.adele.apam.tutorials.spell.dico.impl.SpellDicoFr">
<property name="Language" value="French" />
</implementation>
</apam>Within the same OSGi bundle, we can also package several ApAM Components, in this case the SpellChecker Specification and the SpellChecker Implementation.
The java interface is defined as follow (SpellChecker.java) :
package fr.imag.adele.apam.tutorials.spell.checker;
public interface SpellChecker {
/**
* @param passage is a sentence (sequence of words)
* @return An array of String, each String is a word that haven't been recognized
*/
public String[] check(String passage);
}package fr.imag.adele.apam.tutorials.spell.checker;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import fr.imag.adele.apam.tutorials.spell.dico.spec.SpellDico;
public class SimpleSpellChecker implements SpellChecker {
private SpellDico dictionnaryProvider ;
/* (non-Javadoc)
* @see fr.imag.adele.apam.tutorials.spell.checker.SpellChecker#check(java.lang.String)
*/
public String[] check(String passage) {
if ((passage == null) || (passage.length() == 0))
return null;
Set<String> errorList = new HashSet<String>();
StringTokenizer st = new StringTokenizer(passage, " ,.!?;:");
while (st.hasMoreTokens()) {
String word = st.nextToken();
if (!dictionnaryProvider.check(word))
errorList.add(word);
}
return errorList.toArray(new String[0]);
}
}We can now describe the components within the same ApAM descriptor (metadata.xml) :
<apam xmlns="fr.imag.adele.apam" xmlns:ipojo="org.apache.felix.ipojo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="fr.imag.adele.apam http://repository-apam.forge.cloudbees.com/release/schema/ApamCore.xsd" >
<specification name="SpellChecker"
interfaces="fr.imag.adele.apam.tutorials.spell.checker.SpellChecker">
<dependency specification="SpellDico" name="dico"/>
</specification>
<implementation name="SimpleSpellChecker"
specification="SpellChecker"
classname="fr.imag.adele.apam.tutorials.spell.checker.SimpleSpellChecker">
<dependency name="dico" specification="SpellDico" field="dictionnaryProvider" />
</implementation>
</apam>The java implementation is pretty simple (SpellGUIFrame.java) :
package fr.imag.adele.apam.tutorials.spell.gui;
import java.awt.Font;
import java.awt.event.ActionListener;
import fr.imag.adele.apam.tutorials.spell.checker.SpellChecker;
public class SpellGUIFrame implements ActionListener{
private javax.swing.JFrame frame;
private javax.swing.JTextArea textAreaEnter;
private javax.swing.JLabel textAreaReturn;
private javax.swing.JButton checkBtn;
private String name ="APAM Spell Checker Tutorial";
private SpellChecker spellCheckerServiceProvider;
private String currentLanguage;
public void start() {
System.out.println("SpellGUIFrame Service Started");
frame = new javax.swing.JFrame(name);
initComponents();
frame.setVisible(true);
}
public void stop() {
System.out.println("SpellGUIFrame Service Stopped");
if (frame != null) {
frame.dispose();
frame = null;
}
}
private void initComponents() {
frame.setSize(600, 200);
textAreaEnter = new javax.swing.JTextArea("Enter your passage here...",5,100);
textAreaEnter.setFont(new Font("Serif", Font.ITALIC, 16));
textAreaReturn = new javax.swing.JLabel(" | No results for the moment !");
checkBtn = new javax.swing.JButton("Check Text !");
checkBtn.addActionListener(this);
frame.setLayout(new java.awt.BorderLayout());
frame.add(textAreaEnter, java.awt.BorderLayout.NORTH);
frame.add(checkBtn, java.awt.BorderLayout.CENTER);
frame.add(textAreaReturn, java.awt.BorderLayout.SOUTH);
}
public void actionPerformed(java.awt.event.ActionEvent e) {
String passage = textAreaEnter.getText();
String[] wrongs = spellCheckerServiceProvider.check(passage);
String results= "Current Language : "+currentLanguage+" | Wrong words : ";
for(int i=0;i<wrongs.length;i++)
results+=" - "+wrongs[i];
textAreaReturn.setText(results);
}
}<apam xmlns="fr.imag.adele.apam" xmlns:ipojo="org.apache.felix.ipojo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="fr.imag.adele.apam http://repository-apam.forge.cloudbees.com/release/schema/ApamCore.xsd" >
<implementation name="SpellGUIFrame"
classname="fr.imag.adele.apam.tutorials.spell.gui.SpellGUIFrame">
<callback onInit="start" onRemove="stop"/>
<dependency name="spellChecker" specification="SpellChecker" field="spellCheckerServiceProvider" />
<definition name="Language" field="currentLanguage" type="French, English, German, Italian" value="$this.spellChecker.dico$Language"/>
</implementation>
<apam-instance implementation="SpellGUIFrame" name="SpellGUIFrameInstance"/>
</apam>Another operation we use is substitution,
$thisindicate the source (the current instance), in which we retrieve the spellChecker dependecy (the field that is dynamically injected), in the spellChecker we retrieve the dico dependency (another field dynamically injected) and finally the value of the attribute (the Language property).
Last but not least, we can see that we declare directly an ApAM component instance in the descriptor (instead of calling it from the console).