mardi 22 février 2011

J2EE : transformer du XML en une chaine

Tout d'abord, il faut initialiser un transformer et mettre l'option OMIT_XML_DECLARATION pour éviter la déclaration du XML :


tf = TransformerFactory.newInstance();
try {
c = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e1) {
logger.error("Erreur de configuration du builder XML", e1);
}
try {
transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
"yes");
} catch (TransformerConfigurationException e) {
logger.error("Erreur d'instantiation du transformer XML", e);
}


Et ensuite la transformation :


String htmlResult;
tf = TransformerFactory.newInstance();
DOMSource domSource = new DOMSource(d);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(domSource, result);
htmlResult = writer.toString();



Voici l'exemple complet :

package com.generic.description;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.generic.description.mapping.Element;
import com.generic.description.mapping.FieldDes;
import com.generic.front.Init;
import com.generic.link.LinkManager;
import com.generic.project.Project;
import com.generic.project.ProjectManager;
import com.generic.user.User;
import com.generic.util.ReloadablePropertyResourceBundle;

public class PostTraitementHelper {

private static PostTraitementHelper instance = null;

private static final Logger logger = Logger.getLogger(ProjectLoader.class);

private String directory = "";

private HashMap methodCache = new HashMap();

private TransformerFactory tf;

private Transformer transformer;

private DocumentBuilder c;

static {
// initialisation
ResourceBundle rb = ReloadablePropertyResourceBundle
.getResourceBundle(Init.PROP_GENERAL);
String dir = rb.getString(ProjectManager.PROPERTIES_SPECIFIQUES_DIR);
instance = new PostTraitementHelper();
instance.setDirectory(dir);
instance.initActionMap();
}

public static final String NONE = "none";
public static final String POSTTRAITEMENT_PROPERTIES = "posttraitement.properties";

private Map actionMap = new HashMap();
private long lastModification = 0L;

private PostTraitementHelper() {
super();

tf = TransformerFactory.newInstance();
try {
c = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e1) {
logger.error("Erreur de configuration du builder XML", e1);
}
try {
transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
"yes");
} catch (TransformerConfigurationException e) {
logger.error("Erreur d'instantiation du transformer XML", e);
}
}

public static PostTraitementHelper getInstance() {
return instance.initActionMap();
}

@SuppressWarnings("unchecked")
public synchronized PostTraitementHelper initActionMap() {
Date debut = new Date();

if (directory == null && "".equals(directory)) {
throw new IllegalArgumentException(String.format(
"l'argument [%s] est invalide", directory));
}

String pathFile = directory + "/"
+ PostTraitementHelper.POSTTRAITEMENT_PROPERTIES;

File f = null;
FileReader r = null;
try {
f = new File(pathFile);

if (f.exists() && f.canRead()) {
if (f.lastModified() > lastModification) {
// le fichier a changé et doit etre relu
lastModification = f.lastModified();

r = new FileReader(f);
Properties properties = new Properties();

if (logger.isDebugEnabled()) {
logger
.debug(String
.format(
"valeur de config du fichier [%s] sous forme [key]=[value]",
POSTTRAITEMENT_PROPERTIES));
}

try {
// lecture des cle
properties.load(r);

// nettoyage
this.actionMap.clear();
this.methodCache.clear();

// ajout du cas par defaut
this.actionMap.put(NONE, NONE);

// iteration et traitement de chaque cle
Enumeration keys = properties.keys();

while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = properties.getProperty(key, NONE);

if (!this.actionMap.containsKey(key)) {

try {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"[%s]=[%s] \n", key, value));
}
this.actionMap.put(key, value);
getActionMethod(key);
} catch (SecurityException e) {
logger.error(
"erreur lors de la reflection", e);
this.actionMap.remove(key);
} catch (NoSuchMethodException e) {
logger.error(
"erreur lors de la reflection", e);
this.actionMap.remove(key);
}
} else {
logger
.warn(String
.format(
"the following key [%s] exists in conf file [%s]",
key,
POSTTRAITEMENT_PROPERTIES));
}
}

} catch (IOException e) {
logger.error("I/O ERROR", e);
}
}
} else {
logger
.error(String
.format(
"Le fichier [%s] n'a pas les droits de lecture, les posts-traitements sont inutilisables",
POSTTRAITEMENT_PROPERTIES));
}

} catch (FileNotFoundException e1) {
logger.error("fichier introuvable", e1);
} finally {
if (logger.isDebugEnabled()) {
Date fin = new Date();
logger.debug(String.format(
"temps pour la lecture du fichier [%d] ms", fin
.getTime()
- debut.getTime()));
}

if (r != null) {
try {
r.close();
} catch (IOException e) {
logger.error("Echec de la fermeture du fichier", e);
}
}
}

return instance;
}

public Collection getActionList() {
return Collections.unmodifiableCollection(this.actionMap.values());
}

public Collection getChampsPostTraite() {
return Collections.unmodifiableCollection(this.actionMap.keySet());
}

public boolean isPostTraite(final String idChamp) {
if (actionMap.containsKey(idChamp)) {
return true;
} else {
return false;
}
}

/**
* methode pour le hmtl
* @param idChamp
* @return
*/
public String isPostTraiteToStr(final String idChamp) {
return isPostTraite(idChamp) == true ? "true" : "false";
}

public String getAction(String methodName) {
if (actionMap.containsKey(methodName)) {
return actionMap.get(methodName);
} else {
return NONE;
}
}

public void setDirectory(String directory) {
this.directory = directory;
}

public String getDirectory() {
return directory;
}

/**
* permets de retrouver une methode a invoquer, et declarer dans le fichier postraitement.properties
* @param fieldId est la cle a rechercher
* @return une methode a invoquer
* @throws SecurityException si une erreur se produit
* @throws NoSuchMethodException si une erreur se produit
*/
private synchronized Method getActionMethod(final String fieldId)
throws SecurityException, NoSuchMethodException {
Method m = null;
String nomMethod = getAction(fieldId);

if (!methodCache.containsKey(nomMethod)) {
// si pas dans le chache, on la cherche, et on l'ajoute
Class c = PostTraitementHelper.class;
m = c.getDeclaredMethod(nomMethod, Object[].class);
methodCache.put(nomMethod, m);
} else {
m = methodCache.get(nomMethod);
}

return m;
}

/**
* methode permettant l'invocation du methode par reflexion
* @param fieldId ID du champ HMTL
* @param params listes des parametres necessaires à l'application de la regle metier
* @return l'objet calcule a partir de la regle d'affichage
*/
public Object invokeActionMethod(final String fieldId, Object... params) {
Method m = null;
Object result = null;

try {
m = getActionMethod(fieldId);
result = m.invoke(this, new Object[] { params });

} catch (SecurityException e) {
logger.error("Reflection ERROR", e);
} catch (NoSuchMethodException e) {
logger.error("Reflection ERROR", e);
} catch (IllegalArgumentException e) {
logger.error("Reflection ERROR", e);
} catch (IllegalAccessException e) {
logger.error("Reflection ERROR", e);
} catch (InvocationTargetException e) {
logger.error("Reflection ERROR", e);
}
return result;
}

public FieldDes affichageCRAM(Object[] params) {
// recupe des params
Object o = params[0];
FieldDes fieldToChange = null;

if (o instanceof FieldDes) {
fieldToChange = (FieldDes) o;
}

// pas de cast c'est une interface
User u = (User) params[1];

o = params[2];
Project p = null;
if (o instanceof Project) {
p = (Project) o;
}

if (!LinkManager.isAdmin(p, u)) {
// le champ sdoit etre post traite et l'utilisateur n'est pas un
// profil admin
String login = u.getLogin();

Element[] elts = fieldToChange.getElement();

for (Element element : elts) {
if (element.getValue().equals(login)
|| element.getKey().equals(login)) {
Element[] newElts = new Element[1];
newElts[0] = element;
fieldToChange.setElement(newElts);
break;
}
}
}

return fieldToChange;
}

public String affichageCRAMParUser(Object[] params) {
// recupe des params
Object o = params[0];
String html = "";
String htmlResult = "";

if (o instanceof String) {
html = (String) o;
htmlResult = html;
}

// pas de cast c'est une interface
User u = (User) params[1];

o = params[2];
Project p = null;
if (o instanceof Project) {
p = (Project) o;
}

o = params[3];
String tagName = "*";
if (o instanceof String) {
tagName = (String) o;
}

o = params[4];
String idValue = "";
if (o instanceof String) {
idValue = (String) o;
}

if (!LinkManager.isAdmin(p, u)) {
// le champ sdoit etre post traite et l'utilisateur n'est pas un
// profil admin
String login = u.getLogin();

try {
htmlResult = parseXML(tagName, idValue, login, html);
} catch (TransformerException e) {
logger.error("erreur lors de la transformation XML", e);
} catch (ParserConfigurationException e) {
logger.error("erreur lors parsing XML", e);
} catch (SAXException e) {
logger.error("erreur SAX lors du parsing XML", e);
} catch (IOException e) {
logger.error("erreur I/O lors du parsing XML", e);
}
}
else
{
if(logger.isDebugEnabled())
{
logger.debug("cas d'un user admin, donc pas de modification de la liste d'option");
}
}

return htmlResult;
}

public String parseXML(final String tagName, final String idValue,
final String optionAGarder, final String html)
throws TransformerException, ParserConfigurationException,
SAXException, IOException {

String htmlResult = html;

List aSupprimer = new ArrayList();

Document d = c.parse(new InputSource(new StringReader(html)));
NodeList selects = d.getElementsByTagName(tagName);
boolean found = false;
Node select = null;

// si on a trouve au moins un selec avec id qui matche, on sort
for (int i = 0; i < selects.getLength() && found != true; i++) {
select = selects.item(i);
// on recherche un tag de type tagName et contentant un attribut id
// avec la valeur idValue
NamedNodeMap atts = select.getAttributes();
Node att = atts.getNamedItem("id");

if (att.getNodeValue().equals(idValue)) {
// un noeud a ete trouve
NodeList options = select.getChildNodes();
for (int j = 0; j < options.getLength(); j++) {
Node option = options.item(j);
NamedNodeMap child = option.getAttributes();
Node attChild = child.getNamedItem("value");

String valeur = attChild.getNodeValue();

if (valeur != null
&& !valeur.equalsIgnoreCase(optionAGarder)) {
aSupprimer.add(option);
} else {
if (option instanceof org.w3c.dom.Element) {
if(logger.isDebugEnabled())
{
logger.debug("OPTION trouvee = " + valeur);
}
org.w3c.dom.Element e = (org.w3c.dom.Element) option;
e.setAttribute("selected", "selected");
/*
* on considere que c'est bon si et on a trouve
* un noeud select, et avec id correspondant et
* une option qui correspond au login sinon, on
* renvoie tout
*/
found = true;
}
}
}
}
}

if (found && !aSupprimer.isEmpty()) {
// si on a trouve et qu'il y a des option a supprimer
nettoyageDOM(aSupprimer, select);
// on regenere la chaine
htmlResult = xml2String(d);
}
else
{
if(logger.isDebugEnabled())
{
logger.debug("OPTION non trouvee pour l'id = [" + idValue + "] et la valeur = [" + optionAGarder + "]");
}
}

return htmlResult;
}

private String xml2String(Document d)
throws TransformerFactoryConfigurationError,
TransformerConfigurationException, TransformerException {
String htmlResult;
tf = TransformerFactory.newInstance();
DOMSource domSource = new DOMSource(d);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(domSource, result);
htmlResult = writer.toString();
return htmlResult;
}

private void nettoyageDOM(List aSupprimer, Node select) {
for (Node supp : aSupprimer) {
select.removeChild(supp);
}
}

}

Aucun commentaire:

Enregistrer un commentaire