Index: main/plugin-odf-sync/plugin.xml =================================================================== --- main/plugin-odf-sync/plugin.xml (revision 16240) +++ main/plugin-odf-sync/plugin.xml (working copy) @@ -20,8 +20,20 @@ xsi:schemaLocation="http://www.ametys.org/schema/plugin http://www.ametys.org/schema/plugin-2.0.xsd http://www.ametys.org/schema/cms http://www.ametys.org/schema/cms-3.0.xsd" runtimeVersion="2.0" version="2.0"> + + <config> + <param type="string" id="odf.cdmfr.search.repository"> + <label i18n="true">PLUGINS_ODF_CDMFR_FOLDER</label> + <description i18n="true">PLUGINS_ODF_CDMFR_FOLDER_DESC</description> + <category i18n="true">plugin.odf:PLUGINS_ODF_CONFIG_CATEGORY</category> + <group i18n="true">plugin.odf:PLUGINS_ODF_CONSTANTS_CONFIG_GROUP</group> + </param> + </config> <extension-points> + <extension-point id="org.ametys.plugins.odfsync.cdmfr.CDMFrSyncExtensionPoint" + class="org.ametys.plugins.odfsync.cdmfr.CDMFrSyncExtensionPoint"/> + <single-extension-point id="org.ametys.plugins.odfsync.ODFSyncManager" class="org.ametys.plugins.odfsync.ODFSyncManager" default-extension-id="org.ametys.plugins.odfsync.cdmfr.CDMFrODFSyncManager"/> @@ -30,14 +42,14 @@ class="org.ametys.plugins.odfsync.person.PersonsImportManager" default-extension-id="org.ametys.plugins.odfsync.person.LdapPersonImportManager"/> </extension-points> - + <feature name="workflow"> <components> <component class="org.ametys.plugins.odfsync.workflow.ValidateContentAfterSynchroFunction" role="org.ametys.plugins.odfsync.workflow.ValidateContentAfterSynchroFunction"/> </components> </feature> - + <!-- + | Apogee implementation + --> @@ -140,32 +152,25 @@ | CDM-fr implementation + --> <feature name="synchronization.cdm-fr"> - <config> - <param type="string" id="odf.cdmfr.search.repository"> - <label i18n="true">PLUGINS_ODF_CDMFR_FOLDER</label> - <description i18n="true">PLUGINS_ODF_CDMFR_FOLDER_DESC</description> - <category i18n="true">plugin.odf:PLUGINS_ODF_CONFIG_CATEGORY</category> - <group i18n="true">plugin.odf:PLUGINS_ODF_CONSTANTS_CONFIG_GROUP</group> - </param> - </config> - + <config> + <param-ref id="odf.cdmfr.search.repository"/> + </config> + <components> <component class="org.ametys.plugins.odfsync.cdmfr.CDMFrImportManager" role="org.ametys.plugins.odfsync.cdmfr.CDMFrImportManager"> - <xsl-transform>plugin:odf-sync://pages/cdmfr2content.xsl</xsl-transform> - <program-workflow-name>program</program-workflow-name> - <course-workflow-name>course</course-workflow-name> - <orgunit-workflow-name>orgunit</orgunit-workflow-name> - <person-workflow-name>person</person-workflow-name> + <program-workflow-name>program</program-workflow-name> + <course-workflow-name>course</course-workflow-name> + <orgunit-workflow-name>orgunit</orgunit-workflow-name> + <person-workflow-name>person</person-workflow-name> </component> <component class="org.ametys.plugins.odfsync.cdmfr.CDMFrSynchronizationManager" role="org.ametys.plugins.odfsync.cdmfr.CDMFrSynchronizationManager"> - <xsl-transform>plugin:odf-sync://pages/cdmfr2content.xsl</xsl-transform> - <program-workflow-name>program</program-workflow-name> - <course-workflow-name>course</course-workflow-name> - <orgunit-workflow-name>orgunit</orgunit-workflow-name> - <person-workflow-name>person</person-workflow-name> + <program-workflow-name>program</program-workflow-name> + <course-workflow-name>course</course-workflow-name> + <orgunit-workflow-name>orgunit</orgunit-workflow-name> + <person-workflow-name>person</person-workflow-name> </component> </components> @@ -175,31 +180,38 @@ class="org.ametys.plugins.odfsync.cdmfr.CDMFrODFSyncManager"> </extension> </extensions> - </feature> + </feature> <!-- + - | ROF implementation + | Global CDM-fr implementation + --> - <feature name="synchronization.rof"> + <feature name="synchronization.cdm-fr.global"> <config> - <param-ref id="odf.cdmfr.search.repository"/> - </config> - + <param-ref id="odf.cdmfr.search.repository"/> + </config> + <components> <component class="org.ametys.plugins.odfsync.cdmfr.CDMFrImportManager" role="org.ametys.plugins.odfsync.cdmfr.CDMFrImportManager"> + <program-workflow-name>program</program-workflow-name> + <course-workflow-name>course</course-workflow-name> + <orgunit-workflow-name>orgunit</orgunit-workflow-name> + <person-workflow-name>person</person-workflow-name> </component> - - <component class="org.ametys.plugins.odfsync.cdmfr.CDMFrSynchronizationManager" - role="org.ametys.plugins.odfsync.cdmfr.CDMFrSynchronizationManager"> - <xsl-transform>plugin:odf-sync://pages/rof2content.xsl</xsl-transform> + + <component class="org.ametys.plugins.odfsync.cdmfr.GlobalCDMFrSynchronizationManager" + role="org.ametys.plugins.odfsync.cdmfr.GlobalCDMFrSynchronizationManager"> + <program-workflow-name>program</program-workflow-name> + <course-workflow-name>course</course-workflow-name> + <orgunit-workflow-name>orgunit</orgunit-workflow-name> + <person-workflow-name>person</person-workflow-name> </component> </components> <extensions> - <extension point="org.ametys.plugins.odfsync.ODFSyncManager" - id="org.ametys.plugins.odfsync.cdmfr.ROFODFSyncManager" - class="org.ametys.plugins.odfsync.cdmfr.CDMFrODFSyncManager"> + <extension point="org.ametys.plugins.odfsync.ODFSyncManager" + id="org.ametys.plugins.odfsync.cdmfr.GlobalCDMFrODFSyncManager" + class="org.ametys.plugins.odfsync.cdmfr.GlobalCDMFrODFSyncManager"> </extension> </extensions> </feature> @@ -207,7 +219,7 @@ <!-- + | Remote CDM-fr implementation + --> - <feature name="synchronization.remote.cdm-fr"> + <feature name="synchronization.cdm-fr.remote"> <config> <param-ref id="odf.cdmfr.search.repository"/> </config> @@ -215,7 +227,10 @@ <components> <component class="org.ametys.plugins.odfsync.cdmfr.RemoteCDMFRImportManager" role="org.ametys.plugins.odfsync.cdmfr.RemoteCDMFRImportManager"> - <xsl-transform>plugin:odf-sync://pages/cdmfr2content.xsl</xsl-transform> + <program-workflow-name>program</program-workflow-name> + <course-workflow-name>course</course-workflow-name> + <orgunit-workflow-name>orgunit</orgunit-workflow-name> + <person-workflow-name>person</person-workflow-name> </component> </components> @@ -228,6 +243,39 @@ </feature> <!-- + + | Ametys implementation + + --> + <feature name="synchronization.ametys"> + <extensions> + <extension point="org.ametys.plugins.odfsync.cdmfr.CDMFrSyncExtensionPoint" + id="org.ametys.plugins.odfsync.cdmfr.Ametys3ODFSyncManager" + class="org.ametys.plugins.odfsync.cdmfr.transformers.DefaultCDMFrSyncTransformer"> + <app>Ametys v3</app> + <configuration> + <xsl-transform>plugin:odf-sync://pages/cdmfr2content.xsl</xsl-transform> + </configuration> + </extension> + </extensions> + </feature> + + <!-- + + | ROF implementation + + --> + <feature name="synchronization.rof"> + <extensions> + <extension point="org.ametys.plugins.odfsync.cdmfr.CDMFrSyncExtensionPoint" + id="org.ametys.plugins.odfsync.cdmfr.ROF13ODFSyncManager" + class="org.ametys.plugins.odfsync.cdmfr.transformers.DefaultCDMFrSyncTransformer"> + <app>ROF 1.25</app> + <app>ROF 1.30</app> + <configuration> + <xsl-transform>plugin:odf-sync://pages/rof2content.xsl</xsl-transform> + </configuration> + </extension> + </extensions> + </feature> + + <!-- + | WIDGETS + --> <feature name="widget"> Index: main/plugin-odf-sync/doc/workflow/workflow-person.xml =================================================================== --- main/plugin-odf-sync/doc/workflow/workflow-person.xml (revision 16249) +++ main/plugin-odf-sync/doc/workflow/workflow-person.xml (working copy) @@ -178,7 +178,7 @@ </actions> <post-functions> <function type="avalon"> - <arg name="role">org.ametys.web.workflow.ValidationStepFunction</arg> + <arg name="role">org.ametys.cms.workflow.ValidationStepFunction</arg> </function> </post-functions> </step> Index: main/plugin-odf-sync/doc/workflow/workflow-course.xml =================================================================== --- main/plugin-odf-sync/doc/workflow/workflow-course.xml (revision 16249) +++ main/plugin-odf-sync/doc/workflow/workflow-course.xml (working copy) @@ -301,7 +301,7 @@ </actions> <post-functions> <function type="avalon"> - <arg name="role">org.ametys.web.workflow.ValidationStepFunction</arg> + <arg name="role">org.ametys.cms.workflow.ValidationStepFunction</arg> </function> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.CommentStepFunction</arg> Index: main/plugin-odf-sync/doc/workflow/workflow-orgunit.xml =================================================================== --- main/plugin-odf-sync/doc/workflow/workflow-orgunit.xml (revision 16249) +++ main/plugin-odf-sync/doc/workflow/workflow-orgunit.xml (working copy) @@ -257,7 +257,7 @@ </actions> <post-functions> <function type="avalon"> - <arg name="role">org.ametys.web.workflow.ValidationStepFunction</arg> + <arg name="role">org.ametys.cms.workflow.ValidationStepFunction</arg> </function> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.CommentStepFunction</arg> Index: main/plugin-odf-sync/doc/workflow/workflow-program-publication.xml =================================================================== --- main/plugin-odf-sync/doc/workflow/workflow-program-publication.xml (revision 16249) +++ main/plugin-odf-sync/doc/workflow/workflow-program-publication.xml (working copy) @@ -431,7 +431,7 @@ </actions> <post-functions> <function type="avalon"> - <arg name="role">org.ametys.web.workflow.ValidationStepFunction</arg> + <arg name="role">org.ametys.cms.workflow.ValidationStepFunction</arg> </function> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.CommentStepFunction</arg> Index: main/plugin-odf-sync/doc/workflow/workflow-program.xml =================================================================== --- main/plugin-odf-sync/doc/workflow/workflow-program.xml (revision 16249) +++ main/plugin-odf-sync/doc/workflow/workflow-program.xml (working copy) @@ -391,7 +391,7 @@ </actions> <post-functions> <function type="avalon"> - <arg name="role">org.ametys.web.workflow.ValidationStepFunction</arg> + <arg name="role">org.ametys.cms.workflow.ValidationStepFunction</arg> </function> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.CommentStepFunction</arg> Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/AbstractCDMFrManager.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/AbstractCDMFrManager.java (revision 16249) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/AbstractCDMFrManager.java (working copy) @@ -15,6 +15,8 @@ */ package org.ametys.plugins.odfsync.cdmfr; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -28,12 +30,13 @@ import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; -import org.apache.excalibur.source.SourceResolver; +import org.apache.cocoon.ProcessingException; import org.apache.excalibur.xml.dom.DOMParser; import org.apache.excalibur.xml.xpath.XPathProcessor; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; import org.ametys.cms.observation.Event; import org.ametys.cms.observation.ObservationConstants; @@ -60,6 +63,7 @@ import org.ametys.odf.program.SubProgramFactory; import org.ametys.odf.workflow.CreateODFContentFunction; import org.ametys.plugins.odfsync.SynchronizationReport; +import org.ametys.plugins.odfsync.cdmfr.transformers.CDMFrSyncTransformer; import org.ametys.plugins.repository.AmetysObject; import org.ametys.plugins.repository.AmetysObjectIterable; import org.ametys.plugins.repository.AmetysObjectResolver; @@ -70,6 +74,7 @@ import org.ametys.plugins.repository.query.expression.Expression.Operator; import org.ametys.plugins.repository.version.VersionableAmetysObject; import org.ametys.plugins.workflow.Workflow; +import org.ametys.runtime.config.Config; import org.ametys.runtime.user.CurrentUserProvider; import com.opensymphony.workflow.WorkflowException; @@ -90,15 +95,12 @@ protected OdfConstantsProvider _provider; /** The DOM parser. */ protected DOMParser _domParser; - /** Ametys object resolver. */ - protected SourceResolver _sourceResolver; /** Observer manager. */ protected ObservationManager _observerManager; /** Current user provider */ protected CurrentUserProvider _currentUserProvider; - - /** XSL file path. */ - protected String _xslFile; + /** Current user provider */ + protected CDMFrSyncExtensionPoint _cdmFrSyncExtensionPoint; /** Workflow name for program */ protected String _programWorkflowName; @@ -117,17 +119,14 @@ _xPathProcessor = (XPathProcessor) manager.lookup(XPathProcessor.ROLE); _provider = (OdfConstantsProvider) manager.lookup(OdfConstantsProvider.ROLE); _domParser = (DOMParser) manager.lookup(DOMParser.ROLE); - _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); _observerManager = (ObservationManager) manager.lookup(ObservationManager.ROLE); _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); - + _cdmFrSyncExtensionPoint = (CDMFrSyncExtensionPoint) manager.lookup(CDMFrSyncExtensionPoint.ROLE); } @Override public void configure(Configuration configuration) throws ConfigurationException { - _xslFile = configuration.getChild("xsl-transform").getValue(null); - _programWorkflowName = configuration.getChild("program-workflow-name").getValue(null); _courseWorkflowName = configuration.getChild("course-workflow-name").getValue(null); _orgUnitWorkflowName = configuration.getChild("orgunit-workflow-name").getValue(null); @@ -771,4 +770,32 @@ String actionId = "8" + currentStepId + "0"; _workflow.doAction(content.getWorkflowId(), Integer.valueOf(actionId), inputs); } + + /** + * Transform the document depending of it structure. + * @param document Document to transform. + * @param report Report for errors. + * @return The transformed document. + * @throws IOException + * @throws ProcessingException + */ + protected Document transformDocument (Document document, SynchronizationReport report) throws IOException, SAXException, ProcessingException + { + CDMFrSyncTransformer transformer = _cdmFrSyncExtensionPoint.getTransformer(document); + if (transformer == null) + { + String msg = "Aucun transformer CDM-fr ne correspond à cette structure."; + report.error(msg); + getLogger().error(msg); + return null; + } + + return transformer.transform(document); + } + + protected File getCDMFrDirectory () + { + String dirPath = Config.getInstance().getValueAsString("odf.cdmfr.search.repository"); + return new File(dirPath); + } } Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrImportManager.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrImportManager.java (revision 16249) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrImportManager.java (working copy) @@ -23,13 +23,12 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.avalon.framework.logger.Logger; +import org.apache.cocoon.ProcessingException; import org.apache.commons.io.IOUtils; -import org.apache.excalibur.source.Source; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -53,7 +52,6 @@ import org.ametys.plugins.odfsync.cdmfr.item.CDMFrFileRemoteItem; import org.ametys.plugins.odfsync.cdmfr.searchitem.CDMFrFileSearchRemoteItem; import org.ametys.plugins.repository.AmetysRepositoryException; -import org.ametys.runtime.config.Config; import org.ametys.runtime.util.LoggerFactory; import org.ametys.runtime.util.parameter.ParameterHelper; import org.ametys.runtime.util.parameter.ParameterHelper.ParameterType; @@ -116,57 +114,53 @@ { List<Program> importedPrograms = new ArrayList<Program>(); - InputStream is = null; try { - // Parsing - HashMap<String, Object> parameters = new HashMap<String, Object>(); - parameters.put("source", stream); - parameters.put("xslFile", _xslFile); - Source src = _sourceResolver.resolveURI("cocoon://_plugins/odf-sync/cdmfr/import/file", null, parameters); - // XML to Content - is = src.getInputStream(); - Document doc = _domParser.parseDocument(new InputSource(is)); + Document doc = _domParser.parseDocument(new InputSource(stream)); + doc = transformDocument(doc, report); - // Import programs - report.info("Import des formations ..."); - - NodeList nodes = doc.getElementsByTagName("program"); - - for (int i = 0; i < nodes.getLength(); i++) + if (doc != null) { - Node contentNode = nodes.item(i); - // String cdmId = contentNode.getAttributes().getNamedItem("CDMid").getTextContent(); - String contentName = _xPathProcessor.evaluateAsString(contentNode, "code"); + // Import programs + report.info("Import des formations ..."); - SynchronizableContent content = getContent(ProgramFactory.PROGRAM_CONTENT_TYPE, "code", contentName); - if (content == null) + NodeList nodes = doc.getElementsByTagName("program"); + + for (int i = 0; i < nodes.getLength(); i++) { - try + Node contentNode = nodes.item(i); + // String cdmId = contentNode.getAttributes().getNamedItem("CDMid").getTextContent(); + String contentName = _xPathProcessor.evaluateAsString(contentNode, "code"); + + SynchronizableContent content = getContent(ProgramFactory.PROGRAM_CONTENT_TYPE, "code", contentName); + if (content == null) { - // Create program - String contentTitle = _xPathProcessor.evaluateAsString(contentNode, "title"); - report.info("Création de la formation " + contentName); - String contentId = createContent(ProgramFactory.PROGRAM_CONTENT_TYPE, contentName, contentTitle, _programWorkflowName, 1, null); - content = _resolver.resolveById(contentId); - synchronizeContent(doc, content, contentNode, report, true); - - importedPrograms.add((Program) content); + try + { + // Create program + String contentTitle = _xPathProcessor.evaluateAsString(contentNode, "title"); + report.info("Création de la formation " + contentName); + String contentId = createContent(ProgramFactory.PROGRAM_CONTENT_TYPE, contentName, contentTitle, _programWorkflowName, 1, null); + content = _resolver.resolveById(contentId); + synchronizeContent(doc, content, contentNode, report, true); + + importedPrograms.add((Program) content); + } + catch (WorkflowException e) + { + report.error("Une erreur est survenue lors de la création du contenu " + contentName, e); + } } - catch (WorkflowException e) + else { - report.error("Une erreur est survenue lors de la création du contenu " + contentName, e); + synchronizeContent(doc, content, contentNode, report, true); + report.info("La formation " + contentName + " existe déjà , elle ne sera pas recrée"); } } - else - { - synchronizeContent(doc, content, contentNode, report, true); - report.info("La formation " + contentName + " existe déjà , elle ne sera pas recrée"); - } + + report.info(importedPrograms.size() + " formation(s) ont été importées"); } - - report.info(importedPrograms.size() + " formation(s) ont été importées"); } catch (IOException e) { @@ -176,9 +170,9 @@ { throw new AmetysRepositoryException("A problem occured while parsing the input stream.", e); } - finally + catch (ProcessingException e) { - IOUtils.closeQuietly(is); + throw new AmetysRepositoryException("A problem occured while transforming the document.", e); } return importedPrograms; @@ -193,8 +187,7 @@ FileFilter filter = new CDMFRFileFilter(fileName, lastModifiedAfter, lastModifiedBefore); - String path = Config.getInstance().getValueAsString("odf.cdmfr.search.repository"); - File repository = new File(path); + File repository = getCDMFrDirectory(); List<CDMFrFileSearchRemoteItem> items = new ArrayList<CDMFrFileSearchRemoteItem>(); @@ -221,9 +214,8 @@ Date lastModifiedBefore = (Date) ParameterHelper.castValue(params.get("lastModifiedBefore"), ParameterType.DATE); FileFilter filter = new CDMFRFileFilter(fileName, lastModifiedAfter, lastModifiedBefore); - - String path = Config.getInstance().getValueAsString("odf.cdmfr.search.repository"); - File repository = new File(path); + + File repository = getCDMFrDirectory(); File[] cdmfrFiles = repository.listFiles(filter); if (cdmfrFiles != null && cdmfrFiles.length > 0) Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/GlobalCDMFrSynchronizationManager.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/GlobalCDMFrSynchronizationManager.java (revision 0) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/GlobalCDMFrSynchronizationManager.java (revision 0) @@ -0,0 +1,110 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.plugins.odfsync.cdmfr; + +import java.io.File; +import java.io.FileFilter; +import java.util.Arrays; + +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.commons.io.comparator.LastModifiedFileComparator; + +import org.ametys.plugins.odfsync.SynchronizationReport; +import org.ametys.plugins.odfsync.cdmfr.item.CDMFrFileRemoteItem; +import org.ametys.plugins.repository.AmetysRepositoryException; + +import com.opensymphony.workflow.WorkflowException; + +/** + * This implementation synchronize ODF contents from CDM-fr files + * + */ +public class GlobalCDMFrSynchronizationManager extends CDMFrSynchronizationManager +{ + /** Avalon Role */ + public static final String ROLE = GlobalCDMFrSynchronizationManager.class.getName(); + + private CDMFrImportManager _importManager; + + @Override + public void service(ServiceManager smanager) throws ServiceException + { + super.service(smanager); + _importManager = (CDMFrImportManager) smanager.lookup(CDMFrImportManager.ROLE); + } + + //------------------------------------------------------------ + // PROGRAMS + //------------------------------------------------------------ + + @Override + public void synchronizePrograms(SynchronizationReport report) + { + String infoMsg = "Synchronisation des formations ..."; + report.info(infoMsg); + _logger.info(infoMsg); + + boolean hasChanges = false; + + FileFilter filter = new CDMFRFileFilter(null, null, null); + File repository = getCDMFrDirectory (); + File[] cdmfrFiles = repository.listFiles(filter); + + // Sort by last modified date + Arrays.sort(cdmfrFiles, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR); + + if (cdmfrFiles.length > 0) + { + for (File cdmfrFile : cdmfrFiles) + { + CDMFrFileRemoteItem item = new CDMFrFileRemoteItem(); + item.setFile(cdmfrFile); + try + { + _importManager.importPrograms(item, report); + } + catch (AmetysRepositoryException e) + { + String msg = "Erreur à la synchronisation du fichier " + cdmfrFile.getPath(); + report.error(msg, e); + _logger.error(msg, e); + } + catch (WorkflowException e) + { + String msg = "Erreur de workflow lors de la synchronisation du fichier " + cdmfrFile.getPath(); + report.error(msg, e); + _logger.error(msg, e); + } + } + } + else + { + infoMsg = "Aucun fichier CDM-fr ne contient des formations"; + report.info(infoMsg); + _logger.info(infoMsg); + } + + infoMsg = "Synchronization des formations terminée"; + if (!hasChanges) + { + infoMsg += ": il n'y a eu aucune modification depuis la dernière synchronisation"; + } + report.info(infoMsg); + _logger.info(infoMsg); + + } +} Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrSyncExtensionPoint.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrSyncExtensionPoint.java (revision 0) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrSyncExtensionPoint.java (revision 0) @@ -0,0 +1,54 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.plugins.odfsync.cdmfr; + +import java.util.Set; + +import org.w3c.dom.Document; + +import org.ametys.plugins.odfsync.cdmfr.transformers.CDMFrSyncTransformer; +import org.ametys.runtime.plugin.ExtensionPoint; +import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; + +/** + * {@link ExtensionPoint} for registering {@link CDMFrSyncTransformer}s. + */ +public class CDMFrSyncExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<CDMFrSyncTransformer> +{ + /** Avalon Role */ + public static final String ROLE = CDMFrSyncExtensionPoint.class.getName(); + + /** + * Get the transformer. + * @param document + * @return the transformer + */ + public CDMFrSyncTransformer getTransformer(Document document) + { + Set<String> extensionsIds = getExtensionsIds(); + + for (String id : extensionsIds) + { + CDMFrSyncTransformer transformer = getExtension(id); + if (transformer.supports(document)) + { + return transformer; + } + } + + return null; + } +} Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/AbstractCDMFrSyncTransformer.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/AbstractCDMFrSyncTransformer.java (revision 0) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/AbstractCDMFrSyncTransformer.java (revision 0) @@ -0,0 +1,44 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.plugins.odfsync.cdmfr.transformers; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.logger.AbstractLogEnabled; + +/** + * Abstract class for CDMFrSyncTransformer, it configure applications list. + * @author Bérénice MAUREL + */ +public abstract class AbstractCDMFrSyncTransformer extends AbstractLogEnabled implements CDMFrSyncTransformer, Configurable +{ + /** Set of applications supported by the transformer. */ + protected Set<String> _applications = new HashSet<String>(); + + @Override + public void configure(Configuration configuration) throws ConfigurationException + { + Configuration[] applications = configuration.getChildren("app"); + for (Configuration application : applications) + { + _applications.add(application.getValue("")); + } + } +} Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/CDMFrSyncTransformer.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/CDMFrSyncTransformer.java (revision 0) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/CDMFrSyncTransformer.java (revision 0) @@ -0,0 +1,46 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.plugins.odfsync.cdmfr.transformers; + +import java.io.IOException; + +import org.apache.cocoon.ProcessingException; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * Interface for sync transformer objects. + * @author Bérénice MAUREL + */ +public interface CDMFrSyncTransformer +{ + /** + * Analyze the document and tell if it's support or not by the current transformer. + * @param document The document to analyze. + * @return TRUE if the document is supported by the transformer, otherwise FALSE. + */ + public boolean supports(Document document); + + /** + * Transform the document to a generic document designed for Ametys importers and synchronizers. + * @param document The document to transform. + * @return The transformed document. + * @throws IOException + * @throws SAXException + * @throws ProcessingException + */ + public Document transform(Document document) throws IOException, SAXException, ProcessingException; +} Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/DefaultCDMFrSyncTransformer.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/DefaultCDMFrSyncTransformer.java (revision 0) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/transformers/DefaultCDMFrSyncTransformer.java (revision 0) @@ -0,0 +1,114 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.plugins.odfsync.cdmfr.transformers; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.components.source.SourceUtil; +import org.apache.commons.lang.StringUtils; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceResolver; +import org.apache.excalibur.xml.dom.DOMParser; +import org.apache.excalibur.xml.xpath.PrefixResolver; +import org.apache.excalibur.xml.xpath.XPathProcessor; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * Default implementation of CDMFrSyncTransformer. + * @author Bérénice MAUREL + */ +public class DefaultCDMFrSyncTransformer extends AbstractCDMFrSyncTransformer implements Serviceable +{ + /** The rich text prefix resolver. */ + public static final PrefixResolver CDMFR_PREFIX_RESOLVER = new CDMFrPrefixResolver(); + + /** The DOM parser. */ + protected DOMParser _domParser; + /** Ametys object resolver. */ + protected SourceResolver _sourceResolver; + /** The XPath processor. */ + protected XPathProcessor _xPathProcessor; + + /** The XSL file to transform the document. */ + protected String _xslFile; + + @Override + public void service(ServiceManager manager) throws ServiceException + { + _domParser = (DOMParser) manager.lookup(DOMParser.ROLE); + _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); + _xPathProcessor = (XPathProcessor) manager.lookup(XPathProcessor.ROLE); + } + + @Override + public void configure(Configuration configuration) throws ConfigurationException + { + super.configure(configuration); + _xslFile = configuration.getChild("configuration").getChild("xsl-transform").getValue(""); + } + + @Override + public boolean supports(Document document) + { + String application = _xPathProcessor.evaluateAsString(document, "/cdm:CDM/cdm:properties/cdm:datasource", CDMFR_PREFIX_RESOLVER); + if (StringUtils.isNotBlank(application)) + { + return _applications.contains(application); + } + return false; + } + + @Override + public Document transform(Document document) throws IOException, SAXException, ProcessingException + { + HashMap<String, Object> parameters = new HashMap<String, Object>(); + parameters.put("source", document); + parameters.put("xslFile", _xslFile); + Source src = _sourceResolver.resolveURI("cocoon://_plugins/odf-sync/cdmfr/import/file", null, parameters); + return SourceUtil.toDOM(src); + } + + /** + * XML prefix resolver which declares CDMFr namespaces. + */ + public static class CDMFrPrefixResolver implements PrefixResolver + { + /** + * The declared XML namespaces. + */ + public static final Map<String, String> NAMESPACES = new HashMap<String, String>(); + + static + { + NAMESPACES.put("cdm", "http://cdm-fr.fr/2011/CDM"); + NAMESPACES.put("cdmfr", "http://cdm-fr.fr/2011/CDM-frSchema"); + } + + public String prefixToNamespace(String prefix) + { + return NAMESPACES.get(prefix); + } + } +} Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/GlobalCDMFrODFSyncManager.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/GlobalCDMFrODFSyncManager.java (revision 0) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/GlobalCDMFrODFSyncManager.java (revision 0) @@ -0,0 +1,52 @@ +/* + * Copyright 2012 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.plugins.odfsync.cdmfr; + +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; + +import org.ametys.plugins.odfsync.ImportManager; +import org.ametys.plugins.odfsync.ODFSyncManager; +import org.ametys.plugins.odfsync.SynchronizationManager; + +/** + * Implementation to import and synchronize ODF contents from CDM-fr folder. + * + */ +public class GlobalCDMFrODFSyncManager implements ODFSyncManager, Serviceable +{ + private GlobalCDMFrSynchronizationManager _synchroManager; + + @Override + public void service(ServiceManager smanager) throws ServiceException + { + _synchroManager = (GlobalCDMFrSynchronizationManager) smanager.lookup(GlobalCDMFrSynchronizationManager.ROLE); + } + + @Override + public ImportManager getImportManager() + { + return null; + } + + @Override + public SynchronizationManager getSynchronizationManager() + { + return _synchroManager; + } + +} Index: main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrSynchronizationManager.java =================================================================== --- main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrSynchronizationManager.java (revision 16249) +++ main/plugin-odf-sync/src/org/ametys/plugins/odfsync/cdmfr/CDMFrSynchronizationManager.java (working copy) @@ -25,16 +25,11 @@ import java.util.HashMap; import java.util.Map; -import org.apache.avalon.framework.component.Component; -import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.logger.Logger; -import org.apache.avalon.framework.service.ServiceException; -import org.apache.avalon.framework.service.ServiceManager; -import org.apache.avalon.framework.service.Serviceable; +import org.apache.cocoon.ProcessingException; import org.apache.commons.io.IOUtils; import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.lang.StringUtils; -import org.apache.excalibur.source.Source; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -50,13 +45,11 @@ import org.ametys.odf.program.ProgramFactory; import org.ametys.plugins.odfsync.SynchronizationManager; import org.ametys.plugins.odfsync.SynchronizationReport; -import org.ametys.plugins.odfsync.global.GlobalSynchronizationEngine; import org.ametys.plugins.repository.AmetysObjectIterable; import org.ametys.plugins.repository.AmetysRepositoryException; import org.ametys.plugins.repository.query.expression.AndExpression; import org.ametys.plugins.repository.query.expression.Expression; import org.ametys.plugins.repository.query.expression.Expression.Operator; -import org.ametys.runtime.config.Config; import org.ametys.runtime.util.LoggerFactory; import com.opensymphony.workflow.WorkflowException; @@ -65,26 +58,19 @@ * This implementation synchronize ODF contents from CDM-fr files * */ -public class CDMFrSynchronizationManager extends AbstractCDMFrManager implements SynchronizationManager, Serviceable, Configurable, Component +public class CDMFrSynchronizationManager extends AbstractCDMFrManager implements SynchronizationManager { /** Avalon Role */ public static final String ROLE = CDMFrSynchronizationManager.class.getName(); /** Logger available to subclasses. */ - protected Logger _logger = LoggerFactory.getLoggerFor(GlobalSynchronizationEngine.class); + protected Logger _logger = LoggerFactory.getLoggerFor(CDMFrSynchronizationManager.class); @Override protected Logger getLogger() { return _logger; } - - @Override - public void service(ServiceManager manager) throws ServiceException - { - super.service(manager); - - } //------------------------------------------------------------ // PROGRAMS @@ -100,6 +86,7 @@ boolean hasChanges = false; Map<String, String> programToFile = getContentsToFile("program"); + if (!programToFile.isEmpty()) { try @@ -134,7 +121,7 @@ } else { - File dirFile = _getCDMFrDirectory(); + File dirFile = getCDMFrDirectory(); File cdmFile = new File(dirFile, fileName); InputStream is = null; try @@ -179,12 +166,6 @@ _logger.info(infoMsg); } - - private File _getCDMFrDirectory () - { - String dirPath = Config.getInstance().getValueAsString("odf.cdmfr.search.repository"); - return new File(dirPath); - } @Override public boolean synchronizeProgram(String syncCode, Program program, SynchronizationReport report) throws AmetysRepositoryException @@ -200,7 +181,7 @@ return false; } - File dirFile = _getCDMFrDirectory(); + File dirFile = getCDMFrDirectory(); File cdmFile = new File(dirFile, fileName); InputStream is = null; try @@ -249,32 +230,28 @@ } else { - InputStream is = null; try { - // Parsing - HashMap<String, Object> parameters = new HashMap<String, Object>(); - parameters.put("source", stream); - parameters.put("xslFile", _xslFile); - Source src = _sourceResolver.resolveURI("cocoon://_plugins/odf-sync/cdmfr/import/file", null, parameters); - // XML to Content - is = src.getInputStream(); - Document doc = _domParser.parseDocument(new InputSource(is)); + Document doc = _domParser.parseDocument(new InputSource(stream)); + doc = transformDocument(doc, report); - Node programNode = _xPathProcessor.selectSingleNode(doc.getFirstChild(), "program[@CDMid = '" + syncCode + "']"); - if (programNode == null) + if (doc != null) { - String errorMsg = "La formation \"" + program.getTitle() + " (" + program.getCdmCode() + ")\" n'a pas été trouvé dans le fichier CDM-fr"; - report.error(errorMsg); - _logger.error(errorMsg); - return false; - } - hasChanges = synchronizeContent(doc, program, programNode, report, false); - - if (hasChanges) - { - applyChanges(program); + Node programNode = _xPathProcessor.selectSingleNode(doc.getFirstChild(), "program[@CDMid = '" + syncCode + "']"); + if (programNode == null) + { + String errorMsg = "La formation \"" + program.getTitle() + " (" + program.getCdmCode() + ")\" n'a pas été trouvé dans le fichier CDM-fr"; + report.error(errorMsg); + _logger.error(errorMsg); + return false; + } + hasChanges = synchronizeContent(doc, program, programNode, report, false); + + if (hasChanges) + { + applyChanges(program); + } } } catch (IOException e) @@ -289,9 +266,9 @@ { throw new AmetysRepositoryException("Unable to process workflow action", e); } - finally + catch (ProcessingException e) { - IOUtils.closeQuietly(is); + throw new AmetysRepositoryException("A problem occured while transforming the document.", e); } infoMsg = "Synchronisation de la formation \"" + program.getTitle() + " (" + program.getCdmCode() + ")\" terminée"; @@ -374,7 +351,7 @@ Map<String, String> contentToFile = new HashMap<String, String>(); FileFilter filter = new CDMFRFileFilter(null, null, null); - File repository = _getCDMFrDirectory (); + File repository = getCDMFrDirectory (); File[] cdmfrFiles = repository.listFiles(filter); // Sort by last modified date @@ -430,7 +407,7 @@ protected String getFileForContent(String syncCode, String tagName) { FileFilter filter = new CDMFRFileFilter(null, null, null); - File repository = _getCDMFrDirectory(); + File repository = getCDMFrDirectory(); File[] cdmfrFiles = repository.listFiles(filter); // Sort by last modified date Index: main/plugin-odf-sync/sitemap.xmap =================================================================== --- main/plugin-odf-sync/sitemap.xmap (revision 16240) +++ main/plugin-odf-sync/sitemap.xmap (working copy) @@ -34,7 +34,7 @@ <map:generator name="content" src="org.ametys.cms.content.ContentGenerator" /> - <map:generator name="input-stream" src="org.ametys.cms.transformation.InputStreamGenerator"/> + <map:generator name="dom" src="org.ametys.cms.transformation.DOMGenerator"/> </map:generators> <map:actions> @@ -228,14 +228,7 @@ </map:match> <map:match pattern="cdmfr/import/file"> - <map:generate type="input-stream"/> - <map:transform src="{parent-context-attr:xslFile}"/> - <map:serialize type="xml"/> - </map:match> - - <!-- Synchronisation CDM-FR --> - <map:match pattern="cdmfr/sync/file"> - <map:generate type="input-stream"/> + <map:generate type="dom"/> <map:transform src="{parent-context-attr:xslFile}"/> <map:serialize type="xml"/> </map:match>