/*
 * LOMv1.java
 *
 */

package com.uvigo.tMaestro.SCOCreator.tool.metadataGenerator;

import java.io.File;
import java.util.HashMap;
import net.sf.vcard4j.java.VCard;
import org.ietf.mimedir.MimeDir;
import org.ietf.mimedir.impl.MimeDirImpl;
import org.ietf.mimedir.vcard.impl.VCardImpl;

/**
 * Esta clase se encarga de generar el fichero .xml de metadatos correspondiente
 * al estandar LOM en su versi�n 1.0.
 * @author raul
 * @version 0.1
 */
public class LOMv1 implements XmlGenerator {
    
    /**
     * M�todo encargado de escribir el fichero .xml con los metadatos indicados
     * al schema de metadatos de LOM v1.0
     */
    public void generateXMLFile(File oFile, HashMap<String, Object> oMetadata) throws Exception {
        
        //Como vamos a utilizar la libreria org.ieee.ltsc.lom para generar el fichero
        //es necesario indicarle a esta libreria donde se encuentra el fichero lom.xsd, ya que
        //si no lo encuentra localmente, lo intentara descargar desde la localizacion por defecto
        //que es internet (pagina del ieee). Para ello debemos establecer el valor de la propiedad
        //de sistema org.ieee.ltsc.lom.LOM.SchemaLocation a la localizacion en disco.
        System.setProperty("org.ieee.ltsc.lom.LOM.SchemaLocation",this.getClass().getResource("lom.xsd").toString());
        
        
        
        //Codigo que crea las estructuras intermedias que se utilizaron en la generacion del fichero .xml
        final org.ieee.ltsc.lom.impl.LOMImpl lom = new org.ieee.ltsc.lom.impl.LOMImpl();
        
        //Nivel "General""
        if (oMetadata.containsKey("general.identifier.catalog")) lom.newGeneral().newIdentifier(0).newCatalog().setString(oMetadata.get("general.identifier.catalog").toString());
        if (oMetadata.containsKey("general.identifier.entry")) lom.newGeneral().newIdentifier(0).newEntry().setString(oMetadata.get("general.identifier.entry").toString());
        if (oMetadata.containsKey("general.title")) lom.newGeneral().newTitle().newString(0).setString(oMetadata.get("general.title").toString());
        if (oMetadata.containsKey("general.language")) lom.newGeneral().newLanguage(0).setString(oMetadata.get("general.language").toString());
        if (oMetadata.containsKey("general.description")) lom.newGeneral().newDescription(0).newString(0).setString(oMetadata.get("general.description").toString());
        if (oMetadata.containsKey("general.keywords")) lom.newGeneral().newKeyword(0).newString(0).setString(oMetadata.get("general.keywords").toString());
        if (oMetadata.containsKey("general.coverage")) lom.newGeneral().newCoverage(0).newString(0).setString(oMetadata.get("general.coverage").toString());
        if (oMetadata.containsKey("general.structure.source")) lom.newGeneral().newStructure().newSource().setString(oMetadata.get("general.structure.source").toString());
        if (oMetadata.containsKey("general.structure.value")) lom.newGeneral().newStructure().newValue().setString(oMetadata.get("general.structure.value").toString());
        if (oMetadata.containsKey("general.aggregationLevel.source")) lom.newGeneral().newAggregationLevel().newSource().setString(oMetadata.get("general.aggregationLevel.source").toString());
        if (oMetadata.containsKey("general.aggregationLevel.value")) lom.newGeneral().newAggregationLevel().newValue().setString(oMetadata.get("general.aggregationLevel.value").toString());
        
        //Nivel "lifeCycle""
        if (oMetadata.containsKey("lifeCycle.version")) lom.newLifeCycle().newVersion().newString(0).setString(oMetadata.get("lifeCycle.version").toString());
        if (oMetadata.containsKey("lifeCycle.status.source")) lom.newLifeCycle().newStatus().newSource().setString(oMetadata.get("lifeCycle.status.source").toString());
        if (oMetadata.containsKey("lifeCycle.status.value")) lom.newLifeCycle().newStatus().newValue().setString(oMetadata.get("lifeCycle.status.value").toString());
        if (oMetadata.containsKey("lifeCycle.contribute.role.source")) lom.newLifeCycle().newContribute(0).newRole().newSource().setString(oMetadata.get("lifeCycle.contribute.role.source").toString());
        if (oMetadata.containsKey("lifeCycle.contribute.role.value")) lom.newLifeCycle().newContribute(0).newRole().newValue().setString(oMetadata.get("lifeCycle.contribute.role.value").toString());
        
        
        setVCard("lifeCycle.contribute",oMetadata,lom);
        setDate("lifeCycle.contribute",oMetadata,lom);
        if (oMetadata.containsKey("lifeCycle.contribute.date.description")) lom.newLifeCycle().newContribute(0).newDate().newDescription().newString(0).setString(oMetadata.get("lifeCycle.contribute.date.description").toString());
        
        //Nivel "metaMetadata"
        if (oMetadata.containsKey("metaMetadata.identifier.catalog")) lom.newMetaMetadata().newIdentifier(0).newCatalog().setString(oMetadata.get("metaMetadata.identifier.catalog").toString());
        if (oMetadata.containsKey("metaMetadata.identifier.entry")) lom.newMetaMetadata().newIdentifier(0).newEntry().setString(oMetadata.get("metaMetadata.identifier.entry").toString());
        if (oMetadata.containsKey("metaMetadata.contribute.role.source")) lom.newMetaMetadata().newContribute(0).newRole().newSource().setString(oMetadata.get("metaMetadata.contribute.role.source").toString());
        if (oMetadata.containsKey("metaMetadata.contribute.role.value")) lom.newMetaMetadata().newContribute(0).newRole().newValue().setString(oMetadata.get("metaMetadata.contribute.role.value").toString());
        
        setVCard("metaMetadata.contribute",oMetadata,lom);
        setDate("metaMetadata.contribute",oMetadata,lom);
        if (oMetadata.containsKey("metaMetadata.contribute.date.description")) lom.newMetaMetadata().newContribute(0).newDate().newDescription().newString(0).setString(oMetadata.get("metaMetadata.contribute.date.description").toString());
        if (oMetadata.containsKey("metaMetadata.metadataSchema")) lom.newMetaMetadata().newMetadataSchema(0).setString(oMetadata.get("metaMetadata.metadataSchema").toString());
        if (oMetadata.containsKey("metaMetadata.metadataSchema2")) lom.newMetaMetadata().newMetadataSchema(1).setString(oMetadata.get("metaMetadata.metadataSchema2").toString());
        if (oMetadata.containsKey("metaMetadata.metadataSchema3")) lom.newMetaMetadata().newMetadataSchema(2).setString(oMetadata.get("metaMetadata.metadataSchema3").toString());
        if (oMetadata.containsKey("metaMetadata.language")) lom.newMetaMetadata().newLanguage().setString(oMetadata.get("metaMetadata.language").toString());
        
        //Nivel "technical"
        if (oMetadata.containsKey("technical.format")) lom.newTechnical().newFormat(0).setString(oMetadata.get("technical.format").toString());
        if (oMetadata.containsKey("technical.size")) lom.newTechnical().newSize().setString(oMetadata.get("technical.size").toString());
        if (oMetadata.containsKey("technical.location")) lom.newTechnical().newLocation(0).setString(oMetadata.get("technical.location").toString());
        if (oMetadata.containsKey("technical.requirement.type.source")) lom.newTechnical().newRequirement(0).newOrComposite(0).newType().newSource().setString(oMetadata.get("technical.requirement.type.source").toString());
        if (oMetadata.containsKey("technical.requirement.type.value")) lom.newTechnical().newRequirement(0).newOrComposite(0).newType().newValue().setString(oMetadata.get("technical.requirement.type.value").toString());
        if (oMetadata.containsKey("technical.requirement.name.source")) lom.newTechnical().newRequirement(0).newOrComposite(0).newName().newSource().setString(oMetadata.get("technical.requirement.name.source").toString());
        if (oMetadata.containsKey("technical.requirement.name.value")) lom.newTechnical().newRequirement(0).newOrComposite(0).newName().newValue().setString(oMetadata.get("technical.requirement.name.value").toString());
        if (oMetadata.containsKey("technical.requirement.minimumVersion")) lom.newTechnical().newRequirement(0).newOrComposite(0).newMinimumVersion().setString(oMetadata.get("technical.requirement.minimumVersion").toString());
        if (oMetadata.containsKey("technical.requirement.maximumVersion")) lom.newTechnical().newRequirement(0).newOrComposite(0).newMaximumVersion().setString(oMetadata.get("technical.requirement.maximumVersion").toString());
        if (oMetadata.containsKey("technical.installationRemarks")) lom.newTechnical().newInstallationRemarks().newString(0).setString(oMetadata.get("technical.installationRemarks").toString());
        if (oMetadata.containsKey("technical.otherPlatformRequirements")) lom.newTechnical().newOtherPlatformRequirements().newString(0).setString(oMetadata.get("technical.otherPlatformRequirements").toString());
        setDuration("technical",oMetadata,lom);
        if (oMetadata.containsKey("technical.duration.description")) lom.newTechnical().newDuration().newDescription().newString(0).setString(oMetadata.get("technical.duration.description").toString());
        
        //Nivel "educational"
        if (oMetadata.containsKey("educational.interactivityType.source")) lom.newEducational(0).newInteractivityType().newSource().setString(oMetadata.get("educational.interactivityType.source").toString());
        if (oMetadata.containsKey("educational.interactivityType.value")) lom.newEducational(0).newInteractivityType().newValue().setString(oMetadata.get("educational.interactivityType.value").toString());
        if (oMetadata.containsKey("educational.learningResourceType.source")) lom.newEducational(0).newLearningResourceType(0).newSource().setString(oMetadata.get("educational.learningResourceType.source").toString());
        if (oMetadata.containsKey("educational.learningResourceType.value")) lom.newEducational(0).newLearningResourceType(0).newValue().setString(oMetadata.get("educational.learningResourceType.value").toString());
        if (oMetadata.containsKey("educational.interactivityLevel.source")) lom.newEducational(0).newInteractivityLevel().newSource().setString(oMetadata.get("educational.interactivityLevel.source").toString());
        if (oMetadata.containsKey("educational.interactivityLevel.value")) lom.newEducational(0).newInteractivityLevel().newValue().setString(oMetadata.get("educational.interactivityLevel.value").toString());
        if (oMetadata.containsKey("educational.semanticDensity.source")) lom.newEducational(0).newSemanticDensity().newSource().setString(oMetadata.get("educational.semanticDensity.source").toString());
        if (oMetadata.containsKey("educational.semanticDensity.value")) lom.newEducational(0).newSemanticDensity().newValue().setString(oMetadata.get("educational.semanticDensity.value").toString());
        if (oMetadata.containsKey("educational.intendedEndUserRol.source")) lom.newEducational(0).newIntendedEndUserRole(0).newSource().setString(oMetadata.get("educational.intendedEndUserRol.source").toString());
        if (oMetadata.containsKey("educational.intendedEndUserRol.value")) lom.newEducational(0).newIntendedEndUserRole(0).newValue().setString(oMetadata.get("educational.intendedEndUserRol.value").toString());
        if (oMetadata.containsKey("educational.context.source")) lom.newEducational(0).newContext(0).newSource().setString(oMetadata.get("educational.context.source").toString());
        if (oMetadata.containsKey("educational.context.value")) lom.newEducational(0).newContext(0).newValue().setString(oMetadata.get("educational.context.value").toString());
        if (oMetadata.containsKey("educational.difficulty.source")) lom.newEducational(0).newDifficulty().newSource().setString(oMetadata.get("educational.difficulty.source").toString());
        if (oMetadata.containsKey("educational.difficulty.value")) lom.newEducational(0).newDifficulty().newValue().setString(oMetadata.get("educational.difficulty.value").toString());
        if (oMetadata.containsKey("educational.typicalAgeRange")) lom.newEducational(0).newTypicalAgeRange(0).newString(0).setString(oMetadata.get("educational.typicalAgeRange").toString());
        //lom.newEducational().newDuration().newDurationValueInternal().getDurationImpl()
        //lom.newEducational().newDuration().newDurationDescriptionInternal();
        if (oMetadata.containsKey("educational.language")) lom.newEducational(0).newLanguage(0).setString(oMetadata.get("educational.language").toString());
        
        
        //Nivel "rights""
        if (oMetadata.containsKey("rights.cost.source")) lom.newRights().newCost().newSource().setString(oMetadata.get("rights.cost.source").toString());
        if (oMetadata.containsKey("rights.cost.value")) lom.newRights().newCost().newValue().setString(oMetadata.get("rights.cost.value").toString());
        if (oMetadata.containsKey("rights.copyrightAndOtherResctrictions.source")) lom.newRights().newCopyrightAndOtherRestrictions().newSource().setString(oMetadata.get("rights.copyrightAndOtherResctrictions.source").toString());
        if (oMetadata.containsKey("rights.copyrightAndOtherResctrictions.value")) lom.newRights().newCopyrightAndOtherRestrictions().newValue().setString(oMetadata.get("rights.copyrightAndOtherResctrictions.value").toString());
        if (oMetadata.containsKey("rights.description")) lom.newRights().newDescription().newString(0).setString(oMetadata.get("rights.description").toString());
        
        
        //Nivel "relation"
        if (oMetadata.containsKey("relation.kind.source")) lom.newRelation(0).newKind().newSource().setString(oMetadata.get("relation.kind.source").toString());
        if (oMetadata.containsKey("relation.kind.value")) lom.newRelation(0).newKind().newValue().setString(oMetadata.get("relation.kind.value").toString());
        if (oMetadata.containsKey("relation.resource.identifier.catalog")) lom.newRelation(0).newResource().newIdentifier(0).newCatalog().setString(oMetadata.get("relation.resource.identifier.catalog").toString());
        if (oMetadata.containsKey("relation.resource.identifier.entry")) lom.newRelation(0).newResource().newIdentifier(0).newEntry().setString(oMetadata.get("relation.resource.identifier.entry").toString());
        if (oMetadata.containsKey("relation.resource.description")) lom.newRelation(0).newResource().newDescription(0).newString(0).setString(oMetadata.get("relation.resource.description").toString());
        
        
        //Nivel "annotation"
        setVCard("annotation",oMetadata,lom);
        setDate("annotation",oMetadata,lom);
        if (oMetadata.containsKey("annotation.date.description")) lom.newAnnotation(0).newDate().newDescription().newString(0).setString(oMetadata.get("annotation.date.description").toString());
        
        
        //Nivel "classification"
        if (oMetadata.containsKey("classification.purpose.source")) lom.newClassification(0).newPurpose().newSource().setString(oMetadata.get("classification.purpose.source").toString());
        if (oMetadata.containsKey("classification.purpose.value")) lom.newClassification(0).newPurpose().newValue().setString(oMetadata.get("classification.purpose.value").toString());
        if (oMetadata.containsKey("classification.taxonPath.source")) lom.newClassification(0).newTaxonPath(0).newSource().newString(0).setString(oMetadata.get("classification.taxonPath.source").toString());
        if (oMetadata.containsKey("classification.taxonPath.taxon.id")) lom.newClassification(0).newTaxonPath(0).newTaxon(0).newId().setString(oMetadata.get("classification.taxonPath.taxon.id").toString());
        if (oMetadata.containsKey("classification.taxonPath.taxon.entry")) lom.newClassification(0).newTaxonPath(0).newTaxon(0).newEntry().newString(0).setString(oMetadata.get("classification.taxonPath.taxon.entry").toString());
        if (oMetadata.containsKey("classification.description")) lom.newClassification(0).newDescription().newString(0).setString(oMetadata.get("classification.description").toString());
        if (oMetadata.containsKey("classification.keyword")) lom.newClassification(0).newKeyword(0).newString(0).setString(oMetadata.get("classification.keyword").toString());
        
        
        //Codigo para escribir el fichero .xml
        //-----------------------------------------------------------------------------------------------
        final javax.xml.bind.JAXBContext jaxbContext = javax.xml.bind.JAXBContext.newInstance("org.ieee.ltsc.lom.jaxb.lomxml");
        final javax.xml.bind.Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(lom, new java.io.FileOutputStream(oFile));
    }
    
    
    /**
     * Este metodo lee y procesa los campos correspondientes al elemento fecha presente en diferentes
     * categorias del formulario
     */
    private void setDate(String sPrefix,HashMap<String,Object> oMetadata,org.ieee.ltsc.lom.impl.LOMImpl lom) {
        try {
            String sDate = oMetadata.get(sPrefix+".date.year---")+"-"+oMetadata.get(sPrefix+".date.month---")
            +"-"+oMetadata.get(sPrefix+".date.day")+"T"+oMetadata.get(sPrefix+".date.hour---")
            +":"+oMetadata.get(sPrefix+".date.minutes---")+":"+oMetadata.get(sPrefix+".date.seconds")
            +"."+oMetadata.get(sPrefix+".date.fraction---")+oMetadata.get(sPrefix+".date.tzd---")+oMetadata.get(sPrefix+".date.hh---")+":"+oMetadata.get(sPrefix+".date.mm");
            java.util.Date oDate=org.ieee.ltsc.datatype.impl.DateTimeImpl.parseISO8601DateTime(sDate);
            if (sPrefix.contains("lifeCycle")) lom.newLifeCycle().newContribute(0).newDate().newValue().setDateTime(oDate);
            else if (sPrefix.contains("metaMetadata")) lom.newMetaMetadata().newContribute(0).newDate().newValue().setDateTime(oDate);
            else if (sPrefix.contains("annotation")) lom.newAnnotation(0).newDate().newValue().setDateTime(oDate);
        } catch(Exception oE) {};
    }
    
    /**
     * Este metodo lee y procesa los campos correspondientes al elemento fecha presente en diferentes
     * categorias del formulario
     */
    private void setDuration(String sPrefix,HashMap<String,Object> oMetadata,org.ieee.ltsc.lom.impl.LOMImpl lom) {
        try {
            String sDuration = "P"+oMetadata.get(sPrefix+".duration.years---")+"Y"+oMetadata.get(sPrefix+".duration.months---")
            +"M"+oMetadata.get(sPrefix+".duration.days")+"DT"+oMetadata.get(sPrefix+".duration.hours---")
            +"H"+oMetadata.get(sPrefix+".duration.minutes---")+"M"+oMetadata.get(sPrefix+".duration.seconds")+"S";
            long lDuration=org.ieee.ltsc.datatype.impl.DurationImpl.parseDuration(sDuration);
            if (sPrefix.contains("technical")) lom.newTechnical().newDuration().newValue().setDuration(lDuration);
        } catch(Exception oE) {
            //oE.printStackTrace();
        };
    }
    
    
    /**
     * Este metodo lee y procesa los campos correspondientes al elemento VCard presente en diferentes categorias
     * del formulario
     */
    private void setVCard(String sPrefix,HashMap<String,Object> oMetadata,org.ieee.ltsc.lom.impl.LOMImpl lom) {
        final MimeDir.ContentLine fn = new MimeDirImpl.ContentLine(null, "FN", null, new MimeDirImpl.TextValueType(new String[] {oMetadata.get(sPrefix+".entity.givenName---")+" "+oMetadata.get(sPrefix+".entity.familyName---")}));
        final MimeDir.TextValueType familyName = new MimeDirImpl.TextValueType(new String[] {(String)oMetadata.get(sPrefix+".entity.familyName---")});
        final MimeDir.TextValueType givenName = new MimeDirImpl.TextValueType(new String[] {(String)oMetadata.get(sPrefix+".entity.givenName---")});
        final MimeDir.ContentLine n = new MimeDirImpl.ContentLine(null, "N", null, new VCardImpl.StructuredValueType(new MimeDir.ListValueType[] { familyName, givenName }));
        final MimeDir.ContentLine version = new MimeDirImpl.ContentLine(null, "VERSION", null, new MimeDirImpl.TextValueType(new String[] {(String)oMetadata.get(sPrefix+".entity.version---")}));
        VCardImpl oCard= new VCardImpl(new MimeDir.ContentLine[] { fn, n, version });
        if (oMetadata.get(sPrefix+".entity.givenName---")==null || oMetadata.get(sPrefix+".entity.familyName---")==null || oMetadata.get(sPrefix+".entity.version---")==null) return;
        if (sPrefix.contains("lifeCycle")) lom.newLifeCycle().newContribute(0).newEntity(0).setVCard(oCard);
        else if (sPrefix.contains("metaMetadata")) lom.newMetaMetadata().newContribute(0).newEntity(0).setVCard(oCard);
        else if (sPrefix.contains("annotation")) lom.newAnnotation(0).newEntity().setVCard(oCard);
    }
    
    
}
