jeudi 28 août 2008

Java, Moteur de template : Freemarker

Voici un moteur de template efficace : Freemarker

Le concept et de concevoir un template (un modèle contenant des "variables") :
inputTemplate.ftl :
<html>
<head>
<title>les Contacts</title>
</head>
<body>
<div>
</div>
Les contacts de ${carnet.proprietaire.prenom} ${carnet.proprietaire.nom}
<div>
<table>
<tr>
<td>nom</td>
<td>prenom</td>
</tr>
<#list carnet.lesContacts as unContact>
<tr>
<td>${unContact.nom}</td>
<td>${unContact.prenom}</td>
</tr>
</#list>
</table>
</div>
</body>
</html>
Construire une structure objet contenant les valeurs des variables à remplacer dans le template :
  Map root = new HashMap();

/* structure agenda */
Map agenda = new HashMap();
root.put("carnet", agenda);

/* structure proprietaire (dans agenda) */
Map proprietaire = new HashMap();
agenda.put("proprietaire", proprietaire);

/* remplissage de la structure proprietaire */
proprietaire.put("nom", "Dupont");
proprietaire.put("prenom", "Jean");

/* structure contacts (dans agenda */
List lesContacts = new ArrayList();
agenda.put("lesContacts", lesContacts);

/* remplissage des contacts */
Map unContact = new HashMap();
lesContacts.add(unContact);
unContact.put("nom", "Bond");
unContact.put("prenom", "James");

unContact = new HashMap();
lesContacts.add(unContact);
unContact.put("nom", "Woman");
unContact.put("prenom", "Cat");
Fusionner le template et la structure objet dans un fichier de destination :
   InputStreamReader fileTemplate = new InputStreamReader(ClassLoader
.getSystemResourceAsStream("inputTemplate.ftl"));
Configuration cfg = new Configuration();
cfg.setObjectWrapper(new DefaultObjectWrapper());
Template temp = new Template("inputTemplate.ftl", fileTemplate, cfg);

Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
out.flush();
out.close();
C'est évidemment un exemple assez simple mais les possibilités offertes par Freemarker sont très larges.

Pour plus d'informations : http://freemarker.sourceforge.net/

mercredi 27 août 2008

Java: Scanner un répertoire

Dans la cadre du développement de plugin maven 2, récupérer un ensemble de fichier selon certains critères peut être intéressant :
- récupérer un sous ensemble de fichiers source java.
- récupérer un ensemble de properties.
- ...

Plexus est là! Cette librairie est déjà largement utilisée par les plugins maven 2.

La classe DirectoryScanner vous permettra de faire ça.
Il faut lui spécifier :
- un répertoire de base.
- des patterns d'inclusions et d'exclusions (en options) du style "**/**.properties".
puis appeler la méthode scan() et récupérer ensuite un tableau avec l'ensemble des chemins des fichiers correspondant à la recherche.

Pour plus d'informations, tout est dans la javadoc de la classe.

wonderfull!

jeudi 21 août 2008

requête XPath en java

Une solution simple (à mon goût) existe pour récupérer une valeur ou un attribut dans un fichier Xml en java sans avoir à le parcourir complètement avec Sax ou avec Dom.

Voici un petit exemple de mise en œuvre des APIS XPATH de java 1.5 s'appuyant sur Sax :

Voici le fichier XML source :
<?xml version="1.0" encoding="ISO-8859-1"?>
<level1>
<level2 level2-attribute1="valueOfLevel2-attribute1">
<level3 level3-attribute1="valueOfLevel3-attribute1">
<level41>valueOfLevel41</level41>
<level42>valueOfLevel42</level42>
</level3>
</level2>
</level1>
le code "technique" :

...
import java.io.InputStream;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;

...

public static String executeXpath(InputStream sourceXml, String xPathQuery)
throws XPathExpressionException {

// creation de la source sax
InputSource source = new InputSource(sourceXml);

// creation de la requete XPTAH
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath();
XPathExpression xPathExpression = xpath.compile(xPathQuery);

/* execution de la requete xPath sur le fichier XML */
String resultat = (String) xPathExpression.evaluate(source,
XPathConstants.STRING);

return resultat;

}
...
}
La mise en œuvre :

public static void main(String[] args) {

try {
/* recuperation du flux xml */

InputStream xml = null;
String result = null;
String xPathQuery = null;

/* exemple 1 */
xml = Main.class.getResourceAsStream("/fichier.xml");
xPathQuery = "/level1/level2/@level2-attribute1";
result = XpathHelper.executeXpath(xml, xPathQuery);

System.out.println("xpathQuery : " + xPathQuery
+ "---> resultat : " + result);

/* exemple 2 */
xml = Main.class.getResourceAsStream("/fichier.xml");
xPathQuery = "/level1/level2/level3/level41";
result = XpathHelper.executeXpath(xml, xPathQuery);

System.out.println("xpathQuery : " + xPathQuery
+ "---> resultat : " + result);
} catch (XPathExpressionException e) {
e.printStackTrace();
}

}


Le résultat en console :
xpathQuery : /level1/level2/@level2-attribute1---> resultat : valueOfLevel2-attribute1
xpathQuery : /level1/level2/level3/level41---> resultat : valueOfLevel41


Le tout a le mérite d'être assez simple, élégant et performant.