-
Notifications
You must be signed in to change notification settings - Fork 7
Technical documentation
Technical documentation is available here
You will find here
- how to extend SITools2 REST API with applications, or dataset services, developping in java
- how to integrate your own GUI components, to view your data differently
- how to customize UI for portal, projects and others visual components
1 - Développement des extensions du serveur
_ 1.1 - Développement d'un filtre en entrée
_ 1.2 - Développement d’un convertisseur en sortie
Développement des extensions du serveurSITools2 possède un ensemble d’API permettant de construire différents plugins. Ces plugins permettent d’ajouter de nouvelles fonctionnalités ou bien de modifier certains comportements du serveur :
-
Le plugin « Filter » permet d’ajouter un filtre de requête qui va lire une signature dans une URL et la convertir en une partie de la requête SQL interrogeant le jeu de données,
-
Le plugin « Converter » permet d’appliquer une fonction de transfert sur des données requêtées et de fournir une réponse qui sera affichée dans la réponse du serveur,
-
Le plugin « Application » permet d’ajouter un nouveau comportement au serveur qui peut être indépendant d’un jeu de données ou d’un projet,
-
Le plugin « Resource » est une ressource synchrone ou asynchrone liée à un jeu de données. Elle permet de récupérer les données requêtées et d’effectuer diverses opérations ainsi que de retourner une réponse qui sera affichée par le serveur,
-
Le plugin « Security Filter » permet d’ajouter son propre mécanisme d’autorisation pour l’accès à la fonction « stockage » de l’OAIS.
-
Le plugin « Units » permet d’ajouter ses propres mécanismes de conversion d’unités. Ces mécanismes de conversions d’unités peuvent être ensuite utilisés dans les formulaires de requête de SITools2.
###Développement d’un filtre de requête en entrée -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Les filtres de requête permettent d’ajouter des contraintes lors d’une requête sur un jeu de données. Chaque filtre de requête peut ajouter des prédicats à la requête SQL qui va ensuite être exécuté par la base de données. Un filtre dispose d’un ensemble de paramètres en entrée, de paramètres internes (constantes) et de paramètres en sortie.
La création d’un filtre se résume à l’implémentation d’une classe Java retournant un ensemble de prédicats. Cette classe doit hériter de la classe AbstractFilter et implémenter la méthode createPredicats(Request request, ArrayList<Predicat> predicats) ainsi que getValidator(). Le squelette d’une telle classe est le suivant :
public class MyFilter extends AbstractFilter {
public BasicFilter() {
// méta données du filtre
// déclaration des paramètres de configuration
}
@ Override
public final ArrayList < Predicat > createPredicats(Request request, ArrayList < Predicat > predicats)throws Exception {
// récupération des paramètres de requêtes et de configuration
// création des prédicats
// retour de la liste des prédicats
}
@ Override
public Validator < AbstractFilter > getValidator() {
return new Validator < AbstractFilter > () {
@ Override
public Set < ConstraintViolation > validate(AbstractFilter item) {
// validation des paramètres de configuration
}
}
}
}
####Le constructeur
- Métadonnées du filtre
Le Constructeur possède un ensemble de métadonnées relatif au filtre, à savoir :
Métadonnées | Description | Méthodes à employer |
---|---|---|
L’auteur du filtre | L’auteur du filtre apparaît dans l’interface d’administration | setClassAuthor |
Le propriétaire du filtre | Le propriétaire du filtre apparaît dans l’interface d’administration | setClassOwner |
Le nom du filtre | Le nom du filtre apparaît dans l’interface d’administration | setName |
La description du filtre | La description du filtre apparaît dans l’interface d’administration | setDescription |
La version du filtre | La version du filtre apparaît dans l’interface d’administration. Une vérification entre la version du filtre configuré et la version du filtre provenant du JAR est effectuée. Un warning est affichée si les versions diffèrent. | setClassVersion |
- Paramétrage de configuration du filtre
Lors du développement d’un filtre, le développeur peut créer des paramètres de configuration qui seront saisis par l’administrateur du système. Pour cela il suffit d’instancier des objets FilterParameter(String name, String description, FilterParameterType type) et de les ajouter au filtre par l’utilisation de la méthode addParam(final FilterParameter param).
Lors de l’instanciation d’un objet FilterParameter, les paramètres suivants doivent être spécifiés :
Paramètre | Description |
---|---|
name | Nom du paramètre qui sera affiché dans l’interface d’administration pour la configuration du filtre |
description | Description du paramètre qui sera affiché dans l’interface d’administration |
filterParameterType | Type du paramètre entrainant un comportement différent dans l’IHM. Le type peut être soit INTERN ou IN. Un type INTERN est une constante que l’administrateur devra saisir dans l’IHM d’administration. Un type IN est un attribut du jeu de données que l’utilisateur devra choisir parmi la liste exposée dans l’IHM d’administration. |
- Notion de filtres par défaut
Les filtres sont actuellement le seul moyen d’enrichir l’API de recherche sur un jeu de données, et donc, de générer des prédicats à partir de paramètres d’une requête.
Les composants de formulaires, le filtrage sur les données dans le composant graphique tabulaire (« liveGrid ») utilisent des filtres pour générer des prédicats.
Afin de ne pas alourdir la gestion de l’administrateur, on a ajouté à un filtre la notion « par défaut ». Lors de la création d’un jeu de données, tous les filtres par défaut seront attachés automatiquement au nouveau jeu de données via un mécanisme de Trigger.
Un Filtre peut avoir deux constructeurs. Un par défaut, sans paramètre et obligatoire. Un autre avec un objet de type Context en paramètre. Dans cet objet Context, on peut retrouver le jeu de données en utilisant l’attribut « DATASET ». Ce constructeur permet d’avoir une liste de paramètres qui dépend du jeu de données et rend le filtre encore plus souple.
Cette méthode est exécutée lors de l’exécution du filtre.
Il faut tout d’abord récupérer l’ensemble des paramètres du filtre. Pour ce faire il faut utiliser les méthodes getParameterMap(), getInternParam(final String name).
Une fois les paramètres récupérés, il suffit de créer les prédicats voulus en fonction des attributs du jeu de données paramétrés et des constantes.
Dans cette méthode, on peut également récupérer certaines variables depuis le contexte. Ces variables sont SitoolsSettings (l’ensemble des propriétés du fichier sitools.properties) et la DataSetApplication.
Pour ce faire, il suffit de les récupérer dans les paramètres du contexte avec les clés : « DataSetApplication» et « ContextAttributes.SETTINGS » :
datasetApp = (DataSetApplication) getContext().getAttributes().get("DataSetApplication") ;
sitoolsSettings = (SitoolsSettings) getContext().getAttributes().get(ContextAttributes.SETTINGS ) ;
Depuis la DataSetApplication, il est possible d’obtenir une connexion à la base de données :
// recuperation complete du dataset
DataSet ds = datasetApp.getDataSet();
// recuperation d’une connexion à la source de données
Connection con = SitoolsDataSourceFactory.getInstance()
.getDataSource(ds.getDatasource().getName()).getConnection();
Où datasetApp est la DataSetApplication récupéré depuis le contexte.
- Prévention de l’injection SQL
Chaque filtre doit se prémunir contre l’injection SQL. Si les valeurs attendues sont numériques, il faut « caster » les valeurs attendues en double. Si les valeurs attendues sont des chaines alphanumériques, utiliser la méthode suivante :
String value = SQLUtils.quote(parameters\[VALUES\]);
Chaque développeur peut donc dans l’implémentation de son filtre définir le caractère par défaut de celui ci.
Les classes qui héritent de la classe abstraite AbstractFilter ont à leur disposition la méthode :
Double convert(String unitFromName, String unitToName, String valueFrom, String dimension);
qui renvoie la conversion d’une valeur (valueFrom) donnée dans une certaine unité (unitFromName) vers une autre unité (unitToName) en utilisant une dimension physique Sitools2 dont le nom est indiqué (dimension). Cette méthode peut donc être utilisée dans la méthode createPredicats(Request request, ArrayList<Predicat> predicats) afin de créer une requête cohérente en fonction de l’unité associée à un attribut d’un jeu de données. Cette méthode renvoie une exception ResourceException lorsque l’unité ou la dimension physique envoyée n’est pas reconnue. Un exemple de l’utilisation de cette méthode est visible dans la méthode checkValues du NumericBetweenFilter.
Les paramètres que l’administrateur a saisis peuvent être vérifiés par ce mécanisme de validation. Le squelette de la méthode est la suivante :
/**
* Gets the validator for this Filter
*
* @return the validator for the filter
*/
@ Override
public Validator < AbstractFilter > getValidator() {
return new Validator < AbstractFilter > () {
@ Override
public Set < ConstraintViolation > validate(AbstractFilter item) {
// TODO Auto-generated method stub
return null;
}
};
}
Deux états sont disponibles quand un problème de validation est détecté :
-
WARNING : un warning apparaît lors de la configuration du filtre par l’administrateur,
-
CRITICAL : un erreur critique apparaît lors de la configuration du filtre par l’administration. Dans ce cas, la configuration du filtre n’est pas sauvegardée
Il est important que l’API du filtre soit décrite pour permettre à des clients, autre que l’IHM de SITools2, de comprendre comment utiliser les filtres. Voici un exemple montrant comme décrire les paramètres du filtre pour un WADL. Ce code est à utiliser dans le constructeur :
HashMap < String, ParameterInfo > rpd = new HashMap < String, ParameterInfo > ();
ParameterInfo paramInfo;
paramInfo = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY, "CONE_SEARCH_CARTESIEN|columnAlias1,columnAlias2,columnAlias3|RA_value|DEC_value|SR_Value");
rpd.put("0", paramInfo);
paramInfo = new ParameterInfo("c[#]", false, "xs:string", ParameterStyle.QUERY, "CONE_SEARCH_CARTESIEN|dictionaryName,conceptName1,conceptName2,conceptName3|RA_value|DEC_value|SR_Value");
rpd.put("1", paramInfo);
this.setRequestParamsDescription(rpd);
NOTE : Il est aussi possible de décrire l’API en surchargeant la méthode *getRequestParamsDescription()*.
- Méthode avec Eclipse
Si vous utilisez Eclipse, et que vous avez récupérer l’ensemble des sources, l’ajout d’un convertisseur est très simple.
En effet, il suffit d’ajouter cette classe dans le projet extensions et d’ajouter le nom complet de la classe dans le fichier fr.cnes.sitools.converter.FilterHelper.
Il faut ensuite exécuter la tache Ant présente dans le projet extensions afin d’inclure la nouvelle classe dans la liste des extensions. Il faut également redémarrer Sitools2 pour prendre en compte le nouveau Jar.
- Méthode sans Eclipse
Dans le cas ou vous n’utilisez pas Eclipse, et que le projet extensions n’existe pas, il faut créer la bonne arborescence « à la main ».
Cette arborescence est tout de même assez simple. Il suffit d’avoir à la racine les dossiers contenant les sources ainsi qu’un dossier META-INF/services qui contient un fichier nommé fr.cnes.sitools.converter.FilterHelper dans lequel on place le nom des classes.
Il faut ensuite
-
Compiler les sources en ayant le jar de Sitools2 et de Restlet dans le classpath.
-
Créer un jar en incluant les classes compilées et le dossier META-INF/services.
-
Ajouter ce jar au classpath de Sitools2
####Gestion des logs
Il existe plusieurs méthodes pour récupérer un Logger dans Sitools2.
Via la classe Application :
Application application = getApplication()
Logger logger = application.getLogger();
Directement via la classe Logger :
Logger logger = Logger.getLogger(« nom de la classe courante »);
Via le Context :
Logger logger = Context.getLogger();
Ensuite pour utiliser le Logger :
logger.log(Level.INFO, "Message to log");
<a name="dev_convertisseur_sortie"/>
Développement d’un convertisseur en sortie
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Les convertisseurs peuvent être utilisés pour effectuer une conversion après l’exécution de la requête par la base de données. Il dispose d’un ensemble de paramètres en entrée, de paramètres internes (constantes) et de paramètres en sortie. Les attributs du jeu de données qui possèdent des convertisseurs doivent être sélectionnés comme non filtrable et non ordonnable puisque le convertisseur ne propose pas la conversion inverse.
#### Introduction
La création d’un convertisseur en sortie se résume à l’implémentation d’une classe Java effectuant un traitement sur les données en sortie.
Cette classe doit hériter de la classe *AbstractConverter* et implémenter la méthode *getConversionOf*
Le squelette d’une telle classe est le suivant :
```java
public class MyConverter extends AbstractConverter {
public LinearConverter() {
//initialisation des détails du convertisseur
//déclaration des paramètres
}
@ Override
public final Record getConversionOf(final Record rec)throws Exception {
//récupération des paramètres
//exécution du convertisseur
return rec.
}
@ Override
public Validator < AbstractConverter > getValidator() {
return new Validator < AbstractConverter > () {
@ Override
public Set < ConstraintViolation > validate(AbstractConverter item) {
// validation des paramètres
}
}
}
}
- Métadonnées du convertisseur
Le Constructeur possède un ensemble de métadonnées relatif au convertisseur, à savoir :
Métadonnées | Description | Méthodes à employer |
---|---|---|
L’auteur du convertisseur | L’auteur du convertisseur apparaît dans l’interface d’administration | setClassAuthor |
Le propriétaire du convertisseur | Le propriétaire du convertisseur apparaît dans l’interface d’administration | setClassOwner |
Le nom du convertisseur | Le nom du convertisseur apparaît dans l’interface d’administration | setName |
La description du convertisseur | La description du convertisseur apparaît dans l’interface d’administration | setDescription |
La version du convertisseur | La version du convertisseur apparaît dans l’interface d’administration. Une vérification entre la version du filtre configuré et la version du filtre provenant du JAR est effectuée. Un warning est affichée si les versions diffèrent. | setClassVersion |
- Paramétrage de configuration du convertisseur
Lors du développement d’un convertisseur, le développeur peut créer des paramètres de configuration qui seront saisis par l’administrateur du système. Pour cela il suffit d’instancier des objets ConverterParameter(String name, String description, ConverterParameterType type) et de les ajouter au convertisseur par l’utilisation de la méthode addParam(final ConverterParameter param).
Lors de l’instanciation d’un objet ConverterParameter, les paramètres suivants doivent être spécifiés :
Paramètre | Description |
---|---|
name | Nom du paramètre qui sera affiché dans l’interface d’administration pour la configuration du filtre |
description | Description du paramètre qui sera affiché dans l’interface d’administration |
converterParameterType | Type du paramètre entrainant un comportement différent dans l’IHM. Le type peut être soit INTERN, IN, OUT ou IN_OUT. Un type INTERN est une constante que l’administrateur devra saisir dans l’IHM d’administration. Un type IN est un attribut du jeu de données que l’utilisateur devra choisir parmi la liste exposée dans l’IHM d’administration. Un type OUT est un attribut du jeu de données (l’attribut pouvant être réel ou virtuel) dans lequel la réponse sera écrite. Un type IN_OUT est une fonction de transfert qui sera appliquée sur un attribut du jeu de données. |
Un Convertisseur peut avoir deux constructeurs :
-
Un par défaut, sans paramètre et obligatoire
-
Un autre avec un objet de type Context en paramètre. Dans cet objet Context, on peut retrouver le jeu de données en utilisant l’attribut « DATASET » dans l’objet Context. Ce constructeur permet d’avoir une liste de paramètres qui dépend du jeu de données et rend le filtre encore plus souple.
Cette méthode est exécutée lors de l’exécution du convertisseur.
Il faut tout d’abord récupérer l’ensemble des paramètres du convertisseur. Pour ce faire il faut utiliser les méthodes getInParam, getInternParam, getInOutParam et getOutParam de la classe AbstractConverter.
Une fois les paramètres récupérés il suffit d’effectuer les traitements voulus sur les données
Dans cette méthode, on peut également récupérer certaines variables depuis le contexte. Ces variables sont SitoolsSettings, DataSetApplication ainsi que la requête HTTP effectuée précédemment.
Pour ce faire, il suffit de les récupérer dans les paramètres du contexte avec les clés : « DataSetApplication» et « ContextAttributes.SETTINGS » et « REQUEST ».
Depuis la DataSetApplication, il est possible d’obtenir une connexion à la base de données :
// recuperation complete du dataset
DataSet ds = datasetApp.getDataSet();
// recuperation d’une connexion à la source de données
Connection con = SitoolsDataSourceFactory.getInstance()
.getDataSource(ds.getDatasource().getName()).getConnection();
Où datasetApp est la DataSetApplication récupéré depuis le contexte.
Dans le cas où une valeur nulle est retournée par le convertisseur, aucune conversion n’est réalisée.
Les paramètres que l’administrateur a saisis peuvent être vérifiés par ce mécanisme de validation. Le squelette de la méthode est la suivante :
/**
* Gets the validator for this Converter
*
* @return the validator for the converter
*/
@ Override
public Validator < AbstractConverter > getValidator() {
return new Validator < AbstractConverter > () {
@ Override
public Set < ConstraintViolation > validate(AbstractConverter item) {
// TODO Auto-generated method stub
return null;
}
};
}
Deux états sont disponibles quand un problème de validation est détecté :
-
WARNING : un warning apparaît lors de la configuration du filtre par l’administrateur,
-
CRITICAL : une erreur critique apparaît lors de la configuration du filtre par l’administration. Dans ce cas, la configuration du filtre n’est pas sauvegardée
- Méthode avec Eclipse
Si vous utilisez Eclipse, et que vous avez récupéré l’ensemble des sources, l’ajout d’un convertisseur est très simple.
En effet, il suffit d’ajouter cette classe dans le projet extensions et d’ajouter le nom complet de la classe dans le fichier fr.cnes.sitools.converter.ConverterHelper.
Il faut ensuite exécuter la tache Ant présente dans le projet extensions afin d’inclure la nouvelle classe dans la liste des extensions. Il faut également redémarrer Sitools2 pour prendre en compte le nouveau Jar.
- Méthode sans Eclipse
Dans le cas où vous n’utilisez pas Eclipse, et que le projet extensions n’existe pas, il faut créer la bonne arborescence « à la main ».
Cette arborescence est tout de même assez simple. Il suffit d’avoir à la racine les dossiers contenant les sources ainsi qu’un dossier META-INF/services qui contient un fichier nommé fr.cnes.sitools.converter.ConverterHelper dans lequel on place le nom des classes.
L’arborescence ressemble donc à ceci :
Il faut ensuite
-
Compiler les sources en ayant le jar de Sitools2 et de Restlet dans le classpath.
-
Créer un jar en incluant les classes compilées et le dossier META-INF/services.
-
Ajouter ce jar au classpath de Sitools2
Il existe plusieurs méthodes pour récupérer un Logger dans Sitools2.
Via la classe Application :
Application application = getApplication()
Logger logger = application.getLogger();
Directement via la classe Logger
Logger logger = Logger.getLogger(« nom de la classe courante »);
Via le Context :
Logger logger = Context.getLogger();
Ensuite pour utiliser le Logger :
logger.log(Level.INFO, "Message to log");