[Castore-commits] UnimarcException.java NONE 1.1
ExtractionUnimarc.java NONE 1.1
mathieu grimault
grimault-m at adullact1.hosting.cri74.org
Mar 5 Déc 12:21:48 CET 2006
Update of /cvsroot/castore/castore-core/src/java/fr/emn/castor/documents/metier/unimarc
In directory adullact1:/tmp/cvs-serv24436/src/java/fr/emn/castor/documents/metier/unimarc
Added Files:
UnimarcException.java ExtractionUnimarc.java
Log Message:
Intégration de l'import UNIMARC
--- NEW FILE: ExtractionUnimarc.java ---
/*
* $Id$
*
* Plateforme CASTORE
* CeCILL Copyright (C) 2005-2006 by EMN
* Made by
* Web site = http://www.emn.fr/castore
* Contact = Cédric Dumas, e-mail = Cedric.Dumas at emn.fr
*
* Version
*
* Ce logiciel est un programme informatique servant à créer une plateforme
* open-source de bibliothèque numérique XML pour Conserver, Valoriser et
* Diffuser le patrimoine documentaire de votre institut.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions de la
* licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur le site
* "http://www.cecill.info". En contrepartie de l'accessibilité au code source
* et des droits de copie, de modification et de redistribution accordés par
* cette licence, il n'est offert aux utilisateurs qu'une garantie limitée. Pour
* les mêmes raisons, seule une responsabilité restreinte pèse sur l'auteur du
* programme, le titulaire des droits patrimoniaux et les concédants successifs.
* A cet égard l'attention de l'utilisateur est attirée sur les risques associés
* au chargement, à l'utilisation, à la modification et/ou au développement et à
* la reproduction du logiciel par l'utilisateur étant donné sa spécificité de
* logiciel libre, qui peut le rendre complexe à manipuler et qui le réserve
* donc à des développeurs et des professionnels avertis possédant des
* connaissances informatiques approfondies. Les utilisateurs sont donc invités
* à charger et tester l'adéquation du logiciel à leurs besoins dans des
* conditions permettant d'assurer la sécurité de leurs systèmes et ou de leurs
* données et, plus généralement, à l'utiliser et l'exploiter dans les mêmes
* conditions de sécurité. Le fait que vous puissiez accéder à cet en-tête
* signifie que vous avez pris connaissance de la licence CeCILL, et que vous en
* avez accepté les termes.
*
*/
package fr.emn.castor.documents.metier.unimarc;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.marc4j.MarcReader;
import org.marc4j.MarcStreamReader;
import org.marc4j.converter.CharConverter;
import org.marc4j.converter.impl.Iso5426ToUnicode;
import org.marc4j.marc.ControlField;
import org.marc4j.marc.DataField;
import org.marc4j.marc.Record;
import org.marc4j.marc.Subfield;
import org.marc4j.marc.VariableField;
import fr.emn.castor.common.Constants;
import fr.emn.castor.documents.Fonds;
import fr.emn.castor.documents.metier.docGenerique.ParserNoticeException;
/**
* Extraction de métadonnées d'une notice UNIMARC vers la notice d'un document
* en cours de soumission.
* Le mapping est réalisé par l'adjonction d'informations dans le fichier
* contenant les informations de métadonnées pour un type de document
* (typeDoc/MD_XXX.xml).
*
* @author $Author$
* @version $Revision$
*
*/
public class ExtractionUnimarc {
/** Clef de la map stockant les infos issues de typeDoc/MD_XXX.xml */
private static String TAG_VALEUR = "valeur";
private static String TAG_REPETABLE = "repetable";
private static String TAG_SOUS_ZONE = "sous-zone";
private static String TAG_INDICE = "indice";
/** L'élément racine du fichier XML */
private Element racine;
/** L'enregistrement UNIMARC */
private Record enregistrement;
/** L'identifiant du document en cours de soumission */
private String idDoc;
/** le logger. */
private static Log log = LogFactory.getLog(ExtractionUnimarc.class);
/**
* Interface de conversion du format UNIMARC vers unicode.
* Il existe :
* AnselToUnicode, Iso5426ToUnicode, Iso6937ToUnicode
*/
private static CharConverter converter = new Iso5426ToUnicode();
/**
* Constructeur
* @param idDoc L'identifiant du document en cours de soumission
* @param unimarc Le fichier UNIMARC uploadé
* @throws UnimarcException En cas de pépin
*/
public ExtractionUnimarc(String idDoc, InputStream unimarc) throws UnimarcException {
this.idDoc = idDoc;
// Chargement du descriptif du type de document Castore
String docType =
Fonds.getInstance().getNoticeValue(idDoc, "type");
List fichiers =
Fonds.getInstance().searchFilesForMapping(docType);
if (log.isTraceEnabled()) {
log.trace(
"Fichiers de description XML trouvés pour le type de document " +
docType + ": " + fichiers
);
}
if (fichiers == null || fichiers.size() == 0) {
throw new UnimarcException(
"Aucun fichier de description trouvé pour le type de doc " + docType
);
}
SAXBuilder sxb = new SAXBuilder();
Document document = null;
try {
document =
sxb.build(
new File(Constants.CASTOR_TYPEDOC_PATH + "/" + fichiers.get(0))
);
} catch (JDOMException e) {
log.error(
"Erreur à la lecture du fichier MD_XXX.xml : \n" + e, e
);
throw new UnimarcException(
"Impossible de récupérer les métadonnées : erreur XML."
);
} catch (IOException e) {
log.error(
"Impossible de trouver le fichier MD_XXX.xml : \n" + e, e
);
throw new UnimarcException(
"Impossible de récupérer les métadonnées : erreur XML."
);
}
racine = document.getRootElement();
// Chargement de la notice UNIMARC
MarcReader reader = new MarcStreamReader(unimarc);
// On ne traite que le 1er enregistrement du fichier !
if (reader.hasNext()) {
enregistrement = reader.next();
} else {
throw new UnimarcException(
"Impossible de récupérer les métadonnées : \n " +
"Le fichier UNIMARC ne contient pas d'enregistrement."
);
}
}
/**
* Lancement de l'extraction des données UNIMARC vers la notice Castore
* @throws UnimarcException En cas de soucis
*/
public void extraire() throws UnimarcException {
try {
Map metadatas = new HashMap();
Map mappingsDCUnimarc = recupMappingsDCUnimarc();
Iterator i = mappingsDCUnimarc.keySet().iterator();
// Itération sur chaque champ DC ayant une correspondance UNIMARC
while (i.hasNext()) {
String nomDc = (String)i.next();
List zones = (List)mappingsDCUnimarc.get(nomDc);
if (log.isTraceEnabled()) {
log.trace("Traitement du champ DC " + nomDc);
}
// Itération sur chaque zone UNIMARC
Iterator zonator = zones.iterator();
while (zonator.hasNext()) {
Map zone = (Map)zonator.next();
List donnees =
recupMetadonnees(
(String)zone.get(TAG_VALEUR),
(String)zone.get(TAG_SOUS_ZONE),
(String)zone.get(TAG_INDICE),
Boolean.parseBoolean((String)zone.get(TAG_REPETABLE)),
!Fonds.getInstance().isMultipleMetadata(nomDc, idDoc)
);
if (donnees != null && donnees.size() > 0) {
if (log.isTraceEnabled()) {
log.trace(
"Injection des données dans le champ " +
nomDc + " :\n" +
donnees
);
}
if (Fonds.getInstance().isMultipleMetadata(nomDc, idDoc)) {
// cas dc multiple, on doit fournir une liste de valeurs
ajouterDonneesMetadatas(nomDc, metadatas, donnees, true);
} else {
// cas dc unique, on doit fournir une seule valeur
ajouterDonneesMetadatas(nomDc, metadatas, donnees, false);
}
}
}
}
// Injection des metadonnnées dans la notice du document
if (metadatas != null && metadatas.size() > 0) {
if (log.isTraceEnabled()) {
log.trace("Injection des données dans la notice...");
}
Fonds.getInstance().setMetaDatas(idDoc, metadatas, "unimarc");
}
} catch (ParserNoticeException e) {
log.error(
"Erreur à la lecture du fichier MD_XXX.xml : \n"+ e, e
);
throw new UnimarcException(
"Impossible de récupérer les métadonnées : erreur XML."
);
}
}
/**
* Ajoute les métadonnées à la liste des métadonnées récupérées.
* @param nomDc Le nom du champ Dublin Core en cours de traitement
* @param metadatas La liste des métadonnées récupérées
* @param donnees Les données à ajouter
* @param multiple Si le champ Dublin Core est unique (false) ou multiple (true)
*/
private void ajouterDonneesMetadatas(String nomDc, Map metadatas, List donnees, boolean multiple) {
if (metadatas.containsKey(nomDc)) {
if (multiple) {
List donneesPresentes = (List)metadatas.get(nomDc);
donneesPresentes.addAll((List)donnees);
metadatas.put(nomDc, donneesPresentes);
} else {
List donneesPresentes = (List)metadatas.get(nomDc);
String donneePresente = (String)donneesPresentes.get(0);
Iterator i = donnees.iterator();
while (i.hasNext()) {
donneePresente += " " + (String)i.next();
}
donneesPresentes.clear();
donneesPresentes.add(donneePresente);
metadatas.put(nomDc, donneesPresentes);
}
} else {
metadatas.put(nomDc, donnees);
}
}
/**
* Récupération des informations de mapping UNIMARC/Dublin Core
* mentionnées dans le fichier MD_XXX.xml
* @return Une Map conscienceusement remplie
*/
private Map recupMappingsDCUnimarc() {
Map mappingsDCUnimarc = new HashMap();
List metadatas = racine.getChildren("metadata");
Iterator i = metadatas.iterator();
// Boucle sur les metadata
while (i.hasNext()) {
Element metadata = (Element)i.next();
if (metadata.getChild("unimarc") != null) {
// un mapping est renseigné !
Element unimarc = metadata.getChild("unimarc");
List zones = unimarc.getChildren("zone");
Iterator zonator = zones.iterator();
// boucle sur les zones pour un champ DC
while (zonator.hasNext()) {
Element zone = (Element)zonator.next();
// Représentation du mapping indiqué dans le MD_XXX.xml
Map mappingZones = new HashMap();
mappingZones.put(TAG_VALEUR, zone.getTextNormalize());
mappingZones.put(TAG_REPETABLE, zone.getAttributeValue(TAG_REPETABLE));
if (zone.getAttribute(TAG_SOUS_ZONE) != null) {
mappingZones.put(TAG_SOUS_ZONE, zone.getAttributeValue(TAG_SOUS_ZONE));
}
if (zone.getAttribute(TAG_INDICE) != null) {
mappingZones.put(TAG_INDICE, zone.getAttributeValue(TAG_INDICE));
}
ajouterMapping(
mappingsDCUnimarc,
metadata.getChild("equivalent_dc").getTextNormalize(),
mappingZones
);
}
}
}
return mappingsDCUnimarc;
}
/**
* Ajoute le mapping fourni en paramètre à la liste des mappings déjà trouvés
* @param mappingsDCUnimarc les mappings déjà trouvés
* @param nomDC Le nom du champ Dublin Core en cours de traitement
* @param mappingZones Le mapping nouvellement trouvé
*/
private void ajouterMapping(Map mappingsDCUnimarc, String nomDC, Map mappingZones) {
List mappings = null;
if (mappingsDCUnimarc.get(nomDC) == null) {
// champ dc pas encore traité
mappings = new ArrayList();
} else {
// deja des infos de recupérées
mappings = (List)mappingsDCUnimarc.get(nomDC);
}
mappings.add(mappingZones);
mappingsDCUnimarc.put(nomDC, mappings);
}
/**
* Récupération des informations contenues dans le fichier UNIMARC
* @param etiquette L'étiquette de la zone à traiter
* @param sousZone Optionnel, la/les sous-zone(s) à traiter
* @param indice optionnel, l'indice de la zone si la zone est répétable et que ne veut que l'élément précisé [0,X]
* @param repetable Si la zone est répétable ou non
* @param concatener Si le champ Dublin Core est multiple (false) ou unique (true)
* @return une List de valeur avec plusieurs éléments (concatener=false) ou un seul (concatener=true)
*/
private List recupMetadonnees(String etiquette, String sousZone, String indice, boolean repetable, boolean concatener) {
List liste = new ArrayList();
if (repetable) {
// on doit traiter une liste de champs
List dfs = enregistrement.getVariableFields(etiquette);
if (dfs != null && dfs.size() > 0) {
if (concatener) {
String resultat = "";
Iterator i = dfs.iterator();
while (i.hasNext()) {
VariableField vf = (VariableField)i.next();
String zu = lireZoneUnimarc(vf, sousZone);
if (zu != null && zu.length() > 0) {
resultat += zu + " ";
}
}
resultat = resultat.trim();
if (!"".equals(resultat)) {
liste.add(resultat);
}
} else {
Iterator i = dfs.iterator();
while (i.hasNext()) {
VariableField vf = (VariableField)i.next();
String zu = lireZoneUnimarc(vf, sousZone);
if (zu != null && zu.length() > 0) {
liste.add(zu);
}
}
}
}
} else {
if (indice == null) {
// on veut une unique zone
VariableField vf = enregistrement.getVariableField(etiquette);
String zu = lireZoneUnimarc(vf, sousZone);
if (zu != null && zu.length() > 0) {
liste.add(zu);
}
} else {
// on veut une zone particuliere d'une zone repetable
List dfs = enregistrement.getVariableFields(etiquette);
if (dfs != null && dfs.size() >= (Integer.parseInt(indice)+1)) {
VariableField vf = (VariableField)dfs.get(Integer.parseInt(indice));
String zu = lireZoneUnimarc(vf, sousZone);
if (zu != null && zu.length() > 0) {
liste.add(zu);
}
}
}
}
return liste;
}
/**
* Retourne la valeur de la zone UNIMARC
* @param vf La zone Unimarc à lire
* @param sousZone optionnel, la/les sous-zone(s)
* @return La valeur débarassée des caractères spéciaux UNIMARC
*/
private String lireZoneUnimarc(VariableField vf, String sousZone) {
if (sousZone == null) {
// la zone est un champ de controle
ControlField cf = (ControlField)vf;
if (cf != null) {
return converter.convert(cf.getData());
}
return null;
} else {
// la zone est un champ de données
DataField df = (DataField)vf;
if (df != null) {
if (sousZone.length() > 1) {
// Il y a plusieurs sous-zones,
// on les concatène avec un espace séparateur
String s = "";
for (int i=0;i<sousZone.length();i++) {
Subfield sf = df.getSubfield(sousZone.charAt(i));
if (sf != null) {
s += converter.convert(sf.getData()) + " ";
}
}
s = s.trim();
if (!"".equals(s)) {
return s;
}
} else {
// il n'y a qu'une sous-zone à traiter
Subfield sf = df.getSubfield(sousZone.charAt(0));
if (sf != null) {
return converter.convert(sf.getData());
}
}
}
return null;
}
}
}
--- NEW FILE: UnimarcException.java ---
/*
* $Id$
*
* Plateforme CASTORE
* CeCILL Copyright (C) 2005-2006 by EMN
* Made by
* Web site = http://www.emn.fr/castore
* Contact = Cédric Dumas, e-mail = Cedric.Dumas at emn.fr
*
* Version
*
* Ce logiciel est un programme informatique servant à créer une plateforme
* open-source de bibliothèque numérique XML pour Conserver, Valoriser et
* Diffuser le patrimoine documentaire de votre institut.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions de la
* licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur le site
* "http://www.cecill.info". En contrepartie de l'accessibilité au code source
* et des droits de copie, de modification et de redistribution accordés par
* cette licence, il n'est offert aux utilisateurs qu'une garantie limitée. Pour
* les mêmes raisons, seule une responsabilité restreinte pèse sur l'auteur du
* programme, le titulaire des droits patrimoniaux et les concédants successifs.
* A cet égard l'attention de l'utilisateur est attirée sur les risques associés
* au chargement, à l'utilisation, à la modification et/ou au développement et à
* la reproduction du logiciel par l'utilisateur étant donné sa spécificité de
* logiciel libre, qui peut le rendre complexe à manipuler et qui le réserve
* donc à des développeurs et des professionnels avertis possédant des
* connaissances informatiques approfondies. Les utilisateurs sont donc invités
* à charger et tester l'adéquation du logiciel à leurs besoins dans des
* conditions permettant d'assurer la sécurité de leurs systèmes et ou de leurs
* données et, plus généralement, à l'utiliser et l'exploiter dans les mêmes
* conditions de sécurité. Le fait que vous puissiez accéder à cet en-tête
* signifie que vous avez pris connaissance de la licence CeCILL, et que vous en
* avez accepté les termes.
*
*/
package fr.emn.castor.documents.metier.unimarc;
/**
* Exception lancée lors de la manipulation UNIMARC
*
* @author $Author$
* @version $Revision$
*
*/
public class UnimarcException extends Exception {
/**
* Pour interface Serializable
*/
private static final long serialVersionUID = 1L;
/**
* Constructeur
* @param erreur Le message d'erreur
*/
public UnimarcException(String erreur) {
super(erreur);
}
}
Plus d'informations sur la liste de diffusion Castore-commits