Technical migration manual for versions 1.1.x, 1.2.x and 1.3.x to 2.x


  1. Data model
    1. New fields listed
    2. Domain and ministerial domain
    3. Metadata "universalAdjustment
    4. Deletion of "sector of activity
    5. No more "discipline
    6. Multi-valued locations
    7. Multiple attachments
    8. Synchronized rich text
    9. Multi-valued sub-program keywords
    10. Joint establishments become a listed field
    11. Component
      1. RNE code becomes UAI code
      2. Root component name change
  2. List of courses" service
    1. Data migration
    2. Graphic charter migration
  3. Research department
    1. Data migration
    2. Graphic charter migration
  4. Insert content" service
  5. SQLMap files for Apogée
  6. Apogee conversion files
  7. Runtime file.xml
  8. Ribbon file
  9. Workflow

 

Data model

New fields listed

The ROME, SISE, ERASMUS and CITE 97 references become listed fields.

The "DGESIP disciplinary sector" field has been added. It is a multiple enumerated field.

Some existing values and field labels (Diploma, Level of study, Type of diploma, etc.) have also been modified.

Download the xml files for these listed fields and copy/replace them in your application's WEB-INF/param/odf directory.

Add/replace the associated i18n keys in your application catalog(WEB-INF/i18n /application.xml and WEB-INF/i18n/application_en .xml).

Run the various migration scripts in the console: Migration of enumerated fields v1 to v2

Domain and ministerial domain

The ministerial domain becomes an enumerated field and is mandatory.

This field is now used to build the virtual tree instead of the "Discipline area" field.

Download the file xml domain.xml and copy it into your application's WEB-INF/param/odf directory.

Add the associated i18n keys to your application catalog(WEB-INF/i18n /application.xml and WEB-INF/i18n/application_en .xml):

<message key="APPLICATION_ODF_PRIMARY_DOMAIN_00">Hors domaines de formation</message> 
<message key="APPLICATION_ODF_PRIMARY_DOMAIN_01">Arts, Lettres, Langues</message> 
<message key="APPLICATION_ODF_PRIMARY_DOMAIN_02">Droit, Economie, Gestion</message> 
<message key="APPLICATION_ODF_PRIMARY_DOMAIN_03">Sciences humaines et sociales</message> 
<message key="APPLICATION_ODF_PRIMARY_DOMAIN_04">Sciences, Technologies, Santé</message> 
<message key="APPLICATION_ODF_PRIMARY_DOMAIN_05">Sciences et technologies des activités physiques et sportives</message> 

The "ministryDomain" metadata has been deleted. If you have overloaded the definition of program and/or subprogram contents(WEB-INF/param/content-types/_override/*.xml), you must delete all references to"ministryDomain".

The metadata "ametys:domain" is still used for the tree structure and the various services ODF, but it no longer corresponds to the domains defined in the file domain_discipline.xml but to the new file domain.xml.
Execute the following script to migrate the domain field of your training courses without losing the tree structure of the training offer.

Please note that the codes for the existing "domains" depend on your application. Refer to your file to make the correspondence.

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program']", javax.jcr.query.Query.XPATH); 

var nodes = query.execute().getNodes(); 
 
var count = 0; 
while (nodes.hasNext()) 
{ 
   var program = nodes.next(); 
  
   if (program.hasProperty("ametys:domain")) 
   { 
     var domain = program.getProperty("ametys:domain").getValue().getString(); 
     if (domain == "0001") 
     { 
       // Sciences humaines et sociales 
       program.setProperty("ametys:domain", "SHS"); 
     } 
     else if (domain == "0002") 
     { 
       // Droit, Economie, Gestion 
       program.setProperty("ametys:domain", "DEG"); 
     } 
     else if (domain == "0003") 
     { 
       // Arts, Lettres, Langues 
       program.setProperty("ametys:domain", "ALL"); 
     } 
     else if (domain == "0004") 
     { 
       // Sciences, Technologies, Santé 
       program.setProperty("ametys:domain", "STS"); 
     } 
     program.save(); 
     count++; 
   } 
} 

println(count + " programs has been modified"); 

Metadata "universalAdjustment

The "universalAdjustment" metadata corresponding to the "special fittings" field was sometimes misnamed "universalAdjustment".

If you have overloaded the definition of program, subprogram and/or orgunit content(WEB-INF/param/content-types/_override/*.xml), you must replace all references to"universalAdjustment" with"universalAdjustment".

For your data, run the following script :

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program' or @ametys-internal:contentType = 'org.ametys.plugins.odf.Content.subProgram' or @ametys-internal:contentType = 'org.ametys.plugins.odf.Content.orgunit']", javax.jcr.query.Query.XPATH); 
 
var nodes = query.execute().getNodes(); 
  
var count = 0; 
while (nodes.hasNext()) 
{ 
   var node = nodes.next(); 
   if (node.hasNode("ametys:universalAdjustement_remote")) 
   { 
        var uaNode = node.getNode("ametys:universalAdjustement_remote"); 
        uaNode.getSession().move(uaNode.getPath(), node.getPath() + "/ametys:universalAdjustment_remote"); 
        
        node.save(); 
        count++; 
   } 
   if (node.hasNode("ametys:universalAdjustement")) 
   { 
        var uaNode = node.getNode("ametys:universalAdjustement"); 
        uaNode.getSession().move(uaNode.getPath(), node.getPath() + "/ametys:universalAdjustment"); 
        
        node.save(); 
        count++; 
   } 
} 

println(count + " contents have been modified"); 

Deletion of "sector of activity

The "Sector of activity" field has been removed and replaced by the "DGESIP Sector" field.

  • If you wish to keep this field , you will need to redefine the "sector_activity" metadata in the WEB-INF/param/content-types/_override/org file .ametys.plugins.odf.Content.program. xml
<cms:metadata name="sector-activity" type="string" multiple="true"> 
        <label i18n="true">plugin.odf-projet:PLUGINS_ODF_PROJET_SECTOR_ACTIVITY</label> 
        <description i18n="true">plugin.odf-projet:PLUGINS_ODF_PROJET_SECTOR_ACTIVITY_DESC</description> 
        <widget>sorted-multiselect</widget> 
        <enumeration> 
            <custom-enumerator class="org.ametys.plugins.odfprojet.enumeration.SectorsEnumerator"/> 
        </enumeration>   
</cms:metadata> 

Please note that the SectorsEnumerator class no longer exists in plugin ODF , so you'll need to write it down.

 

  • If you don't want to keep this field, delete the file WEB-INF/param/odf/sector_activity.xml and remove all references to the "sector_activity" metadata in the file WEB-INF/param/content-types/_override/org.ametys.plugins.odf.Content.program.xml (if you have overridden a training data model)

No more "discipline

The "discipline" field has been removed in favor of the "Discipline SISE" field.

  • Delete the WEB-INF/param/odf/domain_discipline file. xml
  • Replace all references to the "domain_discipline" metadata with the "siseCode" metadata in the file WEB-INF/param/content-types/_override/org.ametys.plugins.odf.Content.program.xml (if you have overridden a training data model)
  • Go to script to migrate your training courses:
importClass(org.ametys.workspaces.repository.ConsoleHelper); 

var mapping = { 
    '0001.1': '27', // Histoire 
    '0001.2': '27', // Géographie 
    '0001.3': '29', // Aménagement 
    '0001.4': '32', // Psychologie 
    '0001.5': '33', // Sociologie, démographie 
    '0001.6': '34', // Sciences de l'éducation 
    '0001.7': '35', // Sciences de l'info. et de la communication 
    '0001.8': '66', // Pluri Sciences humaines et Sociales 
    '0002.1': '36', // Sciences juridiques 
    '0002.2': '37', // Sciences politiques 
    '0002.3': '38', // Sciences économiques 
    '0002.4': '39', // Sciences de gestion 
    '0002.5': '40', // Administration économique et sociale 
    '0002.6': '62', // Pluri Sciences Economique-Gestion 
    '0003.1': '17', // Sciences du langage - linguistique 
    '0003.2': '18', // Langues et littératures anciennes 
    '0003.3': '19', // Langues et littératures françaises 
    '0003.4': '20', // Littérature générale et comparée 
    '0003.5': '22', // Français, langue étrangère 
    '0003.6': '23', // Langues et littératures étrangères 
    '0003.7': '24', // Langues étrangères appliquées 
    '0003.8': '25', // Cultures et langues régionales 
    '0003.9': '67', // Pluri Lettres-Langues-Sciences humaines 
    '0004.1': '1',  // Mathématique 
    '0004.2': '2',  // Physique 
    '0004.3': '3',  // Chimie 
    '0004.4': '4',  // Mathématiques appliquées - sciences sociales 
    '0004.5': '5',  // Sciences de l'univers 
    '0004.6': '6',  // Sciences de la vie 
    '0004.7': '11', // Mécanique, génie mécanique 
    '0004.8': '12', // Génie civil 
    '0004.9': '13', // Génie des procédés 
    '0004.10': '14', // Informatique 
    '0004.11': '15', // Electronique, génie électrique 
'0004.12': '16', // Sciences et technologie industrielles 
'0004.13': '41', // Form. générale métiers de l'ingénieur 
'0004.14': '43', // Physique et Chimie 
'0004.15': '68', // Pluri Sciences Fondamentales et Application 
'0004.16': '70', // Pluri Sciences 
'0004.17': '7',  // Médecine 
'0004.18': '9',  // Pharmacie 
'0004.19': '69', // Pluri Sciences de la vie,de la santé 
'0004.20': '71'  // Pluri Santé 
} 

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program']", javax.jcr.query.Query.XPATH); 

var nodes = query.execute().getNodes(); 
 
var count = 0; 
while (nodes.hasNext()) 
{ 
    var program = nodes.next(); 
   var needSave = false; 
    if (program.hasProperty("ametys:domain-discipline")) 
    {  
var newValues = []; 
var oldValues = program.getProperty("ametys:domain-discipline").getValues(); 
for (var i=0; i < oldValues.length; i++) 
{ 
  var oldValue= oldValues[i].getString(); 
if (mapping[oldValue] != null) 
{ 
newValues.push(mapping[oldValue]); 
      } 
} 
if (newValues.length != 0) 
{ 
var siseCodes = java.lang.reflect.Array.newInstance(java.lang.String, newValues.length); 
            ConsoleHelper.setProperty(program, "ametys:siseCode", siseCodes); 
} 
program.getProperty("ametys:domain-discipline").remove(); 
needSave = true; 
} 
 
if (program.hasProperty("ametys:domain-discipline_remote")) 
    {  
var newValues = []; 
var oldValues = program.getProperty("ametys:domain-discipline_remote").getValues(); 
for (var i=0; i < oldValues.length; i++) 
{ 
  var oldValue= oldValues[i].getString(); 
if (mapping[oldValue] != null) 
{ 
newValues.push(mapping[oldValue]); 
      } 
} 
if (newValues.length != 0) 
{ 
var siseCodes = java.lang.reflect.Array.newInstance(java.lang.String, newValues.length); 
            ConsoleHelper.setProperty(program, "ametys:siseCode_remote", siseCodes); 
} 
program.getProperty("ametys:domain-discipline_remote").remove(); 
needSave = true; 
} 

if (program.hasProperty("ametys:domain-discipline_sync")) 
    { 
var sync = program.getProperty("domain-discipline_sync").getValue().getBoolean(); 
program.setProperty("ametys:siseCode_sync", sync); 
program.getProperty("ametys:domain-discipline_sync").remove();  
        needSave = true; 
} 

if (needSave) 
{ 
    program.save(); 
    count++; 
} 
} 

println(count + " programs has been modified"); 

Multi-valued locations

importClass(org.ametys.workspaces.repository.ConsoleHelper); 

function _migrateMultipleMetadata (node, propertyName) 
{ 
    if (node.hasProperty(propertyName)) 
    { 
       var property = node.getProperty(propertyName); 
       if (!property.getDefinition().isMultiple()) 
       { 
           var value = property.getValue().getString(); 
           property.remove(); 
             
           var values = value.split(","); 
           var places = java.lang.reflect.Array.newInstance(java.lang.String, values.length); 
           for (var i=0; i < values.length; i++) 
           { 
               places[i] = values[i].trim(); 
           } 
           ConsoleHelper.setProperty(node, propertyName, places); 
           node.save(); 
           return true; 
       }        
    } 
    return false; 
} 

var query1 = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program' or @ametys-internal:contentType = 'org.ametys.plugins.odf.Content.subProgram']", javax.jcr.query.Query.XPATH); 
  
var programNodes= query1.execute().getNodes(); 
   
var count = 0; 
while (programNodes.hasNext()) 
{ 
   var node = programNodes.next(); 
   if (_migrateMultipleMetadata (node, "ametys:place") || _migrateMultipleMetadata (node, "ametys:place_remote")) 
   { 
    count++;       
   } 
} 
println(count + " programs have been modified"); 

var query2 = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.course']", javax.jcr.query.Query.XPATH); 
  
var courseNodes = query2.execute().getNodes(); 
   
var count = 0; 
while (courseNodes.hasNext()) 
{ 
   var node = courseNodes.next(); 
   if (_migrateMultipleMetadata (node, "ametys:teachingLocation") || _migrateMultipleMetadata (node, "ametys:teachingLocation_remote")) 
   { 
    count++;       
   } 
} 
println(count + " courses' place have been modified"); 

 

Multiple attachments

The number of files to be downloaded on a course is increasing.

Run the following script to migrate existing attachments:

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program']", javax.jcr.query.Query.XPATH); 
 
var nodes = query.execute().getNodes(); 
  
var count = 0; 
while (nodes.hasNext()) 
{ 
   var program = nodes.next(); 
  
   if (program.hasNode("ametys:attachment") && !program.hasNode("ametys:attachments")) 
   { 
       var attachNode = program.getNode("ametys:attachment"); 
       var entryNode = program.addNode("ametys:attachments", "ametys:compositeMetadata").addNode("ametys:1", "ametys:compositeMetadata"); 
       // Move node 
       attachNode.getSession().move(attachNode.getPath(), entryNode.getPath() + "/ametys:attachment"); 
     
       program.save(); 
       count++; 
   } 
} 

println(count + " attachments have been moved"); 

If you have overloaded the definition of "program" content(WEB-INF/param/content-types/_override/*.xml), remember to change the references to the metadata "ametys:attachment" which becomes:

<cms:metadata-ref name="attachments"> 
    <cms:metadata-ref name="attachment"/> 
    <cms:metadata-ref name="attachment-text"/> 
</cms:metadata-ref>       

Synchronized rich text

TheODF rich text metadata no longer stores synchronized(remote) data as plain text. It is now stored as rich text.

To take this change into account, the following script must be executed:

importClass(java.io.ByteArrayInputStream); 
importClass(org.ametys.plugins.repository.RepositoryConstants); 

var data = { 
'ametys:courseContent' : [ 
'description', 
'objectives', 
'neededPrerequisite', 
'recommendedPrerequisite', 
'formOfAssessment', 
'benefits', 
'syllabus', 
'additionalInformations' 
], 
'ametys:programContent' : [ 
'presentation', 
'objectives', 
'qualification', 
'teachingOrganization', 
'accessCondition', 
'neededPrerequisite', 
'recommendedPrerequisite', 
'furtherStudy', 
'studyAbroad', 
'targetGroup', 
'jobOpportunities', 
'trainingStrategy', 
'knowledgeCheck', 
'universalAdjustment', 
'additionalInformations', 
'reorientation', 
'expenses' 
], 
'ametys:subProgramContent' : [ 
'presentation', 
'objectives', 
'qualification', 
'teachingOrganization', 
'accessCondition', 
'neededPrerequisite', 
'recommendedPrerequisite', 
'furtherStudy', 
'studyAbroad', 
'targetGroup', 
'jobOpportunities', 
'trainingStrategy', 
'knowledgeCheck', 
'universalAdjustment', 
'additionalInformations', 
'reorientation', 
'expenses' 
], 
'ametys:orgunitContent' : [ 
'description', 
'admissionInfo', 
'regulations', 
'expenses', 
'universalAdjustment', 
'studentFacilities', 
'additionalInfos' 
], 
'ametys:personContent' : [ 
'additionalInformations' 
] 
}; 

var qm = session.getWorkspace().getQueryManager(); 
suffix = '_remote', 
count = 0; 

for (var nt in data) { 

var query = qm.createQuery('//ametys:odf//element(*, ' + nt + ')', javax.jcr.query.Query.XPATH); 
nodes = query.execute().getNodes(), 
props = data[nt], 
l = props.length; 

while (nodes.hasNext()) { 
var contentNode = nodes.next(); 
        if (contentNode.isLocked()) unlock(contentNode); 
      
for (var i = 0; i < l; i++) { 
if (convertToRichText(contentNode, props[i] + suffix)) { 
count++; 
} 
} 
} 
} 

function unlock(node) 
{ 
    if (!node) return; 
  
    var lm = node.getSession().getWorkspace().getLockManager(); 
    if (lm.holdsLock(node.getPath())) 
    { 
      var lockToken = node.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString(); 
     
      lm.addLockToken(lockToken); 
      lm.unlock(node.getPath()); 
     
      // Remove residual properties 
      node["setProperty(java.lang.String,javax.jcr.Value)"](RepositoryConstants.METADATA_LOCKTOKEN, null); 
      node["setProperty(java.lang.String,javax.jcr.Value)"](RepositoryConstants.METADATA_LOCKOWNER, null); 
    } 
    else 
    { 
      unlock(node.getParent()); 
    } 
} 

function convertToRichText(contentNode, metadataName) { 
var prefix = 'ametys:', 
fullMetadataName = prefix + metadataName; 
 
function strToIS(str) { 
        var bytes = new java.lang.String(str).getBytes('UTF-8'); 
return new ByteArrayInputStream(bytes); 
} 
 
function setInputStream(rtNode, stream) { 
var binary = rtNode.getSession().getValueFactory().createBinary(stream); 
rtNode.setProperty('jcr:data', binary); 
} 
 
function setMimeType(rtNode, mime) { 
rtNode.setProperty('jcr:mimeType', mime); 
} 

if (contentNode.hasProperty(fullMetadataName)) { 
var p = contentNode.getProperty(fullMetadataName); 
var str = p.getString(); 
 
if (!contentNode.hasNode(fullMetadataName)) { 
if (str) { 
var rtn = contentNode.addNode(fullMetadataName, prefix + 'richText'), 
db = textToDocbook(str); 
setInputStream(rtn, strToIS(db)); 
setMimeType(rtn, 'text/xml'); 
} 
 
p.remove(); 
return true; 
} 
else { 
prinln('node ' + contentNode.getPath() + ' has a property and a node with the the name ' + fullMetadataName); 
} 
} 
return false; 
} 

function textToDocbook(str) { 
var mapping = { 
'<' : '&lt;', 
'&' : '&amp;', 
'\r\n' : '<phrase role="linebreak"/>', 
'\n' : '<phrase role="linebreak"/>' 
}; 
 
function repFn(match, p1) { 
return mapping[p1]; 
} 

var res = ''; 
res +=  '<?xml version="1.0" encoding="UTF-8"?>'; 
res +=  '<article xmlns="http://docbook.org/ns/docbook">'; 
res +=      '<para>'; 
res +=          new String(str).replace(/(<|&|\r?\n)/g, repFn); 
res +=      '</para>'; 
res +=  '</article>'; 

return res; 
} 

session.save(); 
println(count + ' metadata migrated'); 

Multi-valued sub-program keywords

Sub-program keywords are now multi-valued. Run the following script to migrate your subprograms:

importClass(org.ametys.workspaces.repository.ConsoleHelper); 

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.subProgram']", javax.jcr.query.Query.XPATH); 
 
var nodes = query.execute().getNodes(); 
  
var count = 0; 
while (nodes.hasNext()) 
{ 
   var node = nodes.next(); 
   
   if (node.hasProperty("ametys:keywords")) 
   { 
       var property = node.getProperty("ametys:keywords"); 
       if (!property.getDefinition().isMultiple()) 
       { 
           var value = property.getValue().getString(); 
           property.remove(); 
           
           var values = value.split(","); 
           var keywords = java.lang.reflect.Array.newInstance(java.lang.String, values.length); 
           for (var i=0; i < values.length; i++) 
           { 
               keywords[i] = values[i].trim(); 
           } 
           ConsoleHelper.setProperty(node, "ametys:keywords", keywords); 
           node.save(); 
           count++; 
       }         
   } 
} 
 
println(count + " subprograms' keywords have been modified"); 

Joint establishments become a listed field

The "Jointly accredited establishments" field ("joinOrgUnit" metadata) is no longer free text, but an enumerated field with the list of establishments accredited by the Ministry.

Download the XML file for the school list: join_orgunit.xml and copy it to your application's WEB-INF/param/odf directory.

Retrieve the associated i18n keys and add them to your application catalog(WEB-INF/i18n /application.xml and WEB-INF/i18n/application_en .xml).

If you wish to keep this field as free text you will need to redefine the "jointOrgUnit" metadata in the WEB-INF/param/content-types/_override/org.ametys.plugins.odf.Content.program.xml

<cms:metadata name="jointOrgUnit" type="string" multiple="true"> 
<label i18n="true">PLUGINS_ODF_PROGRAM_JOINT_ORGUNIT</label> 
    <description i18n="true">PLUGINS_ODF_PROGRAM_JOINT_ORGUNIT_DESC</description> 
</cms:metadata>        

Component

RNE code becomes UAI code

To comply with CDM-fr v2, the RNE code has been renamed UAI code.

Run the following script to update your existing components:

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.orgunit']", javax.jcr.query.Query.XPATH); 

var nodes = query.execute().getNodes(); 
  
var count = 0; 
while (nodes.hasNext()) 
{ 
   var ou = nodes.next(); 
  
   var needSave = false; 
   if (ou.hasProperty("ametys:rneCode")) 
   { 
       var code = ou.getProperty("ametys:rneCode").getValue().getString(); 
       ou.setProperty("ametys:codeUAI", code); 
       needSave = true; 
   } 
  
   if (ou.hasProperty("ametys:rneCode_remote")) 
   { 
       var code = ou.getProperty("ametys:rneCode_remote").getValue().getString(); 
       ou.setProperty("ametys:codeUAI_remote", code); 
       needSave = true; 
   } 
  
   if (ou.hasProperty("ametys:rneCode_sync")) 
   { 
       var sync = ou.getProperty("ametys:rneCode_sync").getValue().getString(); 
       ou.setProperty("ametys:codeUAI_sync", sync); 
       needSave = true; 
   } 
  
   if (needSave) 
   { 
       count++; 
       ou.save() 
   } 
} 

println(count + " orgunits has been modified"); 

Root component name change

The name of the JCR node corresponding to the root component has been modified in 3.5. Run the following script in the repository console to update the node name:

function getOU(qm, name) { 
  var xpath = "//element(*, ametys:orgunitContent)[fn:name() = '" + name + "']", 
      nodeIt = qm.createQuery(xpath, javax.jcr.query.Query.XPATH).execute().getNodes(); 
  return nodeIt.hasNext() ? nodeIt.next() : null; 
} 
var oldRootOUName = 'root-orgunit', 
    newRootOUName = 'orgunit-root-orgunit', 
    qm = session.getWorkspace().getQueryManager(), 
    oldRootOU = getOU(qm, oldRootOUName), 
    newRootOU = getOU(qm, newRootOUName); 
if (oldRootOU !== null) 
{ 
  // delete new root OU if existing 
  var path; 
  if (newRootOU !== null) 
  { 
    var wfNode = newRootOU.getProperty('ametys-internal:workflowRef').getNode(); 
    path = wfNode.getPath(); 
    wfNode.remove(); 
    println("workflow node at path '" + path + "' has been removed."); 
    
    path = newRootOU.getPath(); 
    newRootOU.remove(); 
    println("orgunit at path '" + path + "' has been removed."); 
  } 
  
  // rename old root orgunit 
  path = oldRootOU.getPath(); 
  session.move(path, oldRootOU.getParent().getParent().getParent().getPath() + '/55/83/' + newRootOUName); 
  println("orgunit at path '" + path + "' has been moved to to '" + oldRootOU.getPath() + "'."); 
               
  session.save() 
} 
else 
{ 
  println("No orgunit with the name '" + oldRootOUName + "' were found, nothing to do."); 
} 

NB: If the node name of your old root orgunit is not 'root-orgunit', you can change the value of the oldRootOUName variable at script.

List of courses" service

In 1.1.x, 1.2.x and 1.3.x, 5 services enabled you to create a training tree by field, diploma, component or sector of activity:

  • Training by field
  • Training by field
  • Training by type
  • Training by component
  • Training by activity

These 5 services have been replaced by a single, configurable service called "List of courses", enabling 1st and 2nd level grouping to be configured.

Data migration

To migrate instances of old services, run the following script in the console (repository interface):

var getAndRemoveBoolean = function(node, name) 
{ 
    var value = false; 
    if (node.hasProperty(name)) 
    { 
        var prop = node.getProperty(name); 
        value = prop.getBoolean(); 
        prop.remove(); 
    } 
    return value; 
} 
 
var migrated = 0; 
var xpath = "//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and (" 
    + "@ametys-internal:service='org.ametys.odf.service.ProgramsByType'" 
    + " or @ametys-internal:service='org.ametys.odf.service.ProgramsByDegreeDomain'" 
    + " or @ametys-internal:service='org.ametys.odf.service.ProgramsByDomain'" 
    + " or @ametys-internal:service='org.ametys.odf.service.ProgramsByOrgUnit'" 
    + " or @ametys-internal:service='org.ametys.odf.service.ProgramsBySector')]"; 
 
var query = session.getWorkspace().getQueryManager().createQuery(xpath, javax.jcr.query.Query.XPATH); 
var nodes = query.execute().getNodes(); 
 
while (nodes.hasNext()) 
{ 
    var node = nodes.next(); 
    var paramsNode = node.getNode('ametys:service_parameters'); 
     
    var currentServiceId = node.getProperty('ametys-internal:service').getString(); 
    var currentServiceXSLT = paramsNode.getProperty('ametys:xslt').getString(); 
     
    node.setProperty('ametys-internal:service', 'org.ametys.odf.service.ProgramList'); 
    paramsNode.setProperty('ametys:xslt', 'pages/services/program-list/program-list_1.3.xsl'); 
     
    var firstLevel = ''; 
    var secondLevel = ''; 
    var alphaOrderOnFirstLevel = false; 
    var alphaOrderOnSecondLevel = false; 
     
    if (currentServiceId == 'org.ametys.odf.service.ProgramsByType') 
    { 
        firstLevel = 'degree'; 
        secondLevel = 'orgunit'; 
        alphaOrderOnFirstLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDegrees'); 
    } 
    else if (currentServiceId == 'org.ametys.odf.service.ProgramsByDegreeDomain') 
    { 
        firstLevel = 'degree'; 
        secondLevel = 'domain'; 
        alphaOrderOnFirstLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDegrees'); 
        alphaOrderOnSecondLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDomains'); 
    } 
    else if (currentServiceId == 'org.ametys.odf.service.ProgramsByDomain') 
    { 
        firstLevel = 'domain'; 
        secondLevel = 'degree'; 
        alphaOrderOnFirstLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDomains'); 
        alphaOrderOnSecondLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDegrees'); 
    } 
    else if (currentServiceId == 'org.ametys.odf.service.ProgramsByOrgUnit') 
    { 
        firstLevel = 'orgunit'; 
        secondLevel = 'degree'; 
        alphaOrderOnSecondLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDegrees'); 
    } 
    else if (currentServiceId == 'org.ametys.odf.service.ProgramsBySector') 
    { 
        firstLevel = 'sectors_activity'; 
        secondLevel = 'degree'; 
        alphaOrderOnFirstLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnSectors'); 
        alphaOrderOnSecondLevel = getAndRemoveBoolean(paramsNode, 'ametys:alphaOrderOnDegrees'); 
    } 
     
    paramsNode.setProperty('ametys:firstLevel', firstLevel); 
    paramsNode.setProperty('ametys:secondLevel', secondLevel); 
    paramsNode.setProperty('ametys:alphaOrderOnFirstLevel', alphaOrderOnFirstLevel); 
    paramsNode.setProperty('ametys:alphaOrderOnSecondLevel', alphaOrderOnSecondLevel); 
     
    migrated++; 
} 
 
session.save(); 
println('=> ' + migrated + '  programs list service(s) have been migrated.'); 

Graphic charter migration

In the chart folder, all "programs-by-xxx" directories, located in the directory services/odf-web/pages/services directory, can be deleted.

They have been replaced by a single "program-list" directory. Any "overrides" made in the old XSL ("by-degree_1.2.xsl", "by-domain_1.2.xsl", ..) must be reflected in the new XSL "program-list/program-list_1.3.xsl "

Former organizationNew organization

 

Research department

The "Course search" and "Search criteria" services have been merged into a single service.

Data migration

var xsltMap = { 
 'pages/services/search-criteria/search-criteria.xsl': 'pages/services/search/search.xsl', 
 'pages/services/search-criteria/search-criteria_1.2.xsl': 'pages/services/search/search_1.2.xsl', 
 'pages/services/search-criteria/search-criteria-links_1.3.xsl': 'pages/services/search/search-links_1.3.xsl' 
} 
 
var qm = session.getWorkspace().getQueryManager(); 
var migrated = 0; 
 
// Criteria for ODF search: change into ODF search, criteria-only mode. 
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and @ametys-internal:service='org.ametys.odf.service.CriteriaForSearchService']", javax.jcr.query.Query.XPATH); 
var nodes = query.execute().getNodes(); 
 
while (nodes.hasNext()) 
{ 
 var node = nodes.next(); 
 var paramsNode = node.getNode('ametys:service_parameters'); 
 
 var message = 'Migrated ODF criteria service: ' + node.getPath(); 
 
 var currentServiceXSLT = paramsNode.getProperty('ametys:xslt').getString(); 
 
 node.setProperty('ametys-internal:service', 'org.ametys.odf.service.SearchService'); 
 paramsNode.setProperty('ametys:search-mode', 'criteria-only'); 
 
 if (xsltMap[currentServiceXSLT] != null) 
 { 
 paramsNode.setProperty('ametys:xslt', xsltMap[currentServiceXSLT]); 
 message += ', new xslt is: ' + xsltMap[currentServiceXSLT]; 
 } 
 
 println(message); 
 
 migrated++; 
} 
 
// ODF search: change the search mode. 
query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and @ametys-internal:service='org.ametys.odf.service.SearchService']/ametys:service_parameters[@ametys:on-same-page]", javax.jcr.query.Query.XPATH); 
nodes = query.execute().getNodes(); 
 
while (nodes.hasNext()) 
{ 
 var node = nodes.next(); 
 
 var onSamePage = node.getProperty('ametys:on-same-page').getBoolean(); 
 var mode = onSamePage ? 'criteria-and-results' : 'criteria-or-results'; 
 
 node.setProperty('ametys:search-mode', mode); 
 
 println('Migrated ODF search service parameters.'); 
 
 migrated++; 
} 
 
println('=> ' + migrated + ' ODF search service(s) have been migrated.'); 
 
session.save(); 

Graphic charter migration

In the graphic charter, the "search-criteria" directory, located in the services/odf-web/pages/services directory, must be moved to the services/odf-web/pages/services/search directory.

Insert content" service

If you were using the "insert content" service with courses, run the following script :

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and @ametys-internal:service='org.ametys.web.service.InsertContentService']", javax.jcr.query.Query.XPATH); 
var nodes = query.execute().getNodes(); 
  
var count = 0; 
while (nodes.hasNext()) 
{ 
  var zone = nodes.next(); 
  var serviceParameter = zone.getNode("ametys:service_parameters"); 
  
  if (serviceParameter.hasProperty("ametys:contentId")) 
  { 
      var contentId = serviceParameter.getProperty("ametys:contentId").getValue().getString(); 

      if (contentId.indexOf("programContent") != -1) 
      { 
        zone.setProperty("ametys-internal:service", "org.ametys.odf.service.InsertProgram"); 
        zone.save(); 
        count++; 
      } 
  } 
} 

println(count + " service(s) of ODF insert content have been migrated"); 

 

 

SQLMap files for Apogée

sqlMap objects defined in mapping files (WEB-INF/param/odf/apogee) have changed package.

Here's the new id - class correspondence.

FileIdClass
programs.xml



searchProgramItemorg.ametys.plugins.odfsync.apogee.searchitem.ApogeeProgramSearchRemoteItem
programorg.ametys.plugins.odfsync.apogee.item.ApogeeProgramRemoteItem
steporg.ametys.plugins.odfsync.apogee.item.ApogeeSubProgramRemoteItem
stepItemorg.ametys.plugins.odfsync.apogee.searchitem.ApogeeSubProgramSearchRemoteItem
stepElementorg.ametys.plugins.odfsync.apogee.item.ApogeeELPRemoteItem
orgUnits.xml

orgUnit, associatedOrgUnit, rootOrgUnitorg.ametys.plugins.odfsync.apogee.item.ApogeeOrgUnitRemoteItem
orgUnitSearchItemorg.ametys.plugins.odfsync.apogee.searchitem.ApogeeOrgUnitSearchRemoteItem
educationalElements.xmleducationalElementorg.ametys.plugins.odfsync.apogee.item.ApogeeCourseRemoteItem
educationalElementSearchItemorg.ametys.plugins.odfsync.apogee.searchitem.ApogeeCourseSearchRemoteItem
educationalElementContainerorg.ametys.plugins.odfsync.apogee.item.ApogeeContainerRemoteItem
educationalElementSearchContainerorg.ametys.plugins.odfsync.apogee.searchitem.ApogeeContainerSearchRemoteItem
raceListSearchItemorg.ametys.plugins.odfsync.apogee.item.ApogeeCourseListRemoteItem
raceListorg.ametys.plugins.odfsync.apogee.item.ApogeeCourseListRemoteItem

Apogee conversion files

The files used to convert Apogée codes have been moved.

The files listed below, initially located in the WEB-INF/param/apogee directory, must be moved to the WEB-INF/param/apogee/codedirectory ofyour application:

They must be placed in the WEB-INF/param/apogee/code directory of your application:

Runtime file.xml

If you are using Apogee synchronization, the WEB-INF/params/runtime.xml file must contain the following lines:

<org.ametys.plugins.odfsync.ODFSyncManager>org.ametys.plugins.odfsync.apogee.ApogeeODFSyncManager</org.ametys.plugins.odfsync.ODFSyncManager> 
<org.ametys.plugins.odfsync.apogee.ApogeeSynchronizationHelper>org.ametys.plugins.odfsync.apogee.DefaultApogeeSynchronizationHelper</org.ametys.plugins.odfsync.apogee.ApogeeSynchronizationHelper> 
<org.ametys.plugins.odfsync.apogee.ApogeeDAO>org.ametys.plugins.odfsync.apogee.DefaultApogeeDAO</org.ametys.plugins.odfsync.apogee.ApogeeDAO> 

In the <exclude> ... </exclude>check that the features odf-sync/synchronization.apogee.datasource  and odf-sync/odf.rights.sync.others are not disabled. If they are, remove them from this section.

For full details of how to set up a ODF 2.x application, please refer to the integrator' s manual: Integrator's manual

 

Ribbon file

In the file cms-ribbon-default.xml you must import the ribbon specific to the training offer:

  • if you use Apogée synchronization

    <import>plugin:odf-sync://cms-ribbon-web-apogee.xml</import> 
  • if you don't use Apogée synchronization

    <import>plugin:odf-web://cms-ribbon.xml</import> 

For full details of how to set up a ODF 2.x application, please refer to the integrator' s manual: Integrator's manual

 

Workflow

plugin odf-workflow no longer exists. Each application must have its own plugin defining the workflow actions available. You can find an example of plugin here https://code.ametys.org/projects/ODF /repos/template-odfweb/browse/webapp/cms/ plugins/default-odf-workflow

The workflow parameter files have been modified and depend on the plugins used. Refer to the table below to download the workflow files corresponding to your configuration.

Extract workflow files into your application's WEB-INF/param directory

 

Plugin ODF

Plugin ODF-Web

Plugin ODF-Sync

 

x  

 

xx 

 

x x

 

xx x
Back to top