Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ImporterUnCorpusOkapiMacro.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ImporterUnCorpusOkapiMacro.groovy	(revision 3189)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ImporterUnCorpusOkapiMacro.groovy	(revision 3190)
@@ -1,67 +0,0 @@
-// Copyright © 2021 MY_INSTITUTION
-// Licensed under the terms of the GNU General Public License version 3 (http://www.gnu.org/licenses/gpl-3.0.html)
-// @author mdecorde
-
-// STANDARD DECLARATIONS
-package org.txm.macro
-
-import org.kohsuke.args4j.*
-import groovy.transform.Field
-import org.txm.rcp.swt.widget.parameters.*
-import org.txm.searchengine.cqp.corpus.CQPCorpus
-import org.txm.searchengine.cqp.corpus.Subcorpus
-import org.txm.searchengine.cqp.corpus.query.CQLQuery
-import org.txm.rcp.views.corpora.CorporaView
-
-// BEGINNING OF PARAMETERS
-
-@Field @Option(name="nom_sous_corpus", usage="Nom du sous-corpus à créer", widget="String", required=true, def="")
-def nom_sous_corpus
-@Field @Option(name="liste_identifiants_sujets", usage="Liste des identifiants de notice séparés par des '|'", widget="Text", required=true, def="")
-def liste_identifiants_sujets
-
-if (!(corpusViewSelection instanceof CQPCorpus)) {
-	println "Erreur : la sélection de la vue Corpus n'est pas un corpus ($corpusViewSelection)."
-	return false
-} 
-
-CQPCorpus corpus = corpusViewSelection
-corpus.compute()
-CQPCorpus parentCorpus = corpus.getMainCorpus()
-
-String parentCorpusName = parentCorpus.getCqpId()
-
-if (parentCorpusName.startsWith("AF-VOIX-OFF-")) {
-	
-} else if (parentCorpusName.startsWith("AFNOTICES") || parentCorpusName.startsWith("AF-NOTICES")) {
-	
-} else {
-	println "Erreur : le corpus n'est pas un corpus d'AF-VOIX-OFF ni AFNOTICE."
-	return false
-}
-
-// Open the parameters input dialog box
-if (!ParametersDialog.open(this)) return;
-
-println "Création du sous-corpus avec la liste d'identifiants: $liste_identifiants_sujets"
-String prop = "div_id"
-if (parentCorpusName.startsWith("AFNOTICES") || parentCorpusName.startsWith("AF-NOTICES")) {
-	prop = "notice_identifiantdelanotice"
-}
-
-String query = "[_.$prop=\"$liste_identifiants_sujets\"] expand to $prop"
-println "Requête CQL de création du corpus : $query"
-Subcorpus sub = parentCorpus.createSubcorpus(new CQLQuery(query), nom_sous_corpus)
-
-int s = sub.getSize()
-if (s > 0) {
-	println "Le sous-corpus $nom_sous_corpus a été créé."
-	monitor.syncExec(new Runnable() {
-					public void run() {
-						CorporaView.refresh();
-						CorporaView.expand(parentCorpus);
-					}
-				});
-} else {
-	println "Erreur : Le corpus créé et vide ! >_<'"
-}
\ No newline at end of file
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ImporterCorpusOkapiMacro.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ImporterCorpusOkapiMacro.groovy	(revision 0)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ImporterCorpusOkapiMacro.groovy	(revision 3190)
@@ -0,0 +1,185 @@
+// Copyright © 2021 MY_INSTITUTION
+// Licensed under the terms of the GNU General Public License version 3 (http://www.gnu.org/licenses/gpl-3.0.html)
+// @author mdecorde
+
+// STANDARD DECLARATIONS
+package org.txm.macro.projects.antract
+
+import org.txm.macro.projects.antract.OkapiSaphirAPI
+import org.txm.searchengine.cqp.CQPSearchEngine
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.searchengine.cqp.corpus.CQPCorpus
+import org.txm.searchengine.cqp.corpus.Subcorpus
+import org.txm.searchengine.cqp.corpus.query.CQLQuery
+import org.txm.rcp.views.corpora.CorporaView
+import org.txm.backtomedia.preferences.BackToMediaPreferences
+
+// BEGINNING OF PARAMETERS
+
+@Field @Option(name="liste_identifiants_sujets", usage="Liste des identifiants de notice séparés par des '|'", widget="Text", required=true, def="")
+def liste_identifiants_sujets
+@Field @Option(name="nom_sous_corpus", usage="Nom du sous-corpus à créer", widget="String", required=true, def="")
+def nom_sous_corpus
+//@Field @Option(name="identifiant_corpus_okapi", usage="Identifiant du corpus Okapi à importer", widget="String", required=true, def="")
+//def identifiant_corpus_okapi
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Erreur: la sélection n'est pas un corpus."
+	return false
+} 
+
+CQPCorpus corpus = corpusViewSelection
+corpus.compute()
+CQPCorpus parentCorpus = corpus.getMainCorpus()
+
+String parentCorpusName = parentCorpus.getCqpId()
+
+if (parentCorpusName.startsWith("AF-VOIX-OFF-")) {
+	
+} else if (parentCorpusName.startsWith("AFNOTICES") || parentCorpusName.startsWith("AF-NOTICES")) {
+	
+} else {
+	println "Erreur: le corpus n'est pas un corpus d'AF-VOIX-OFF ni AFNOTICE"
+	return false
+}
+
+// Open the parameters input dialog box
+if (!ParametersDialog.open(this)) return;
+
+
+//monitor.syncExec(new Runnable() {
+//	public void run() {
+//		if (!OkapiSaphirAPI.initializeCredentials(org.eclipse.swt.widgets.Display.getCurrent().getActiveShell(), BackToMediaPreferences.MEDIA_AUTH_LOGIN, BackToMediaPreferences.MEDIA_AUTH_PASSWORD, "OKAPI - Antract", "S'identifier sur la plateforme Okapi.", "OKAPI - Antract", monitor)) {
+//			return null;
+//		}
+//	}
+//});
+//
+//String user = System.getProperty(BackToMediaPreferences.MEDIA_AUTH_LOGIN)
+//String password = System.getProperty(BackToMediaPreferences.MEDIA_AUTH_PASSWORD)
+//if (user == null || user.length() == 0 || password == null || password.length() == 0) {
+//	println "Annulation."
+//}
+//
+//String sessionID = OkapiSaphirAPI.login(user, password)
+//if (sessionID.length() == 0) {
+//	println "Erreur : La session Okapi n'a pu être démarrée."
+//	System.setProperty(BackToMediaPreferences.MEDIA_AUTH_LOGIN, "")
+//	System.setProperty(BackToMediaPreferences.MEDIA_AUTH_PASSWORD, "")
+//}
+//
+//String corpora = OkapiSaphirAPI.get_user_corpus(sessionID, user, null, null, null)
+//if (corpora.length() > 0 ) {
+//	println "CORPORA"
+//	println corpora
+//} else {
+//	println "Erreur : la liste des corpus n'a pas pu être récupérée."
+//}
+
+liste_identifiants_sujets = liste_identifiants_sujets.replace("\n", "|").replace("\t", "|").replace(" ", "|").replaceAll("(\\|)+", "|").trim()
+println "Création du sous-corpus avec la liste: $liste_identifiants_sujets"
+String prop = "div_id"
+if (parentCorpusName.startsWith("AFNOTICES") || parentCorpusName.startsWith("AF-NOTICES")) {
+	prop = "notice_identifiantdelanotice"
+}
+
+liste_identifiants_sujets = (liste_identifiants_sujets.split("\\|") as List)
+liste_identifiants_sujets.remove("")
+liste_identifiants_sujets.unique()
+liste_identifiants_sujets = getShortCQL(liste_identifiants_sujets)
+
+String query = "[_.$prop=\"$liste_identifiants_sujets\"] expand to $prop"
+println "CQL=$query"
+if (query.length() > 15500) {
+	println "Erreur : la requête CQL est trop longue (${query.length()})."
+	return
+}
+Subcorpus sub = parentCorpus.createSubcorpus(new CQLQuery(query), nom_sous_corpus)
+
+int s = sub.getSize()
+if (s > 0) {
+	println "$nom_sous_corpus subcorpus is created."
+	monitor.syncExec(new Runnable() {
+					public void run() {
+						CorporaView.refresh();
+						CorporaView.expand(parentCorpus);
+					}
+				});
+} else {
+	println "Error: the created corpus is empty!"
+}
+
+// UTILS UTILS UTILS UTILS UTILS UTILS UTILS
+
+def getShortCQL(def list) {
+	def origtree = ["":list]
+	breakNode(origtree, "", 0)
+	def CQL1 = list.join("|")
+	def CQL2 = writeNode(origtree)
+	if (CQL1.length() < CQL2.length()) {
+		return CQL1;
+	} else {
+		return CQL2;
+	}
+}
+
+def breakNode(def tree, def key, def p) {
+	def space = (" "*p)
+	//println space + "breaking: $key of $tree at $p"
+		
+	def children = new LinkedHashMap()
+	def ids = tree[key]
+	tree[key] = children
+	
+	for (def child : ids) {
+		//println space+"child="+child
+		if (child.length() <= p) continue;
+		
+		def letter = child[p]
+		if (!children.containsKey(letter)) {
+			children[letter] = []
+		}
+		
+		children[letter].add(child)
+	}
+	
+	for (def k : children.keySet()) {
+		breakNode(children, k , p+1)
+	}
+}
+
+
+def writeNode(def tree) {
+	def s = ""
+	//println "tree: "+tree
+
+	int n = 0;
+	if (tree.size() > 1) s += "("
+	String ss = ""
+	for (def child : tree.keySet()) {
+		if (n > 0) ss += "|"
+		ss += child
+		ss += writeNode(tree[child])
+		n++
+	}
+	
+	if (ss.matches("([0-9]\\|){2,10}[0-9]")) ss = "["+ss.replace("|", "") +"]"
+	if (ss == "[0123456789]") ss = "[0-9]"
+	if (ss == "[123456789]") ss = "[1-9]"
+	if (ss == "[23456789]") ss = "[2-9]"
+	if (ss == "[3456789]") ss = "[3-9]"
+	if (ss == "[0123456789]") ss = "[0-9]"
+	if (ss == "[012345678]") ss = "[0-8]"
+	if (ss == "[01234567]") ss = "[0-7]"
+	if (ss == "[0123456]") ss = "[0-6]"
+	if (ss == "[12345678]") ss = "[1-8]"
+	if (ss == "[1234567]") ss = "[1-7]"
+	s += ss
+	
+	if (tree.size() > 1) s += ")"
+	return s
+}
+
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ListerCorpusOkapiMacro.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ListerCorpusOkapiMacro.groovy	(revision 0)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/macro/projects/antract/ListerCorpusOkapiMacro.groovy	(revision 3190)
@@ -0,0 +1,50 @@
+// Copyright © 2021 MY_INSTITUTION
+// Licensed under the terms of the GNU General Public License version 3 (http://www.gnu.org/licenses/gpl-3.0.html)
+// @author mdecorde
+
+// STANDARD DECLARATIONS
+package org.txm.macro.projects.antract
+
+import org.txm.macro.projects.antract.OkapiSaphirAPI
+import org.txm.searchengine.cqp.CQPSearchEngine
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.searchengine.cqp.corpus.CQPCorpus
+import org.txm.searchengine.cqp.corpus.Subcorpus
+import org.txm.searchengine.cqp.corpus.query.CQLQuery
+import org.txm.rcp.views.corpora.CorporaView
+import org.txm.backtomedia.preferences.BackToMediaPreferences
+
+// BEGINNING OF PARAMETERS
+
+monitor.syncExec(new Runnable() {
+	public void run() {
+		if (!OkapiSaphirAPI.initializeCredentials(org.eclipse.swt.widgets.Display.getCurrent().getActiveShell(), BackToMediaPreferences.MEDIA_AUTH_LOGIN, BackToMediaPreferences.MEDIA_AUTH_PASSWORD, "OKAPI - Antract", "S'identifier sur la plateforme Okapi.", "OKAPI - Antract", monitor)) {
+			return null;
+		}
+	}
+});
+
+String user = System.getProperty(BackToMediaPreferences.MEDIA_AUTH_LOGIN)
+String password = System.getProperty(BackToMediaPreferences.MEDIA_AUTH_PASSWORD)
+if (user == null || user.length() == 0 || password == null || password.length() == 0) {
+	println "Annulation."
+}
+
+String sessionID = OkapiSaphirAPI.login(user, password)
+if (sessionID.length() == 0) {
+	println "Erreur : La session Okapi n'a pu être démarrée."
+	System.setProperty(BackToMediaPreferences.MEDIA_AUTH_LOGIN, "")
+	System.setProperty(BackToMediaPreferences.MEDIA_AUTH_PASSWORD, "")
+}
+
+String corpora = OkapiSaphirAPI.get_user_corpus(sessionID, user, null, null, null)
+if (corpora.length() > 0 ) {
+	println "CORPORA"
+	println corpora
+} else {
+	println "Erreur : la liste des corpus n'a pas pu être récupérée."
+}
+
