UIMA FR
Communauté francophone autour d'UIMA
  • Accueil
  • Top 10
  • Statistiques
  • Inscription
  • Archives
  • Contact

Informations

UIMA Fr - Agrégation des informations de la communauté francophone autour d'Apache UIMA

Abonnement

  • feed Fil de tous les articles
  • feed Fil des articles populaires

Membres

  • feed  Fabien Poulard
  • feed  Jérôme Rocheteau
  • feed  Matthieu Vernier
  • feed  Nicolas Hernandez
  • feed  Portail UIMA FR

Participer

  • meta Ajouter votre blog
  • meta Administration
Filtrer les articles :     Articles du jour   -   Articles de la semaine   -   Articles du mois   -   Tous les articles

Accès rapide aux derniers articles de la page


28/01/2010 : Comment filtrer des annotations avec UIMA ? 20/01/2010 : Comment récupérer les descripteurs XML de composants UIMA à partir du CLASSPATH ? 14/01/2010 : Comment calculer l'occurrence de termes dans une collection de documents avec UIMA ? 07/01/2010 : Comment utiliser les paramètres de composants UIMA ? 04/12/2009 : Qu'est ce que un Flow Controller ? 30/10/2009 : Comment créer un projet UIMA sous Eclipse ? 29/10/2009 : Comment configurer Eclipse pour UIMA ? 23/10/2009 : Comment installer TextMarker ? 16/10/2009 : Comment récupérer les composants officiels UIMA ? 25/09/2009 : Comment configurer votre POM pour UIMA ?
Page suivante »
Comment filtrer des annotations avec UIMA ? 
0 vote
Par Jérôme Rocheteau le 28/01/2010 à 12:04

Ce billet explique comment sélectionner des annotations en appliquant des filtres sur les indexes des CASes. On prend l'exemple d'un Analysis Engine qui filtre le mot « saperlipopette » dans des textes.

La plate-forme UIMA offre des facilités pour filtrer les annotations parmi l'index d'un CAS. J'explique rapidement comment faire fonctionner ce mécanisme de filtrage en trois temps :

  1. Tout d'abord, il s'agit de récupérer le type d'annotations que nous voulons sélectionner.
  2. Ensuite, il s'agit de sélectionner parmi les annotations seulement celles qui correspondent à ce type.
  3. Enfin, il s'agit d'appliquer un filtre sur ces annotations sélectionnées. Ce filtre est défini par une contrainte qui correspond à ce que nous voulons sélectionner.

La partie générique du code ci-dessous correspond à la façon de créer des contraintes qui permettront d'appliquer des filtres sur les annotations. Il s'agit de créer des contraintes sur la valeur de certains traits d'annotations. Une contrainte peut-être vue avec UIMA comme la donnée d'un chemin de traits (feature path) et d'une contrainte de base (contrainte numérique entière, contrainte numérique flottante, contrainte textuelle, etc). Le mécanisme interne à UIMA consiste vérifier si la valeur du chemin de traits de chaque annotation sélectionnée satisfait effectivement la relation définie par la contrainte de base. C'est ce que fait la méthode getConstraint dans la classe ci-dessous.

La méthode getBasicConstraint renvoie la contrainte de base en fonction de la valeur et plus précisément de son type. Cette méthode s'appuie alors sur deux méthodes getIntContraint et getStringConstraint qui renvoie la contrainte de base en fonction de la relation voulue entre le chemin de traits et la valeur précédente, à savoir une relation d'égalité ou d'inégalité.

En outre, l'Analysis Engine ci-dessous définit une méthode getType qui renvoie le type à partir de son nom et une méthode getFeaturePath qui renvoie le chemin de traits correspondant au type d'annotation et au nom de ce trait.

L'Analysis Engine Filtering suivant réalise les opérations décrites ci-dessus et les met en œuvre afin d'afficher les mots « saperlipopette ». On suppose ainsi que le Type System de cet Analysis Engine contient un type d'annotation fr.free.rocheteau.jerome.Mot qui possède un trait value correspondant au texte couvert par ces mots.

public class Filtering extends JCasAnnotator_ImplBase {

private Type getType (JCas cas,String name) {
Type type = cas.getTypeSystem().getType(name);
if (type == null) {
type = cas.getTypeSystem().getType(name);
if (type == null) {
type = cas.getTypeSystem().getType(name);
if (type == null) {
String msg = "Unknown type " + name);
System.out.println(msg);
}
}
}
return type;
}

private FeaturePath getFeaturePath(JCas cas,Type type,String feat) {
Feature feature = type.getFeatureByBaseName(feat);
FeaturePath path = cas.createFeaturePath();
path.addFeature(feature);
return path;
}

private int EQ = 0;

private int LT = 1;

private int LEQ = 2;

private int GEQ = 3;

private int GT = 4;

private FSConstraint getStringConstraint(ConstraintFactory factory,int type,String string) {
FSStringConstraint constraint = factory.createStringConstraint();
if (type == this.EQ) {
constraint.equals(string);
} else {
return null;
}
return constraint;
}

private FSConstraint getIntConstraint(ConstraintFactory factory,int type,Integer integer) {
FSIntConstraint constraint = factory.createIntConstraint();
if (type == this.EQ) {
constraint.eq(integer);
} else if (type == this.LT) {
constraint.lt(integer);
} else if (type == this.LEQ) {
constraint.leq(integer);
} else if (type == this.GT) {
constraint.gt(integer);
} else if (type == this.GEQ) {
constraint.geq(integer);
} else {
return null;
}
return constraint;
}

private FSConstraint getBasicConstraint(ConstraintFactory factory,int type,Object value) {
if (value instanceof java.lang.String) {
return this.getStringConstraint(factory, type,(String) value);
} else if (value instanceof java.lang.Integer) {
return this.getIntConstraint(factory,type,(Integer) value);
} else {
return null;
}
}

private FSMatchConstraint getConstraint(JCas cas,Type type,String feat,int typ,Object value) {
ConstraintFactory factory = cas.getConstraintFactory();
FSConstraint constraint = this.getBasicConstraint(factory,typ,value);
FeaturePath path = this.getFeaturePath(cas,type,feat);
FSMatchConstraint filter = factory.embedConstraint(path,constraint);
return filter;
}

public void initialize(UimaContext context) throws ResourceInitializationException {
}

public void process(JCas cas) throws AnalysisEngineProcessException {
Type type = this.getType(cas,"fr.free.rocheteau.jerome.Mot");
FSMatchConstraint filter = this.getConstraint(cas,type,"value",this.EQ,"saperlipopette");
FSIterator iter = cas.getAnnotationIndex(type).iterator();
FSIterator res = cas.createFilteredIterator(iter,filter);
while (res.hasNext()) {
Annotation a = res.next();
System.out.println(a.toString(2));
}
}

}
Retour au sommaire
Comment récupérer les descripteurs XML de composants UIMA à partir du CLASSPATH ? 
0 vote
Par Jérôme Rocheteau le 20/01/2010 à 11:36

Ce billet explique comment récupérer les descripteurs XML de Type Systems, Collection Readers, d'Analysis Engines, de CAS Consumers ou d'autres descripteurs XML pour des composants UIMA à partir de répertoires ou d'archives JAR contenus dans le CLASSPATH d'une application Java.

Les outils pour UIMA requiert pour l'instant que les descripteurs XML des composants se trouvent sur le système de fichiers local. Dans la terminologie UIMA, cela s'appelle « importer un composant par son emplacement » (import by location). Or, la plate-forme UIMA permet également de récupérer des composants par leur nom s'ils sont contenus dans le CLASSPATH (import by name). Malheureusement les outils UIMA ne fournissent pas (encore) cette fonctionnalité. Je propose une solution qui s'effectue en deux temps.

Tout d'abord, il s'agit récupérer la liste des éléments contenus dans le CLASSPATH, à parcourir ces éléments et à sélectionner les fichiers XML qu'ils contiennent. Seuls deux types d'élements sont traités : les archives JAR et les répertoires sur le système de fichiers local. C'est la fonction de la méthode setFiles dans l'exemple ci-dessous. Cette méthode fait appel aux deux méthodes addFile pour construire la liste des fichiers XML contenus dans les éléments du CLASSPATH.

Ensuite, il s'agit de parcourir cette liste de fichiers XML et de construire un descripteur XML d'un Analysis Engine à partir des méthodes fournies par la plate-forme UIMA. Si on réussit à obtenir un tel descripteur, on l'ajoute à la liste des Analysis Engines disponibles dans le CLASSPATH. Sinon on tente de construire un descripteur XML d'un Collection Reader qui est lui-même ajouté à la liste des Collection readers disponibles dans le CLASSPATH. C'est le rôle de la méthode setComponents dans l'exemple ci-dessous qui fait appel aux méthodes addAnalysisEngine et addCollectionReader. On a commencé par les Analysis Engines étant donné qu'il représente la majorité des descripteurs XML pour UIMA. On pourrait imaginer étendre la méthode setComponents pour détecter les Type Systems, les CAS Consumers et les autres types de composants UIMA.

public class ComponentDetection {

private List collectionReaders;

private void setCollectionReaders() {
this.collectionReaders = new ArrayList();
}

private List getCollectionReaders() {
return this.collectionReaders;
}

private void addCollectionReader(String name) throws IOException, InvalidXMLException {
XMLInputSource source = new XMLInputSource(name);
XMLParser parser = UIMAFramework.getXMLParser();
CollectionReaderDescription desc = parser.parseCollectionReaderDescription(source);
this.getCollectionReaders().add(desc);
}

private List analysisEngines;

private void setAnalysisEngines() {
this.analysisEngines = new ArrayList();
}

private List getAnalysisEngines() {
return this.analysisEngines;
}

private void addAnalysisEngine(String name) throws IOException, InvalidXMLException {
XMLInputSource source = new XMLInputSource(name);
XMLParser parser = UIMAFramework.getXMLParser();
AnalysisEngineDescription desc = parser.parseAnalysisEngineDescription(source);
this.getAnalysisEngines().add(desc);
}

private List files;

private void setFiles() {
this.files = new ArrayList();
String classPath = System.getProperty("java.class.path");
String pathSeparator = System.getProperty("path.separator");
String[] pathElements = classPath.split(pathSeparator);
for (String pathElement : pathElements) {
try {
JarFile jarFile = new JarFile(pathElement);
this.addFile(jarFile);
} catch (IOException e) {
File file = new File(pathElement);
if (file.exists()) {
if (file.isDirectory()) {
addFile(file);
}
}
} catch (SecurityException e) {
System.err.println(e.getMessage());
}
}
}

private List getFiles() {
return this.files;
}

private void addFile(JarFile jar) {
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.isDirectory()) {
String name = entry.getName();
if (name.endsWith(".xml")) {
try {
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL url = cl.getResource(name);
URI uri = url.toURI();
files.add(uri);
} catch (URISyntaxException e) {
System.err.println(e.getMessage());
}
}
}
}
}

private void addFile(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
addFile(f);
}
} else {
String name = file.getName();
if (name.endsWith(".xml")) {
try {
URI uri = new URI(file.getAbsolutePath());
files.add(uri);
} catch (URISyntaxException e) {
System.err.println(e.getMessage());
}
}
}
}

private void setComponents() {
this.setAnalysisEngines();
this.setCollectionReaders();
for (URI file : this.getFiles()) {
String name = file.toString();
try {
this.addAnalysisEngine(name);
} catch (Exception e) {
try {
this.addCollectionReader(name);
} catch (Exception ee) { }
}
}
}

public ComponentDetection() {
this.setFiles();
this.setComponents();
}

}
<:pre>
Retour au sommaire
Comment calculer l'occurrence de termes dans une collection de documents avec UIMA ? 
0 vote
Par Jérôme Rocheteau le 14/01/2010 à 12:11

Ce billet explique comment réaliser un Analysis Engine qui calcule les occurrences des termes dans des documents avec UIMA et qui les affiche à la fin du traitement de la collection.

Nous définissons tout d'abord ce qu'est une occurrence avant de réaliser le composant qui calcule l'occurrence des termes dans un document.

Définition des occurrences d'un terme dans un document

Le nombre d'occurrences d'un terme dans un document se caractérise simplement par :
  • par le terme lui-même,
  • par l'identifiant du document,
  • par le nombre de ses occurrences.

La classe Java qui correspond à cette définition se nomme Occurence. Elle possède :

  1. un constructeur Occurence qui prend comme paramètres l'identifiant du document, le terme et qui définit le nombre d'occurences à 1,
  2. une méthode incr qui incrémente le nombre d'occurrences et retourne le booléen true si et seulement si le terme et l'identifiant du document en paramètres sont les mêmes que ceux de la classe
  3. une méthode toString afin d'afficher le résultat.
  4. et une méthode compareTo afin d'ordonner une liste d'objets de type Occurence.

Le code de cette classe Java est le suivant :

private class Occurence implements Comparable {

private int id;
private String term;
private int occ;

public Occurence(int id,String term){
this.id = id;
this.term = term;
this.occ = 1;
}

public boolean incr(int id,String term) {
if (this.id == id && this.term.equals(term)) {
this.occ++;
return true;
} else {
return false;
}
}

public String toString() {
String string = "The term '" + this.term + "'";
string += " has " + this.occ + " occurences";
string += " in the " + this.id + "-th document.";
return string;
}

public int compareTo(Occurence occ) {
int diff = 0;
String fst, snd;
Integer i,j;
i = this.id;
j = occ.id;
diff = i.compareTo(j);
if (diff == 0) {
fst = this.term;
snd = occ.term;
diff = fst.compareTo(snd);
if (diff == 0) {
i = this.occ;
j = occ.occ;
diff = i.compareTo(j);
return -diff;
} else { return diff; }
} else { return diff; }
}

}

Le calcul d'occurrences de termes dans les documents d'une collection

L'Analysis Engine qui calcule les occurrences de termes dans un document possède deux attributs :

  1. le premier num qui correspond à l'identifiant du document de la collection en cours d'analyse,
  2. le second occurences qui correspond à la liste globale des occurrences des termes dans les documents de la collection.

Elle possède une méthode add qui incrémente le nombre d'occurrences d'un terme dans un document si celui-ci existe ou qui ajoute une occurrence de ce terme dans ce document à la liste globale.

L'initialisation de l'Analysis Engine, à l'aide de la méthode initialize, consiste à définir le nombre de document traités à 0 et de créer une liste vide pour les occurrences de termes dans les documents. Cette liste sera persistante au cours de l'analyse complète de la collection !

Le cœur de l'analyse, à l'aide de la méthode process, consiste, pour chaque document, à parcourir les annotations dont le type correspond aux termes souhaités (dans l'exemple ci-dessous il s'agit de mots caractérisés par le type d'annotation Mot) et à ajouter cette occurrence avec le texte couvert par cette annotation et l'identifiant du document en cours d'analyse.

Lorsque l'ensemble des documents de la collection est traitée, cet Analysis Engine affiche alors, à l'aide de la méthode collectionProcessComplete, les occurrences des termes dans les documents (d'où l'utilité de la méthode toString de la class Occurence) à partir de la liste globale triée (d'où la nécessité de la méthode compareTo de la classe Occurence).

La classe Java de cet Analysis Engine est le suivant :

public class OccurenceAnalyser extends JCasAnnotator_ImplBase {

private int num;

private List occurences;

private void add(int num,String term) {
boolean done = false;
for (Occurence occ : this.occurences) {
done = done || occ.incr(num,term);
}
if (!done) {
Occurence occ = new Occurence(num,term);
this.occurences.add(occ);
}
}

public void initialize(UimaContext context) throws ResourceInitializationException {
this.num = 0;
this.occurences = new ArrayList();
}

public void process(JCas cas) throws AnalysisEngineProcessException {
this.num++;
Type type = cas.getTypeSystem().getType("fr.free.rocheteau.jerome.Mot");
FSIterator iter = cas.getAnnotationIndex(type).iterator();
while (iter.hasNext()) {
Annotation annotation = iter.next();
String term = annotation.getCoveredText();
this.add(num,term);
}
}

public void collectionProcessComplete() throws AnalysisEngineProcessException {
Collections.sort(this.occurences);
for (Occurence occ : this.occurences) {
System.out.println(occ);
}
}

}
Retour au sommaire
Comment utiliser les paramètres de composants UIMA ? 
0 vote
Par Jérôme Rocheteau le 07/01/2010 à 13:56

Ce billet présente deux manières d'utiliser les paramètres des composants UIMA. Ces deux types d'utilisation sont illustrés avec l'exemple d'un composant qui extrait le contenu textuel d'une ressource en fonction de son type de contenu.

Il existe principalement deux manières d'utiliser les paramètres d'un composant UIMA. Un même paramètre peut être utilisé de ces deux manières. En effet, ou bien le paramètre est utilisé par son composant « en interne » ou bien si il est utilisé « en externe » par un composant agrégé qui contient le composant précédent.

Le 1er type d'utilisation correspond au paramétrage « classique » d'un composant UIMA. Dans ce cas, le descripteur XML du composant UIMA contient, d'une part, la déclaration du paramètre et de sont type de valeur et, d'autre part, de la définition de ce paramètre à l'aide d'une paire composée du nom de ce paramètre et de sa valeur. La classe Java du composant UIMA utilise alors les informations fournies par son descripteur XML :sa méthode initialize récupère la valeur de ce paramètre tandis que la méthode process effectue des traitements en fontion de la valeur de ce paramètre.

Le second type d'utilisation consiste à déclarer et définir, dans le descripteur XML du composant UIMA, un paramètre dont la valeur ne va pas servir à la classe Java de ce composant. En revanche, ce paramètre va être accessible comme une méta-donnée de ce composant UIMA par tout composant qui l'utilisera dans une chaîne de traitement.

Le composant agrégé TextExtractor permet d'illustrer les deux utilisations possibles d'un paramètre de composants UIMA. Il s'agit d'un composant qui extrait le contenu textuel d'une vue d'un CAS et qui la sauvegarde dans une autre vue. Ce composant contient donc respectivement les deux paramètres inputView et outputView.

C'est un composant agrégé contenant quatre composants primitifs qui extrait respectivement le contenu textuel de la vue d'un CAS de type "text/plain", "application/msword", "application/pdf" et "application/rtf". Le texte extrait est alors sauvegardé dans une nouvelle vue du CAS. Ces composants primitifs contiennent donc tous trois paramètres inputView, outputView et contentTypes. Ce dernier paramètre définit la liste de type de contenu traités par chacun de ces composants primitifs et il n'est pas utilisé par les classes Java de ces composants. Le paramètre contentTypes va servir au composant agrégé TextExtractor de sélectionner le composant primitif adéquat lors du traitement d'un CAS.

Le composant TextExtractor utilise un Flow Controller qui récupère des méta-données des quatre composants primitifs le type de contenu à partir duquel le texte est extrait. Ce Flow Controller construit alors une table associant l'identifiant de ces composants primitifs et leur type de contenu traité ; cette table permet alors de sélectionner le composants primitif adéquat. La classe ContentTypeFlowController construit cette table d'association :

public class ContentTypeFlowController extends JCasFlowController_ImplBase {

private Map contentTypes = new HashMap();

private void build(Map map) {
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
String id = (String) iter.next();
AnalysisEngineMetaData md = map.get(id);
ConfigurationParameterSettings config = md.getConfigurationParameterSettings();
String[] types = (String[]) config.getParameterValue("contentTypes");
for (String type : types) {
this.contentTypes.put(type,id);
}
}
}

public void initialize(FlowControllerContext context) throws ResourceInitializationException {
super.initialize(context);
this.build((Map) context.getAnalysisEngineMetaDataMap());
}

public Flow computeFlow(JCas cas) throws AnalysisEngineProcessException {
ContentTypeFlow flow = new ContentTypeFlow(this);
flow.setJCas(cas);
return flow;
}

}

La sélection prprement dite est effectuée par la classe ContentTypeFlow :

public class ContentTypeFlow extends JCasFlow_ImplBase {

private ContentTypeFlowController controller;
private boolean done = false;

public ContentTypeFlow(ContentTypeFlowController controller) {
this.controller = controller;
}

public Step next() throws AnalysisEngineProcessException {
if (done) {
return new FinalStep();
} else {
JCas cas = this.getJCas();
String uri = cas.getSofaDataURI();
String type = cas.getSofaMimeType();
String key = this.controller.contentTypes.get(type);
this.done = true;
return new SimpleStep(key);
}
}

}

Il suffit alors de définir le descripteur XML du composant agrégé TextExtractor ainsi :

Il s'agit de l'onglet Parameters de ce composant. À gauche sont définis les deux paramètres inputView et outputView de telle sorte que leur valeur respective est transmise à ses composants primitifs. À droite figurent les différents paramètres des composants primitifs.

Retour au sommaire
Qu'est ce que un Flow Controller ? 
0 vote
Par Jérôme Rocheteau le 04/12/2009 à 09:52

Ce billet explique ce qu'est un Flow Controller et illustre son utilité à travers l'exemple d'un Flow Controller qui se base sur le langage des CASes.

Un Flow Controller est un composant UIMA qui s'intègre dans un Aggregate Analysis Engine et qui, étant donné un CAS, définit quels sont ses sous Analysis Engines qui vont s'appliquer dessus et dans quel ordre.

En effet, un Aggregate Analysis Engine se définit uniquement par un descripteur XML. d'une part, en renseignant les sous Analysis Engines qui le composent et, d'autre part, en renseignant son Flow Controller. Par défaut, le Flow Controller utilisé se nomme Fixed Flow et consiste simplement à appliquer chaque Analysis Engine dans l'ordre spécifié par l'utilisateur dans le descripteur XML sur chaque CAS.

Un Flow Controller consiste, d'une part, à récupérer l'information sur les Analysis Engines qui compose l'Aggregate Analysis Engine et, d'autre part, à construire un Flow pour chaque CAS à traiter. Un Flow est un objet Java qui définit, à partir des informations collectées par le Flow Controller, quels sont les Analysis Engines qui vont traiter son CAS et ans quel ordre les traitements vont avoir lieu.Je prends l'exemple d'un Aggregate Analysis Engine dont les sous Analysis Engines effectuent une même sorte de traitement mais pour des langues différentes. Il peut s'agir de la traduction de textes en français. Cela suppose trois choses :

  • Nous suppsons que chaque CAS à traiter contient l'information de sa langue.
  • Nous supposons, tout d'abord, que cet Aggregate Analysis Engine se nomme FrenchTranslation et qu'il se compose de deux sous Analysis Engines English2French et German2French.
  • Nous supposons également que chacun de ses sous Analysis Engines possède un paramètre Language qui, dans le cas du sous Analysis Engine Engish2French, est fixé à la valeur "en" et, dans le cas de Greman2French, est fixé à "de". 
  • Nous supposons enfin que le Flow Controller de l'Aggregate Analysis Engine se nomme LanguageFlowController.

Le Flow Controller LanguageFlowController construit une liste d'association entre, d'une part, des langages et, d'autre part, l'identifiant du sous Analysis Engine qui traite ce langage. Pour cela, ce Flow Controller récupère de son contexte la liste des identifiants de chaque sous Analysis Engine. Pour chacun de ces sous Analysis Engines, il récupère de leus paramètres de configuration la valeur du paramètre Language qu'il ajoute alors dans la liste d'association des langages et des identifiant d'Analysis Engines. Enfin, ce Flow Controller construit un Flow par CAS en lui fournissant cette liste d'association des langages. En Java, cela donne :

public class LanguageFlowController extends JCasFlowController_ImplBase {

private Map<String,String> languages = new HashMa<String,String>();

public void initialize(FlowControllerContext context) throws ResourceInitializationException {
super.initialize(context);
Map<String,AnalysisEngineMetadata> map = context.getAnalysisEngineMetaDataMap();
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
String id = (String) iter.next();
AnalysisEngineMetaData md = map.get(id);
ConfigurationParameterSettings config = md.getConfigurationParameterSettings();
String language = (String) config.getParameterValue("Language");
this.languages.put(language,id);
}
}

public Flow computeFlow(JCas cas) throws AnalysisEngineProcessException {
LanguageFlow flow = new LanguageFlow(this.map);
flow.setJCas(cas);
return flow;
}
}

Le Flow construit se nomme LanguageFlow. Il consiste simplement à récupérer l'information du langage de chaque CAS et à rechercher dans la liste d'association qui lu a été fournie quel Analysis Engine traite cette langue. Si cette information existe, le Flow renvoie que le prochain traitement est effectué par le sous Analysis Engine qui correspond à l'identifiant associé au langage du CAS. Si cette information n'existe pas ou que le CAS a déjà été traduit, alors le Flow indique qu'il n'y a plus de traitement à effectuer sur son CAS. En Java, cela donne :

public class LanguageFlow extends JCasFlow_ImplBase {

private Map<String,String> languages;

private boolean done = false;

public LanguageFlow(Map<String,String> lang) {
this.languages = lang;;
}

public Step next() throws AnalysisEngineProcessException {
if (done) {
return new FinalStep();
} else {
JCas cas = this.getJCas();
String lang = cas.getDocumentLanguage();
String id = this.languages.get(lang);
if (id == null || id.isEmpty()) {
return new FinalStep();
} else {
done = true;
return new SimpleStep(id);
}
}
}
}

Il suffit alors de créer un descripteur XML de Flow Controller et de l'associer à la classe LanguageFlowController pour disposer d'un composant UIMA prêt à être intégré dans un Aggregate Analysis Engine qui puisse sélectionner le sous Analysis Engine qui correspond à la langue des CASes.

Retour au sommaire
Comment créer un projet UIMA sous Eclipse ? 
0 vote
Par Jérôme Rocheteau le 30/10/2009 à 12:52

Ce billet explique comment construire un projet sous Eclipse pour développer un composant UIMA avec Maven.

Il suffit de trois étapes pour créer un projet sous Eclipse pour un composant UIMA dont la gestion des dépendances et des phases de construction est déléguée à Maven.

Créer un projet Java sous Eclipse

Il faut tout d'abord créer un projet Java : File > New > Java Project. Il faut alors indiquer le nom du projet sous Eclipse. Cette opération créée :

  • un projet visible dans l'explorateur de projet
  • un répertoire source src
  • un ensemble de bibliothèques Java JRE System Library

Ajouter la nature UIMA au projet Eclipse

Il faut ensuite spécifier que le projet correspond à un composant UIMA : Project Right Click > Add UIMA Nature. Cette opération crée les répertoires conf, data, desc, doc, lib, metadata et resources.

Activer la gestion de dépendances avec Maven

Il faut finalement indiquer que Maven constitue le système de gestion de ce projet : Project Right Click > Maven > Enable Dependency Managment. Il faut alors indiquer :

  • l'identifiant du groupe de l'artéfact, par exemple fr.uima
  • l'identifiant de l'artéfact, par exemple generic-collection-reader
  • la version de l'artéfact, par exemple 0.1.0
  • le nom de l'artéfact, par exemple Generic Collection Reader
  • la description de l'artéfact, par exemple This is an Apache UIMA Collection Reader ...

Configurer Maven

Une telle opération crée un fichier pom.xml qui contient la configuration de Maven pour la gestion de ce projet et retire le répertoire src des répertoires source du projet. Pour que ce projet soit prêt pour développer un composant UIMA, il convient alors de modifier les fichier pom.xml :

en ajoutant l'artéfact qui correspond à la bibliothèque d'Apache UIMA
Dependencies > Dependencies > Add
  • groupId = org.apache.uima
  • artifactId = uimaj-core
  • version = 2.2.2-01-incubating
en ajoutant l'artéfact qui correspond aux outils d'Apache UIMA notamment pour la génération de classes Java à partir de descripteurs XML de Type Systems ainsi que pour l'utilisation des outils Document Analyzer, Annotation Viewer et Collection Processing Managment
Dependencies > Dependencies > Add
  • groupId = org.apache.uima
  • artifactId = uimaj-tools
  • version = 2.2.2-01-incubating
en spécifiant l'emplacement des répertoires source et binaire du projet
Build > Folders
  • Sources = src
  • Output = bin
en ajoutant successivement les répertoires desc et resources aux sources du projet
Build > Resources > Add
  • Directrory = desc
  • Directory = resources

Reconfigurer le projet Eclipse

Il faut alors spécifier que le répertoire src est un répertoire source du projet et que le répertoire bin en est le répertoire binaire étant donné que l'activation Maven les a respectivement remplacé par src/main/java et target/classes. Il faut également ajouter les répertoires desc et resources aux répertoires source du projet afin de rendre les descripteurs XML accessibles par nom. Cela s'effectue par le chemin Project > Properties > Java Build Path > Source :

  • en cochant les répertoires source via Add Folder...
  • en selectionnant le répertoire binaire via Browse...

Le billet « Comment configurer votre POM pour UIMA ? » explique comment configurer le fichier pom.xml à la main.

Retour au sommaire
Comment configurer Eclipse pour UIMA ? 
0 vote
Par Jérôme Rocheteau le 29/10/2009 à 13:43

Ce billet explique comment installer et configurer Eclipse pour utiliser et développer des composants UIMA.

Eclipse est un IDE (Integrated Development Environment) qui sert à la fois :

  • d'environnement d'utilisation des outils UIMA
  • d'environnement de développement de composants UIMA

Je conseille d'utiliser Eclipse Galileo 3.5 avec les greffons ci-dessous :

  • UIMA 2.2.2 — http://www.apache.org/dist/incubator/uima/eclipse-update-site
  • Subversion 1.6 — http://subclipse.tigris.org/update_1.6.x
  • Maven 2 — http://m2eclipse.sonatype.org/update

Il suffit d'installer ces greffons dans Eclipse en indiquant leurs URLs via Help > Install New Software... > Add

Attention : il est nécessaire d'avoir installé au préalable la plate-forme Apache UIMA à partir des sources de la version 2.2.2-incubating. La procédure à suivre est expliquée dans le billet « Comment installer UIMA ? ».

L'archive d'Eclipse Galileo 3.5.1 pour les développeurs Java avec les trois greffons ci-dessus est disponible dans la rubrique public/applications de ce site sous le nom « Eclipse pour UIMA » ou dans les annexes de ce billet.

Retour au sommaire
Comment installer TextMarker ? 
0 vote
Par Jérôme Rocheteau le 23/10/2009 à 15:19

Ce billet explique comment installer TextMarker un outil pour l'extraction d'information et l'analyse de textes. Cet outil s'intègre dans Eclipse et utilise notamment UIMA.

Pour installer TextMarker, il faut tout d'abord disposer :

  • de Java 1.6
  • d'Eclipse Galileo 3.5

Il faut ensuite installer automatiquement sous Eclipse les plugins suivants à l'aide du chemin Help / Install Sew Software .../ Add :

Mozilla XulRunner
http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/1.8.1.3/contrib/eclipse/site.xml
UIMA 2.2.2
http://www.apache.org/dist/incubator/uima/eclipse-update-site
DLTK
http://download.eclipse.org/technology/dltk/updates-dev/1.0/

Il faut enfin installer manuellement les plugins et les features distribués par TextMarker en trois étapes :

  • télécharger et décompresser l'archive ZIP de TextMarker
  • copier le contenu des répertoires features/ et plugins/ extraits de l'archive dans les répertoires homonymes d'Eclipse.
  • relancer Eclipse en ligne de commande avec l'option :
./eclipse -clean
Retour au sommaire
Comment récupérer les composants officiels UIMA ? 
0 vote
Par Jérôme Rocheteau le 16/10/2009 à 10:34

Ce billet explique comment récupérer les composants officiels UIMA de la Sandbox pour la version 2.2.2-incubating.

Pour récupérer les composants UIMA de la Sandbox pour la version 2.2.2-incubating, il faut disposer, d'une part, de Subversion et, d'autre part, de Maven 2. Il n'est normalement pas nécessaire que les archives Java pour la plate-forme UIMA soient installées dans le dépôt Maven local étant donné qu'elles sont récupérées lors de la compilation des composants de la Sandbox à partir d'un dépôt Maven distant.

Il suffit alors d'exécuter les commandes qui suivent :

svn checkout http://svn.apache.org/repos/asf/incubator/uima/sandbox/tags/sandbox-2.2.2/
cd sandbox-2.2.2/sandbox-2.2.2-incubating/SandboxDistr/
mvn compile

Les composants UIMA ci-dessous sont alors prêts à être utilisés dans vos chaînes de traitement. Il s'agit essentiellement de composants UIMA dédiés à l'analyse de textes :

  • WhitespaceTokenizer pour identifier les mots et les phrases d'un texte
  • SnowballAnnotator pour obtenir la racine des mots
  • RegularExpressionAnnotator pour rechercher des motifs dans un texte
  • Tagger pour effectuer une analyse morpho-syntaxique des mots d'un texte
  • DictionaryAnnotator pour associer le contenu de dictionnaires aux mots d'un texte
Retour au sommaire
Comment configurer votre POM pour UIMA ? 
0 vote
Par Jérôme Rocheteau le 25/09/2009 à 14:57

Ce billet explique comment configurer le Project Model Object (POM) pour votre composant UIMA. Il s'agit du descripteur XML pour les projets gérés avec Maven.

Les fichiers pom.xml fournissent à Maven les informations nécessaires pour la compilation, l'installation et le déploiement de composants Java, mais aussi de composants UIMA. C'est d'ailleurs cet outil qui est utilisé pour gérer les différents composants essentiels de la plate-forme UIMA ainsi que ceux du bac-à-sable.

L'identification de votre composant

La structure globale d'un fichier POM correspond à ceci :

<project 
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<modelVersion>4.0.0</modelVersion>
...
</project>

Il faut tout d'abord que vous renseigner l'identifiant de votre composant (ou artifact pour Maven), sa version, etc.

  <groupId>fr.uima</groupId>
<artifactId>your-uima-processing-engine-id</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
...

La déclaration des dépendances

Il faut ensuite déclarer les dépendances de votre composant UIMA. Notamment, il y a de grandes chances pour qu'elles aient les dépendances suivantes afin :

  • de générer les classes correspondantes aux types de Type Systems
  • de compiler les sources avec les importation de classes de la plate-forme UIMA
  <dependencies>
<!-- Required to generate the Java classes -->
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimaj-core</artifactId>
<version>2.2.2-incubating</version>
<scope>compile</scope>
</dependency>
<!-- Required to generate the Java sources from the XML descriptors -->
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimaj-tools</artifactId>
<version>2.2.2-incubating</version>
<scope>compile</scope>
</dependency>
<dependencies>
...

La configuration de la génération des sources et de la compilation

Il faut alors spécifier que les descripteurs XML sont des ressources du projet :

  <build>
<!-- The source directory is set to src/ instead of src/java/main/ -->
<sourceDirectory>src</sourceDirectory>
<!-- The Java class output directory is set to bin/ instead of taget/classes/ -->
<outputDirectory>bin</outputDirectory>
<!-- The desc/ directoriy is added to the project resources -->
<resources>
<resource>
<directory>desc</directory>
</resource>
</resources>
<plugins>
...
</plugins>
</build>

Il faut ensuite activer la génération des classes Java à partir ces descripteurs :

      <!-- The Java sources are generated from the XML desriptors in desc/ -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>org.apache.uima.tools.jcasgen.Jg</mainClass>
<arguments>
<argument>-jcasgeninput</argument>
<argument>${where.your.descriptor.is}</argument>
<argument>-jcasgenoutput</argument>
<argument>${project.build.sourceDirectory}</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
...

Il faut enfin éliminer les classes Java générées à partir des descripteurs XML lors du nettoyage du projet :

      <!-- Clean the Java files generated by JCasGen -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
<configuration>
<filesets>
<fileset>
<directory>${project.build.sourceDirectory}/${path.of.your.types}</directory>
<includes>
<include>*.class</include>
</includes>
<excludes>
<exclude>*.java</exclude>
</excludes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
Retour au sommaire
Page suivante »
Produit par le BilboPlanet CSS - Xhtml valide Dessiné par le BilboPlanet Retour au début