Index: tmp/TXMReleasePlugins.site/site.xml
===================================================================
--- tmp/TXMReleasePlugins.site/site.xml	(revision 2081)
+++ tmp/TXMReleasePlugins.site/site.xml	(revision 2082)
@@ -3,10 +3,10 @@
    <description name="TXM Extensions - RELEASE" url="http://txm.textometrie.org/updates/plugins">
       This update site contains the Release plugins for TXM
    </description>
-   <feature url="features/org.txm.backtomedia.feature_1.0.0.1978.jar" id="org.txm.backtomedia.feature" version="1.0.0.1978">
+   <feature url="features/org.txm.backtomedia.feature_1.0.0.2079.jar" id="org.txm.backtomedia.feature" version="1.0.0.2079">
       <category name="Commands"/>
    </feature>
-   <feature url="features/org.txm.wordcloud.feature_1.0.0.1978.jar" id="org.txm.wordcloud.feature" version="1.0.0.1978">
+   <feature url="features/org.txm.wordcloud.feature_1.0.0.2079.jar" id="org.txm.wordcloud.feature" version="1.0.0.2079">
       <category name="Commands"/>
    </feature>
    <feature url="features/org.txm.treetagger.binaries.feature_1.0.0.1978.jar" id="org.txm.treetagger.binaries.feature" version="1.0.0.1978" os="" ws="">
@@ -15,10 +15,10 @@
    <feature url="features/org.txm.treetagger.models.feature_1.0.0.1978.jar" id="org.txm.treetagger.models.feature" version="1.0.0.1978">
       <category name="Annotation"/>
    </feature>
-   <feature url="features/org.txm.annotation.urs.feature_1.0.0.1978.jar" id="org.txm.annotation.urs.feature" version="1.0.0.1978">
+   <feature url="features/org.txm.annotation.urs.feature_1.0.0.2079.jar" id="org.txm.annotation.urs.feature" version="1.0.0.2079">
       <category name="Annotation"/>
    </feature>
-   <feature url="features/org.txm.tigersearch.feature_1.0.0.1978.jar" id="org.txm.tigersearch.feature" version="1.0.0.1978">
+   <feature url="features/org.txm.tigersearch.feature_1.0.0.2079.jar" id="org.txm.tigersearch.feature" version="1.0.0.2079">
       <category name="Annotation"/>
    </feature>
    <category-def name="Commands" label="Commands">
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSResult.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSResult.java	(revision 2081)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TSResult.java	(revision 2082)
@@ -107,21 +107,23 @@
 		this.tsCorpus = tsCorpus;
 
 		result = tsCorpus.manager.processQuery(query);
-		forest = new ResultForest(result, tsCorpus.manager);
-		header = forest.getHeader();
+		if (result.size() > 0) {
+			forest = new ResultForest(result, tsCorpus.manager);
+			header = forest.getHeader();
 
-		matches = new TSMatch[result.size()];
-		tsquerytosvg = new QueryToSvg(manager, result, forest, header, tsCorpus.config);
+			matches = new TSMatch[result.size()];
+			tsquerytosvg = new QueryToSvg(manager, result, forest, header, tsCorpus.config);
+		}
 	}
-	
+
 	public ResultForest getForest() {
 		return forest;
 	}
-	
+
 	public MatchResult getMatchResult() {
 		return result;
 	}
-	
+
 	public InternalCorpusQueryManager getManager() {
 		return manager;
 	}
@@ -265,60 +267,60 @@
 	}
 
 	//TODO move this code somewhere
-//	public static String CONCSIMPLE = "concordance_simple"; //$NON-NLS-1$
-//	public static String CONCMOTPIVOT = "concordance_mot-pivot"; //$NON-NLS-1$
-//	public static String CONCBLOCKS = "concordance_blocks"; //$NON-NLS-1$
-//	public static String[] EXPORTMETHODS = {CONCSIMPLE, CONCMOTPIVOT, CONCBLOCKS};
-//	public boolean toConcordance(File csvFile, String method, int cx, List<String> list, List<String> list2, boolean punct) throws Exception
-//	{
-//		if (!Arrays.asList(EXPORTMETHODS).contains(method)) {
-//			Log.severe(TXMCoreMessages.TSResult_7+method+TXMCoreMessages.TSResult_8+Arrays.toString(EXPORTMETHODS));
-//			return false;
-//		}
-//
-//		File xmlFile = File.createTempFile(csvFile.getName(), "EXPORTBRUT.xml", csvFile.getParentFile()); //$NON-NLS-1$
-//		boolean rez = false;
-//		if (punct) { 
-//			// export match
-//			//System.out.println("save matches in "+xmlFile);
-//			this.toXml(xmlFile, false, true, false, false, true, false, 0);
-//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "EXPORTBRUT.xml"));
-//			// merge with TigerXMLPOSPNC
-//			File tmp = File.createTempFile("txm", "AFTERMINJECT.xml", xmlFile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
-//			File tigerXml = new File(tsCorpus.tsmanager.getRegistryPath(), "TigerPnc.xml"); //$NON-NLS-1$
-//			//System.out.println("TIGER XML: "+tigerXml);
-//			if (!tigerXml.exists()) {
-//				System.out.println(TXMCoreMessages.TSResult_13+tigerXml.getAbsolutePath());
-//				return false;
-//			}
-//			//System.out.println("Match inject: in "+tmp);
-//			new MatchInject().script(tigerXml, xmlFile, tmp);
-//			xmlFile.delete();
-//			tmp.renameTo(xmlFile);
-//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "AFTERMINJECT.xml"));
-//		} else {
-//			this.toXml(xmlFile); // export match + corpus
-//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "FULLEXPORT.xml"));
-//		}
-//
-//		if (!xmlFile.exists()) { System.out.println(TXMCoreMessages.TSResult_14); return false;}
-//
-//		if (method.equals("concordance_blocks")) { //$NON-NLS-1$
-//			ConcordanceBlocks builder = new ConcordanceBlocks();
-//			rez = builder.process(xmlFile, csvFile, cx, list, list2);
-//		} else { // XSL method
-//			File xslDir = new File(TBXPreferences.getInstance().getString(TBXPreferences.USER_TXM_HOME), "xsl"); //$NON-NLS-1$
-//			File xslFile = new File(xslDir, method+".xsl"); //$NON-NLS-1$
-//			if (!xslFile.exists()) {
-//				Log.severe(TXMCoreMessages.TSResult_7+xslFile);
-//				return false;
-//			}
-//
-//			rez = toXml(csvFile, xmlFile, xslFile, punct, cx, list, list2);
-//		}
-//		xmlFile.delete(); // no more needed
-//		return rez;
-//	}
+	//	public static String CONCSIMPLE = "concordance_simple"; //$NON-NLS-1$
+	//	public static String CONCMOTPIVOT = "concordance_mot-pivot"; //$NON-NLS-1$
+	//	public static String CONCBLOCKS = "concordance_blocks"; //$NON-NLS-1$
+	//	public static String[] EXPORTMETHODS = {CONCSIMPLE, CONCMOTPIVOT, CONCBLOCKS};
+	//	public boolean toConcordance(File csvFile, String method, int cx, List<String> list, List<String> list2, boolean punct) throws Exception
+	//	{
+	//		if (!Arrays.asList(EXPORTMETHODS).contains(method)) {
+	//			Log.severe(TXMCoreMessages.TSResult_7+method+TXMCoreMessages.TSResult_8+Arrays.toString(EXPORTMETHODS));
+	//			return false;
+	//		}
+	//
+	//		File xmlFile = File.createTempFile(csvFile.getName(), "EXPORTBRUT.xml", csvFile.getParentFile()); //$NON-NLS-1$
+	//		boolean rez = false;
+	//		if (punct) { 
+	//			// export match
+	//			//System.out.println("save matches in "+xmlFile);
+	//			this.toXml(xmlFile, false, true, false, false, true, false, 0);
+	//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "EXPORTBRUT.xml"));
+	//			// merge with TigerXMLPOSPNC
+	//			File tmp = File.createTempFile("txm", "AFTERMINJECT.xml", xmlFile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
+	//			File tigerXml = new File(tsCorpus.tsmanager.getRegistryPath(), "TigerPnc.xml"); //$NON-NLS-1$
+	//			//System.out.println("TIGER XML: "+tigerXml);
+	//			if (!tigerXml.exists()) {
+	//				System.out.println(TXMCoreMessages.TSResult_13+tigerXml.getAbsolutePath());
+	//				return false;
+	//			}
+	//			//System.out.println("Match inject: in "+tmp);
+	//			new MatchInject().script(tigerXml, xmlFile, tmp);
+	//			xmlFile.delete();
+	//			tmp.renameTo(xmlFile);
+	//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "AFTERMINJECT.xml"));
+	//		} else {
+	//			this.toXml(xmlFile); // export match + corpus
+	//			//FileCopy.copy(xmlFile, new File(xmlFile.getParentFile(), "FULLEXPORT.xml"));
+	//		}
+	//
+	//		if (!xmlFile.exists()) { System.out.println(TXMCoreMessages.TSResult_14); return false;}
+	//
+	//		if (method.equals("concordance_blocks")) { //$NON-NLS-1$
+	//			ConcordanceBlocks builder = new ConcordanceBlocks();
+	//			rez = builder.process(xmlFile, csvFile, cx, list, list2);
+	//		} else { // XSL method
+	//			File xslDir = new File(TBXPreferences.getInstance().getString(TBXPreferences.USER_TXM_HOME), "xsl"); //$NON-NLS-1$
+	//			File xslFile = new File(xslDir, method+".xsl"); //$NON-NLS-1$
+	//			if (!xslFile.exists()) {
+	//				Log.severe(TXMCoreMessages.TSResult_7+xslFile);
+	//				return false;
+	//			}
+	//
+	//			rez = toXml(csvFile, xmlFile, xslFile, punct, cx, list, list2);
+	//		}
+	//		xmlFile.delete(); // no more needed
+	//		return rez;
+	//	}
 
 	public boolean toXml(File outfile) throws ExportException, ExportStopException
 	{
@@ -329,7 +331,7 @@
 	public boolean toXml(File outfile, boolean includeNonMatch, boolean includeMatch, 
 			boolean includeXmlHeader, boolean includeXMLSentenceStructure, 
 			boolean includeXMLMatchInformation, boolean refineSchema, int referSchema) throws ExportException, ExportStopException
-			{
+	{
 		this.tsCorpus.exporter.setConfiguration(includeXmlHeader,
 				includeXMLSentenceStructure,
 				includeXMLMatchInformation,
@@ -337,7 +339,7 @@
 				referSchema);
 		this.tsCorpus.exporter.saveMatchAsXML(result, outfile, includeNonMatch, includeMatch);
 		return true;
-			}
+	}
 
 	public boolean toXml(File outfile, boolean includeNonMatch, boolean includeMatch) throws ExportException, ExportStopException
 	{
@@ -350,51 +352,51 @@
 		return toXml(outfile, includeNonMatch, includeMatch, includeXmlHeader, includeXMLSentenceStructure, includeXMLMatchInformation, refineSchema, referSchema);
 	}
 
-//	@Deprecated
-//	private void injectPunct(File xmlfile)
-//	{
-//		System.out.println(TXMCoreMessages.TSResult_18);
-//		String corpus = this.tsCorpus.id.toUpperCase();
-//		try {
-//			Document dom = DomUtils.load(xmlfile);
-//			//System.out.println("Getting words of "+corpus);
-//			Object words = PunctInject.getWords(corpus, ""); //$NON-NLS-1$
-//
-//			//			int i = 0;
-//			//			for(String[] word : (ArrayList<String[]>)words)
-//			//			{
-//			//				if(i++ % 10 == 0) System.out.println();
-//			//				System.out.print("[\""+word[0]+"\", \""+word[1].replace("\"", "\\\"")+"\"], ");
-//			//			}
-//			File outfile = File.createTempFile("punct", ".xml", xmlfile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
-//			//System.out.println("Processing "+xmlfile+" to "+outfile);
-//			Document doc = (Document) new PunctInject().process(dom, words);
-//			//System.out.println("Saving file");
-//			DomUtils.save(doc, outfile);
-//
-//			//			FileCopy.copy(outfile, new File(outfile.getParentFile(), "afterinject.xml"));
-//
-//			xmlfile.delete();
-//			outfile.renameTo(xmlfile);
-//		} catch (UnsupportedEncodingException e) {
-//			// TODO Auto-generated catch block
-//			org.txm.utils.logger.Log.printStackTrace(e);
-//		} catch (FileNotFoundException e) {
-//			// TODO Auto-generated catch block
-//			org.txm.utils.logger.Log.printStackTrace(e);
-//		} catch (ParserConfigurationException e) {
-//			// TODO Auto-generated catch block
-//			org.txm.utils.logger.Log.printStackTrace(e);
-//		} catch (SAXException e) {
-//			// TODO Auto-generated catch block
-//			org.txm.utils.logger.Log.printStackTrace(e);
-//		} catch (IOException e) {
-//			// TODO Auto-generated catch block
-//			org.txm.utils.logger.Log.printStackTrace(e);
-//		}
-//
-//
-//	}
+	//	@Deprecated
+	//	private void injectPunct(File xmlfile)
+	//	{
+	//		System.out.println(TXMCoreMessages.TSResult_18);
+	//		String corpus = this.tsCorpus.id.toUpperCase();
+	//		try {
+	//			Document dom = DomUtils.load(xmlfile);
+	//			//System.out.println("Getting words of "+corpus);
+	//			Object words = PunctInject.getWords(corpus, ""); //$NON-NLS-1$
+	//
+	//			//			int i = 0;
+	//			//			for(String[] word : (ArrayList<String[]>)words)
+	//			//			{
+	//			//				if(i++ % 10 == 0) System.out.println();
+	//			//				System.out.print("[\""+word[0]+"\", \""+word[1].replace("\"", "\\\"")+"\"], ");
+	//			//			}
+	//			File outfile = File.createTempFile("punct", ".xml", xmlfile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$
+	//			//System.out.println("Processing "+xmlfile+" to "+outfile);
+	//			Document doc = (Document) new PunctInject().process(dom, words);
+	//			//System.out.println("Saving file");
+	//			DomUtils.save(doc, outfile);
+	//
+	//			//			FileCopy.copy(outfile, new File(outfile.getParentFile(), "afterinject.xml"));
+	//
+	//			xmlfile.delete();
+	//			outfile.renameTo(xmlfile);
+	//		} catch (UnsupportedEncodingException e) {
+	//			// TODO Auto-generated catch block
+	//			org.txm.utils.logger.Log.printStackTrace(e);
+	//		} catch (FileNotFoundException e) {
+	//			// TODO Auto-generated catch block
+	//			org.txm.utils.logger.Log.printStackTrace(e);
+	//		} catch (ParserConfigurationException e) {
+	//			// TODO Auto-generated catch block
+	//			org.txm.utils.logger.Log.printStackTrace(e);
+	//		} catch (SAXException e) {
+	//			// TODO Auto-generated catch block
+	//			org.txm.utils.logger.Log.printStackTrace(e);
+	//		} catch (IOException e) {
+	//			// TODO Auto-generated catch block
+	//			org.txm.utils.logger.Log.printStackTrace(e);
+	//		}
+	//
+	//
+	//	}
 
 	public boolean toXml(File outFile, File xmlFile, File xslFile, boolean punct, int cxsize, List<String> list, List<String> list2) throws ExportException, ExportStopException, IOException, TransformerException
 	{
Index: tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TIGERSearchEngine.java
===================================================================
--- tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TIGERSearchEngine.java	(revision 2081)
+++ tmp/org.txm.tigersearch.rcp/src/org/txm/searchengine/ts/TIGERSearchEngine.java	(revision 2082)
@@ -65,33 +65,20 @@
 
 		TSCorpus tcorpus = manager.getCorpus(corpus.getID());
 		TSResult result = tcorpus.query(query.getQueryString());
-		ResultForest forest = result.getForest();
-		System.out.println("TIGERSearch: forest size="+forest.getForestSize());
 		MatchResult mresult = result.getMatchResult();
+		int size = mresult.size();
+		//System.out.println("size: "+size);
+		int subsize = mresult.submatchSize();
+		if (size == 0 || subsize == 0) {
+			return new EmptySelection(query);
+		}
 		
 		InternalCorpusQueryManagerLocal2 tigermanager = tcorpus.manager;
 		CorpusQueryProcessor processor = tigermanager.getQueryProcessor();
 		Index index = processor.getIndex();
 		
-		
-		
-//		Field f = Index.class.getDeclaredField("sentindex");
-//		f.setAccessible(true);
-//		SentenceIndex sentenceIndex = (SentenceIndex) f.get(index);
-//		
-//		Field f2 = Index.class.getDeclaredField("corpus");
-//		f2.setAccessible(true);
-//		CorpusFeatures corpusFeatures = (CorpusFeatures) f2.get(index);
-		
-		System.out.println("MANAGER="+tigermanager.getClass());
-		int nsentences = 0;
-		//int sentence_sizes[] = new int[nsentences];
-		int size = mresult.size();
-		System.out.println("size: "+size);
-		int subsize = mresult.submatchSize();
-		
-		ArrayList<TIGERMatch> tigerMatchesList = new ArrayList<TIGERMatch>();
-		
+		// compute sentence positions
+		//TODO move it to TSCorpus
 		int[] starts = new int[index.getNumberOfGraphs()];
 		for (int i = 0 ; i < index.getNumberOfGraphs() ; i++) {
 			starts[i] = 0;
@@ -99,14 +86,12 @@
 				starts[i] += index.getNumberOfTNodes(i-1) + starts[i-1];
 			}
 		}
-		System.out.println("sent size="+index.getNumberOfGraphs());
 		
-		tcorpus.manager.getSentence(0);
-		
-		System.out.println("submatchSize: "+subsize);
+		ArrayList<TIGERMatch> tigerMatchesList = new ArrayList<TIGERMatch>();
+		//System.out.println("submatchSize: "+subsize);
 		for (int imatch = 0 ; imatch < size; imatch++) { // the matching sentences
 			int sent = mresult.getSentenceNumberAt(imatch);
-			Sentence sentence = tcorpus.manager.getSentence(sent);
+			//Sentence sentence = tcorpus.manager.getSentence(sent);
 			
 			System.out.println(" sent: "+sent);
 			int sent_submatch = mresult.getSentenceSubmatchSize(sent);
@@ -122,65 +107,7 @@
 				tigerMatchesList.add(tigerMatch);
 			}
 		}
-		
-//		
-//		int size = result.getNumberOfMatch();
-//		for (int match_no = 0 ; match_no < size ; match_no++) {
-//			TSMatch match = result.getMatch(match_no);
-////			int sentno = result.getSentenceNumberAt(match_no);
-////			int n = result.getSentenceSubmatchSize(sentno);
-//			System.out.println("Sent: "+match);
-//			int n = match.getNumberOfSubGraph();
-//			for (int iSubMatch=0 ; iSubMatch<n ; iSubMatch++) {
-//				System.out.println("   Sub: "+iSubMatch+" -> "+match.getResult().getMatchResult().getSentenceSubmatchSize(sentence));
-//				match.getCurrentSubMatchNo()
-//			}
-//		}
 
-		//		Display_Sentence match = forest.getCurrentMatch();
-		//		while (match != null) {
-		////			int s = match.getTerminalsSize();
-		////			ArrayList<ims.tiger.corpus.T_Node> terms = match.getTerminals();
-		////			System.out.print("M="+s+"\t");
-		////			for (ims.tiger.corpus.T_Node term : terms) {
-		////				System.out.print(" "+term.getFeature("word"));
-		////			}
-		////			match.get
-		////			System.out.println();
-		//			match.getSe
-		//			match = forest.nextMatch();
-		//		}
-
-		//		int size = forest.getForestSize();
-		//		for ( int match_no = 0 ; match_no < size ; match_no++) {
-		//			int sentno = mresult.getSentenceNumberAt(match_no);
-		//			Sentence sentence = manager.getSentence(sentno);
-		//
-		//			mresult.orderSentenceSubmatches(sentno); 
-		//			int n = mresult.getSentenceSubmatchSize(sentno);
-		//
-		//			for (int iSubMatch=0; iSubMatch<n; iSubMatch++) {
-		//				int[] var_values = mresult.getSentenceSubmatchAt(sentno, iSubMatch);
-		//				int value;
-		//				for (int j=0; j<var_values.length; j++) {
-		//					value = var_values[j];
-		//					if (value>=0) {
-		//						String var_name = mresult.getVariableName(j);
-		//						Node referred = sentence.getNode(value);
-		//						if (p.matcher(var_name).matches()) {
-		//							if (referred instanceof T_Node) {
-		//								matchingTnodesID.add(referred.getFeature(EDITIONID));
-		//							} else if (referred instanceof NT_Node) {
-		//								for (T_Node c : getTerminals((NT_Node) referred, sentence)) {
-		//									matchingTnodesID.add(c.getFeature(EDITIONID));
-		//								}
-		//							}
-		//						}
-		//					}
-		//				}
-		//			}
-		//		}
-
 		return new TIGERSelection(query, tigerMatchesList);
 	}
 
Index: tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/xmltxm/xmltxmLoader.groovy
===================================================================
--- tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/xmltxm/xmltxmLoader.groovy	(revision 2081)
+++ tmp/org.txm.groovy.core/src/groovy/org/txm/scripts/importer/xmltxm/xmltxmLoader.groovy	(revision 2082)
@@ -226,6 +226,7 @@
 			edition.addPage(""+(++i), wordid);
 		}
 	}
+	println ""
 }
 if (MONITOR != null && MONITOR.isCanceled()) { return MONITOR.done(); }
 if (MONITOR != null) MONITOR.worked(20, "FINALIZING")
Index: tmp/org.txm.edition.rcp/src/org/txm/edition/rcp/editors/EditionPanel.java
===================================================================
--- tmp/org.txm.edition.rcp/src/org/txm/edition/rcp/editors/EditionPanel.java	(revision 2081)
+++ tmp/org.txm.edition.rcp/src/org/txm/edition/rcp/editors/EditionPanel.java	(revision 2082)
@@ -1159,7 +1159,7 @@
 
 	public void expandSelectionTo(String[] ids) {
 		// expand selection
-
+		if (ids == null) return;
 		if (ids.length == 0) return;
 		//TODO: enable the feature for Windows computers
 		//if (System.getProperty("os.name").toLowerCase().contains("windows")) return; 
Index: tmp/org.txm.rcp/src/main/java/org/txm/rcp/swt/widget/parameters/ParametersDialog.java
===================================================================
--- tmp/org.txm.rcp/src/main/java/org/txm/rcp/swt/widget/parameters/ParametersDialog.java	(revision 2081)
+++ tmp/org.txm.rcp/src/main/java/org/txm/rcp/swt/widget/parameters/ParametersDialog.java	(revision 2082)
@@ -362,12 +362,12 @@
 		Class c = bean.getClass();
 		for (String name :fieldNames) {
 			Object value = values.get(name);
-			if (value == null) { // no widget or not set by user
-				value = defaultScriptValues.get(name);
-			}
-			if (value == null) { // no default set by script
-				value = defaultValues.get(name);
-			}
+//			if (value == null) { // no widget or not set by user
+//				value = defaultScriptValues.get(name);
+//			}
+//			if (value == null) { // no default set by script
+//				value = defaultValues.get(name);
+//			}
 			//System.out.println("test if args contains name="+name+" "+args.containsKey(name));
 			if (args.containsKey(name)) { // the 'args' variable may contains values set by another Macro
 				value = args.get(name);
Index: tmp/org.txm.analec.rcp/plugin.xml
===================================================================
--- tmp/org.txm.analec.rcp/plugin.xml	(revision 2081)
+++ tmp/org.txm.analec.rcp/plugin.xml	(revision 2082)
@@ -22,153 +22,32 @@
             <menu
                   id="menu.urs.tools"
                   label="Tools">
-               <visibleWhen
-                     checkEnabled="false">
-                  <reference
-                        definitionId="OneCorpusSelected">
-                  </reference>
-               </visibleWhen>
                <menu
                      label="Annotation">
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Annotate concordance"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/edit/ConcordanceToUnitMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Reset annotation"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/edit/ResetAnnotationsMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="SI to Singleton"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/edit/Si2SingletonMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Annotate selection of units"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/edit/UnitsAnnotateMacro.groovy">
-                     </parameter>
-                  </command>
+                  <dynamic
+                        class="org.txm.annotation.urs.commands.URSToolsMenuContribution"
+                        id="edit">
+                  </dynamic>
                </menu>
                <menu
                      label="Verification">
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Check duplicated units in schema"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/edit/CheckDuplicatesInSchemasMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Check annotation structure values"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/edit/CheckAnnotationStructureValuesMacro.groovy">
-                     </parameter>
-                  </command>
+                  <dynamic
+                        class="org.txm.annotation.urs.commands.URSToolsMenuContribution"
+                        id="check">
+                  </dynamic>
                </menu>
                <menu
                      label="Exploitation">
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Units summary"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/exploit/UnitsSummaryMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Units list"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/exploit/UnitsListMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Units index"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/exploit/UnitsIndexMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Schemas progression"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/exploit/SchemasProgressionMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Schemas summary"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/exploit/SchemasSummaryMacro.groovy">
-                     </parameter>
-                  </command>
-               </menu>
-               <menu
-                     label="Export">
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Export to Glozz"
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/export/ExportToGlozzMacro.groovy">
-                     </parameter>
-                  </command>
-                  <command
-                        commandId="org.txm.rcp.commands.ExecuteMacro"
-                        label="Export as..."
-                        style="push">
-                     <parameter
-                           name="org.txm.rcp.command.parameter.file"
-                           value="org/txm/macro/urs/export/ExportAsMacro.groovy">
-                     </parameter>
-                  </command>
-               </menu>
-               <menu
-                     label="Exploitation2">
                   <dynamic
                         class="org.txm.annotation.urs.commands.URSToolsMenuContribution"
                         id="exploit">
                   </dynamic>
                </menu>
                <menu
-                     label="Annotation2">
+                     label="Export">
                   <dynamic
                         class="org.txm.annotation.urs.commands.URSToolsMenuContribution"
-                        id="edit">
+                        id="export">
                   </dynamic>
                </menu>
             </menu>
Index: tmp/org.txm.analec.rcp/META-INF/MANIFEST.MF
===================================================================
--- tmp/org.txm.analec.rcp/META-INF/MANIFEST.MF	(revision 2081)
+++ tmp/org.txm.analec.rcp/META-INF/MANIFEST.MF	(revision 2082)
@@ -171,7 +171,6 @@
  org.txm.macro.urs.democrat,
  org.txm.macro.urs.edit,
  org.txm.macro.urs.exploit,
- org.txm.macro.urs.exploit.mesures1,
  org.txm.macro.urs.export,
  org.txm.macro.urs.misc,
  visuAnalec,
Index: tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/commands/URSToolsMenuContribution.java
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/commands/URSToolsMenuContribution.java	(revision 2081)
+++ tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/commands/URSToolsMenuContribution.java	(revision 2082)
@@ -118,7 +118,7 @@
 		for (File f : files) {
 			if (f.getName().endsWith("Macro.groovy")) {
 				MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
-				menuItem.setText(f.getName().substring(0, f.getName().length()-12).replaceAll("([A-Z])[^A-Z]", " $1"));
+				menuItem.setText(f.getName().substring(0, f.getName().length()-12).replaceAll("([A-Z])([^A-Z])", " $1$2"));
 				menuItem.addSelectionListener(new MacroSelectionAdapter(f));
 			} else if (f.isDirectory()) {
 				MenuItem subMenuItem = new MenuItem(menu, SWT.CASCADE);
Index: tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/commands/ImportTEIAnnotations.java
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/commands/ImportTEIAnnotations.java	(revision 2081)
+++ tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/commands/ImportTEIAnnotations.java	(revision 2082)
@@ -32,7 +32,7 @@
 
 	@Option(name="directory",usage="the directory containing the XML-TEI-URS annotations files", widget="Folder", required=true, def="annotations")
 	File directory;
-	@Option(name="aamFile",usage="The Glozz model file", widget="FileOpen", required=true, def="model.aam")
+	@Option(name="aamFile",usage="The Glozz model file", widget="FileOpen", required=false, def="model.aam")
 	File aamFile;
 	//@Option(name="standoffAnnotations",usage="select this if the directory contains standoff annotation files", widget="Boolean", required=true, def="false")
 	//boolean standoffAnnotations;
Index: tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/imports/URSAnnotationsImporter.java
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/imports/URSAnnotationsImporter.java	(revision 2081)
+++ tmp/org.txm.analec.rcp/src/org/txm/annotation/urs/imports/URSAnnotationsImporter.java	(revision 2082)
@@ -5,9 +5,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 
 import javax.xml.stream.XMLInputFactory;
@@ -15,18 +15,18 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 
-import org.apache.commons.lang.StringUtils;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.txm.Toolbox;
+import org.txm.annotation.urs.URSCorpora;
 import org.txm.importer.PersonalNamespaceContext;
 import org.txm.searchengine.cqp.AbstractCqiClient;
 import org.txm.searchengine.cqp.CQPSearchEngine;
 import org.txm.searchengine.cqp.corpus.MainCorpus;
-import org.txm.searchengine.cqp.corpus.QueryResult;
+import org.txm.searchengine.cqp.corpus.Subcorpus;
 import org.txm.searchengine.cqp.corpus.query.CQLQuery;
-import org.txm.utils.logger.Log;
+import org.txm.utils.ConsoleProgressBar;
 
 import visuAnalec.donnees.Corpus;
+import visuAnalec.donnees.Structure;
 import visuAnalec.elements.Relation;
 import visuAnalec.elements.Schema;
 import visuAnalec.elements.Unite;
@@ -63,15 +63,14 @@
 			return false;
 		}
 		if (!aamFile.exists()) {
-			System.out.println("Error: aamFile does not exist: "+aamFile.getAbsolutePath());
-			return false;
+			System.out.println("Warning: aamFile does not exist: "+aamFile.getAbsolutePath());
+		} else {
+
+			if (!FichiersGlozz.importerModeleGlozz(analecCorpus, aamFile)) {
+				System.out.println("Error while importing Glozz model: "+aamFile);
+				return false;
+			}
 		}
-		
-		if (!FichiersGlozz.importerModeleGlozz(analecCorpus, aamFile)) {
-			System.out.println("Error while importing Glozz model: "+aamFile);
-			return false;
-		}
-		
 		File[] ursFiles = annotationsDirectory.listFiles(new FilenameFilter() {
 			@Override
 			public boolean accept(File dir, String name) {
@@ -93,7 +92,7 @@
 		List<String> cqpTextIds = Arrays.asList(mainCorpus.getCorpusTextIdsList());
 
 		List<Integer> all_result_summary = Arrays.asList(0,0,0,0,0,0,0,0);
-		
+
 		if (monitor != null) monitor.subTask("Processing "+ursFiles.length+" texts...");
 		for (File xmlTXMFile : ursFiles) {
 			String textid = xmlTXMFile.getName().substring(0, xmlTXMFile.getName().length() - 8);
@@ -102,7 +101,7 @@
 				if (monitor != null) monitor.subTask("Processing "+textid+" text...");
 				// N unit, N unit error, N unit no match error, N unit too much match error, N Relation, N Relation error, N Schema, N Schema error
 				List<Integer> result_summary = processText(textid, xmlTXMFile);
-				
+
 				System.out.println(textid+" import report: ");
 				System.out.println(" N Units added: "+result_summary.get(0));
 				System.out.println(" N Units error: "+result_summary.get(1));
@@ -112,14 +111,23 @@
 				System.out.println(" N Relations error: "+result_summary.get(5));
 				System.out.println(" N Schemas added: "+result_summary.get(6));
 				System.out.println(" N Schemas error: "+result_summary.get(7));
-				
+
 				for (int i = 0 ; i < all_result_summary.size() ; i++) all_result_summary.set(i, all_result_summary.get(i)+result_summary.get(i));
 
 			} else {
 				System.out.println("Warning: cannot found text with ID="+textid+" in current CQP corpus.");
 			}
+			
+			if (monitor != null && monitor.isCanceled()) {
+				return false;
+			}
 		}
 		
+		if (!aamFile.exists()) {
+			Vue vue = URSCorpora.getVue(analecCorpus);
+			vue.retablirVueParDefaut();
+		}
+
 		System.out.println("Final import report: ");
 		System.out.println(" N Units added: "+all_result_summary.get(0));
 		System.out.println(" N Units error: "+all_result_summary.get(1));
@@ -133,6 +141,23 @@
 		return true;
 	}
 
+	private int getPosition(Subcorpus textSubcorpus, HashMap<String, int[]> id2position, String id) {
+		int[] positions = id2position.get(id);
+		int start = textSubcorpus.getMatches().get(0).getStart();
+		int end = textSubcorpus.getMatches().get(0).getEnd();
+		if (positions.length == 0) { // no word for id=deb
+			return -1;
+		} 
+		
+		for (int p : positions) {
+			if (start <= p && p <= end) {
+				return p;
+			}
+		}
+		
+		return -2;
+	}
+	
 	private List<Integer> processText(String textid, File xmlTXMFile) throws Exception {
 		AbstractCqiClient CQI = CQPSearchEngine.getCqiClient();
 		// N unit, N unit error, N unit no match error, N unit too much match error, N Relation, N Relation error, N Schema, N Schema error
@@ -144,74 +169,108 @@
 		int nRelationsError = 0;
 		int nSchemaAdded = 0;
 		int nSchemaError = 0;
-		
+
 		unites.clear();
 		relations.clear();
 		schemas.clear();
 		elementProperties.clear();
 
-		if (!parseXMLTXMFile(xmlTXMFile)) return null;
+		if (!parseXMLTXMFile(xmlTXMFile)) return null; // fill unites, relations, schemas and elementProperties
 
-//		if (unites.size() > 0) System.out.println(unites);
-//		if (relations.size() > 0) System.out.println(relations);
-//		if (schemas.size() > 0) System.out.println(schemas);
-//		if (elementProperties.size() > 0) System.out.println(elementProperties);
-//		for (String u : unites.keySet()) if (!elementProperties.containsKey(u+"-fs")) System.out.println("MISSIGN ELEM PROPERTIES: "+u);
-//		for (String u : relations.keySet()) if (!elementProperties.containsKey(u+"-fs")) System.out.println("MISSIGN ELEM PROPERTIES: "+u);
-//		for (String u : schemas.keySet()) if (!elementProperties.containsKey(u+"-fs")) System.out.println("MISSIGN ELEM PROPERTIES: "+u);
+		//		if (unites.size() > 0) System.out.println(unites);
+		//		if (relations.size() > 0) System.out.println(relations);
+		//		if (schemas.size() > 0) System.out.println(schemas);
+		//		if (elementProperties.size() > 0) System.out.println(elementProperties);
+		//		for (String u : unites.keySet()) if (!elementProperties.containsKey(u+"-fs")) System.out.println("MISSIGN ELEM PROPERTIES: "+u);
+		//		for (String u : relations.keySet()) if (!elementProperties.containsKey(u+"-fs")) System.out.println("MISSIGN ELEM PROPERTIES: "+u);
+		//		for (String u : schemas.keySet()) if (!elementProperties.containsKey(u+"-fs")) System.out.println("MISSIGN ELEM PROPERTIES: "+u);
 
+		
+		CQLQuery textQuery = new CQLQuery("[_.text_id=\""+textid+"\"] expand to text");
+		Subcorpus textSubCorpus = mainCorpus.createSubcorpus(textQuery, "TXTTMP");
+		textSubCorpus.compute();
+		
+		HashSet<String> ids = new HashSet<String>();
 		for (String id : unites.keySet()) {
+			ids.add(unites.get(id)[2]);
+			ids.add(unites.get(id)[3]);
+		}
+		String[] idsArray = ids.toArray(new String[ids.size()]);
+		int[] idsIds = CQI.str2Id(mainCorpus.getProperty("id").getQualifiedName(), idsArray);
+		
+		HashMap<String, int[]> id2position = new HashMap<String, int[]>();
+		for (int i = 0 ; i < idsArray.length ; i++) {
+			int[] positions = CQI.id2Cpos(mainCorpus.getProperty("id").getQualifiedName(), idsIds[i]);
+			id2position.put(idsArray[i], positions);
+		}
+		
+		Structure structure = analecCorpus.getStructure();
+		HashSet<String> unitesStructure = structure.getUnites();
+		HashSet<String> relationsStructure = structure.getRelations();
+		HashSet<String> schemasStructure = structure.getSchemas();
+		
+		ConsoleProgressBar cpb = new ConsoleProgressBar(unites.size());
+		for (String id : unites.keySet()) {
+			cpb.tick();
 			String ana = unites.get(id)[0];
 			String type = unites.get(id)[1];
+			if (!unitesStructure.contains(type)) {
+				structure.ajouterType(Unite.class, type);
+			}
 			String deb = unites.get(id)[2];
 			String fin = unites.get(id)[3];
 			if (elementProperties.containsKey(ana)) {
 
-				try {
-					CQLQuery query = new CQLQuery("[_.text_id=\""+textid+"\" & id=\""+deb+"|"+fin+"\"]");
-					QueryResult result = mainCorpus.query(query, "TMP", true);
-					int[] starts = result.getStarts();
-					result.drop();
-					if (starts.length == 1) {
-						//System.out.println("create unite: "+type+" ["+deb+", "+fin+"]");
-						Unite unite = analecCorpus.addUniteSaisie(type, starts[0], starts[0]);
-						HashMap<String, String> props = elementProperties.get(ana);
-						for (String prop : props.keySet()) {
-							unite.putProp(prop, props.get(prop));
+					int start = getPosition(textSubCorpus, id2position, deb);
+					int end = getPosition(textSubCorpus, id2position, deb);
+					
+					if (start < 0) {
+						nUnitsError++;
+						if (start == -1) {
+							System.out.println("WARNING: no position found word id = "+deb);
+							nUnitsNoMatchError++;
+						} else {
+							System.out.println("WARNING: too many positions found for word id = "+deb);
+							nUnitsTooMuchMatchError++;
 						}
-						unitesRef.put(id, unite);
-						nUnitsAdded++;
-					} else if (starts.length == 2) {
-						Unite unite = analecCorpus.addUniteSaisie(type, starts[0], starts[1]);
+					} else if (end < 0) {
+						nUnitsError++;
+						if (end == -1) {
+							System.out.println("WARNING: no position found word id = "+fin);
+							nUnitsNoMatchError++;
+						} else {
+							System.out.println("WARNING: too many positions found for word id = "+fin);
+							nUnitsTooMuchMatchError++;
+						}
+					} else { // OK
+					
 						//System.out.println("create unite: "+type+" ["+deb+", "+fin+"]");
+						Unite unite = analecCorpus.addUniteSaisie(type, start, end);
 						HashMap<String, String> props = elementProperties.get(ana);
+						HashSet<String> nomsProps = structure.getNomsProps(Unite.class, type);
 						for (String prop : props.keySet()) {
+							if (!nomsProps.contains(prop)) {
+								structure.ajouterProp(Unite.class, type, prop);
+							}
 							unite.putProp(prop, props.get(prop));
 						}
 						unitesRef.put(id, unite);
 						nUnitsAdded++;
-					} else {
-						nUnitsError++;
-						if (starts.length == 0) {
-							System.out.println("WARNING: no position found for query "+query+".");
-							nUnitsNoMatchError++;
-						} else {
-							System.out.println("WARNING: too many positions found for query "+query+" -> "+Arrays.toString(starts));
-							nUnitsTooMuchMatchError++;
-						}
 					}
-				} catch(Exception e) {
-					System.out.println("Error while getting word positions of id="+deb+" and id="+fin+": "+e.getLocalizedMessage());
-					Log.printStackTrace(e);
-				}
 			} else {
 				System.out.println("Warning no properties found for element id="+id+" and ana="+ana);
 			}
 		}
+		cpb.done();
 
+		cpb = new ConsoleProgressBar(relations.size());
 		for (String id : relations.keySet()) {
+			cpb.tick();
 			String ana = relations.get(id)[0];
 			String type = relations.get(id)[1];
+			if (!relationsStructure.contains(type)) {
+				structure.ajouterType(Relation.class, type);
+			}
 			String target = relations.get(id)[2];
 
 			if (elementProperties.containsKey(ana)) {
@@ -227,7 +286,11 @@
 
 						Relation relation = analecCorpus.addRelationSaisie(type, elt1, elt2);
 						HashMap<String, String> props = elementProperties.get(ana);
+						HashSet<String> nomsProps = structure.getNomsProps(Relation.class, type);
 						for (String prop : props.keySet()) {
+							if (!nomsProps.contains(prop)) {
+								structure.ajouterProp(Relation.class, type, prop);
+							}
 							relation.putProp(prop, props.get(prop));
 						}
 						nRelationsAdded++;
@@ -242,10 +305,16 @@
 				System.out.println("Warning no properties found for element id="+id);
 			}
 		}
-
+		cpb.done();
+		
+		cpb = new ConsoleProgressBar(schemas.size());
 		for (String id : schemas.keySet()) {
+			cpb.tick();
 			String ana = schemas.get(id)[0];
 			String type = schemas.get(id)[1];
+			if (!schemasStructure.contains(type)) {
+				structure.ajouterType(Schema.class, type);
+			}
 			String target = schemas.get(id)[2];
 			if (elementProperties.containsKey(ana)) {
 				String[] unitsref = target.split(" ");
@@ -264,7 +333,11 @@
 					}
 					analecCorpus.addSchemaLu(schema);
 					HashMap<String, String> props = elementProperties.get(ana);
+					HashSet<String> nomsProps = structure.getNomsProps(Schema.class, type);
 					for (String prop : props.keySet()) {
+						if (!nomsProps.contains(prop)) {
+							structure.ajouterProp(Schema.class, type, prop);
+						}
 						schema.putProp(prop, props.get(prop));
 					}
 					nSchemaAdded++;
@@ -275,10 +348,12 @@
 				System.out.println("Warning no properties found for element id="+id);
 			}
 		}
-
+		cpb.done();
+		
+		textSubCorpus.delete();
 		return Arrays.asList(nUnitsAdded, nUnitsError, nUnitsNoMatchError, nUnitsTooMuchMatchError,
-		nRelationsAdded, nRelationsError,
-		nSchemaAdded, nSchemaError);
+				nRelationsAdded, nRelationsError,
+				nSchemaAdded, nSchemaError);
 	}
 
 	private boolean parseXMLTXMFile(File xmlTXMFile) throws XMLStreamException, MalformedURLException, IOException {
@@ -317,7 +392,7 @@
 					String type = parser.getAttributeValue(null, "type");
 					if (type == null) type = "";
 					if (type.endsWith("-fs"))
-					processMode = 2;
+						processMode = 2;
 				} 
 
 				if (processMode == 1) {
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/AllMesuresMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/AllMesuresMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/AllMesuresMacro.groovy	(revision 2082)
@@ -0,0 +1,132 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+
+import groovy.transform.Field
+
+import org.txm.*
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.searchengine.cqp.corpus.*
+import org.apache.commons.lang.StringUtils;
+
+// BEGINNING OF PARAMETERS
+
+@Field @Option(name="tsvFile",usage="", widget="FileSave", required=true, def="result.tsv")
+File tsvFile
+
+@Field @Option(name="default_schema_ursql", usage="TYPE@PROP=REGEX", widget="String", required=true, def="CHAINE")
+String default_schema_ursql
+
+@Field @Option(name="default_minimum_schema_size", usage="", widget="Integer", required=true, def="3")
+int default_minimum_schema_size
+
+
+@Field @Option(name="schema_property_display_name",usage="", widget="String", required=false, def="REF")
+String schema_property_display_name
+
+@Field @Option(name="default_unit_ursql", usage="TYPE@PROP=REGEX", widget="String", required=false, def="MENTION")
+String default_unit_ursql
+
+@Field @Option(name="default_word_property", usage="", widget="String", required=false, def="word")
+String default_word_property
+@Field @Option(name="default_pos_property", usage="", widget="String", required=false, def="CATEGORIE")
+String default_pos_property
+
+if (!ParametersDialog.open(this)) return;
+// END OF PARAMETERS
+
+println "Corpora selections: "+corpusViewSelections
+
+table = [] // contains all table lines
+mesures = []
+
+for (def corpus : corpusViewSelections) { // for each corpus selected in the corpora view
+	if (!(corpus instanceof MainCorpus)) continue; // check if the corpus is a maincorpus
+	def line = [] ; table << line // create and add a new table line
+	line << corpus.getID() // add the corpus name in the first column
+	
+	println "*** Computing mesures for $corpus" // each macro return a "result" and a "data"
+
+	params = [
+		"unit_ursql":default_unit_ursql,
+	]
+	returnedValue = execMesure(ReferentialDensityMacro, line, corpus, params)
+	line << returnedValue["result"]
+	
+	params = [
+		"schema_ursql":default_schema_ursql,
+		"minimum_schema_size":default_minimum_schema_size,
+		"unit_ursql":default_unit_ursql,
+	]
+	returnedValue = execMesure(MeanDistanceMacro, line, corpus, params)
+	line << returnedValue["result"]
+	
+	params = [
+		"schema_ursql":default_schema_ursql,
+		"minimum_schema_size":default_minimum_schema_size,
+		"unit_ursql":default_unit_ursql,
+	]
+	returnedValue = execMesure(NumberOfSchemaMacro, line, corpus, params)
+	line << returnedValue["result"]
+	
+	params = [
+		"schema_ursql":default_schema_ursql,
+		"minimum_schema_size":default_minimum_schema_size,
+		"schema_property_display_name":schema_property_display_name,
+		"unit_ursql":default_unit_ursql+"@CATEGORIE=GN Défini|GN Démonstratif|Nom Propre",
+		"word_property":default_word_property,
+	]
+	returnedValue = execMesure(StabilityScoreMacro, line, corpus, params)
+	line << returnedValue["result"]
+	
+	params = [
+		"schema_ursql":default_schema_ursql,
+		"minimum_schema_size":default_minimum_schema_size,
+		"unit_ursql":default_unit_ursql,
+	]
+	returnedValue = execMesure(InterDistanceMacro, line, corpus, params)
+	line << returnedValue["result"]
+
+	params = [
+		"schema_ursql":default_schema_ursql,
+		"minimum_schema_size":default_minimum_schema_size,
+		"unit_ursql":default_unit_ursql,
+		"word_property":default_pos_property,
+	]
+	returnedValue = execMesure(NatureOfTheFirstUnitMacro, line, corpus, params)
+	line << returnedValue["data"]
+	
+	params = [
+		"schema_ursql":default_schema_ursql,
+		"minimum_schema_size":default_minimum_schema_size,
+		"schema_property_display_name":schema_property_display_name,
+		"unit_ursql":default_unit_ursql,
+		"word_property":default_pos_property,
+	]
+	returnedValue = execMesure(GrammaticalCategoryMacro, line, corpus, params)
+	line << returnedValue["data"]
+}
+
+// WRITE RESULTS IN THE TSV FILE
+tsvFile.withWriter("UTF-8") { writer ->
+	writer.println "\t"+mesures.join("\t")
+	table.each { line -> writer.println line.join("\t")	}
+}
+
+println "Done. Results are saved in ${tsvFile.getAbsolutePath()} file."
+
+// UTILITY FUNCTIONS
+def execMesure(def mesure, def line, def corpus, def params) {
+	def m = mesure.getSimpleName().substring(0, mesure.getSimpleName().indexOf("Macro"))
+	mesures << m
+	println "***** ${mesures.size()}- $m with parameters: $params"
+	def r = gse.run(mesure, ["args":params, "corpusViewSelection":corpus, "monitor":monitor])
+	if (r == null) throw new Exception("Null result");
+	return r;
+}
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/GrammaticalCategoryMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/GrammaticalCategoryMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/GrammaticalCategoryMacro.groovy	(revision 2082)
@@ -0,0 +1,126 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.*
+import org.txm.macro.urs.AnalecUtils
+import visuAnalec.elements.*
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.searchengine.cqp.*
+import org.txm.searchengine.cqp.corpus.*
+import org.apache.commons.lang.StringUtils;
+
+// BEGINNING OF PARAMETERS
+
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=VALUE", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="schema_display_property_name",usage="", widget="String", required=false, def="REF")
+String schema_display_property_name
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=VALUE", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="property", usage="", widget="String", required=false, def="CATEGORIE")
+String property
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+// Open the parameters input dialog box
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+// END OF PARAMETERS
+
+MainCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def CQI = CQPSearchEngine.getCqiClient()
+
+def prop = corpus.getProperty(property)
+if (prop == null) {
+	analecCorpus.getStructure()
+}
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+def allFreqs = [:]
+def n = 0
+for (def schema : schemas) {
+	n++
+	
+	def freqs = [:]
+		
+	def allUnites = schema.getUnitesSousjacentesNonTriees()
+
+	def units = AnalecUtils.filterElements(debug, allUnites, unit_ursql)
+	
+	for (def unit : units) { // no need to sort units
+
+		String forme =  null;
+		if (prop == null) { // property is the analec unit property to use
+			forme = unit.getProp(property)
+		} else {
+			int[] pos = null;
+			if (unit.getDeb() == unit.getFin()) pos = [unit.getDeb()]
+			else pos = unit.getDeb()..unit.getFin()
+				
+			forme = StringUtils.join(CQI.cpos2Str(prop.getQualifiedName(), pos), " ") // ids is enough
+		}
+		
+		if (!freqs.containsKey(forme)) freqs[forme] = 0;
+		freqs[forme] = freqs[forme] + 1;
+		
+		if (!allFreqs.containsKey(forme)) allFreqs[forme] = 0;
+		allFreqs[forme] = allFreqs[forme] + 1;
+	}
+	
+	if (schema_display_property_name != null) {
+		println "Index des natures de $unit_ursql de '"+schema.getProp(schema_display_property_name)+"' : "
+	} else {
+		println "Index des natures de $schema_ursql - $n : "
+	}
+	
+	int max = 0;
+	def result = "";
+	for (def forme : freqs.sort() { a, b -> -a.value <=> -b.value ?: a.key <=> b.key }) {
+		println forme.key+"\t"+forme.value
+	}
+}
+
+int max = 0;
+def result = "";
+
+println "Index des natures de $schema_ursql : "
+for (def forme : allFreqs.sort() { a, b -> -a.value <=> -b.value ?: a.key <=> b.key }) {
+	println forme.key+"\t"+forme.value
+	if (max < forme.value) {
+		max = forme.value
+		result = "$forme: "+forme.value
+	}
+}
+
+return ["result":result, "data":allFreqs]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/UnitsSummaryMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/UnitsSummaryMacro.groovy	(revision 2081)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/UnitsSummaryMacro.groovy	(revision 2082)
@@ -45,9 +45,9 @@
 		String unit_ursql
 @Field @Option(name="limit_distance_in_schema", usage="Unit distance in schema (0 = no selection, 1 = first after limit, -1 = last before limit, etc.)", widget="Integer", required=true, def="0")
 		int limit_distance_in_schema
-@Field @Option(name="limit_cql", usage="CQL to build structure limits", widget="Query", required=true, def="<div> [] expand to div")
+@Field @Option(name="limit_cql", usage="CQL to build structure limits", widget="Query", required=false, def="")
 		limit_cql
-@Field @Option(name="strict_inclusion", usage="Units must be strictly included into corpus matches", widget="Boolean", required=true, def="true")
+@Field @Option(name="strict_inclusion", usage="Units must be strictly included into corpus matches", widget="Boolean", required=false, def="true")
 		boolean strict_inclusion
 @Field @Option(name="limit_distance", usage="Unit distance to structure limit (0 = no selection, 1 = first after limit, -1 = last before limit, etc.)", widget="Integer", required=true, def="0")
 		int limit_distance
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/SchemasMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/SchemasMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/SchemasMacro.groovy	(revision 2082)
@@ -0,0 +1,120 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import visuAnalec.elements.*
+import org.txm.searchengine.cqp.corpus.*
+import org.txm.macro.urs.AnalecUtils
+import org.txm.Toolbox
+import org.txm.rcp.commands.*
+import org.apache.commons.lang.StringUtils
+import org.txm.searchengine.cqp.CQPSearchEngine
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpus view selection is not a Corpus"
+	return;
+}
+
+// BEGINNING OF PARAMETERS
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=VALUE", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=VALUE", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="word_property", usage="", widget="StringArray", metaVar="word	lemma	frlemma	frolemma	#forme#	id", required=false, def="word")
+String word_property
+
+@Field @Option(name="separator", usage="", widget="String", required=true, def=", ")
+String separator
+
+@Field @Option(name="buildCQL", usage="générer la requête des unités", widget="Boolean", required=true, def='false')
+def buildCQL
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+
+CQPCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def CQI = CQPSearchEngine.getCqiClient()
+
+if (buildCQL) {
+	word_prop = corpus.getProperty("id")
+} else {
+	word_prop = corpus.getProperty(word_property)
+}
+
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+schemas.sort() {it.getProps()}
+def nSchemas = 0
+
+def lens = [:]
+for (def schema : schemas) {
+
+	def allUnites = schema.getUnitesSousjacentesNonTriees()
+	def units = AnalecUtils.filterElements(debug, allUnites, unit_ursql)
+	
+	print schema.getProps().toString()+ ": "
+	def first = true
+	for (def unit : units) {
+
+		String forme =  null;
+
+		if (buildCQL) {
+			int[] pos = null
+			if (unit.getDeb() == unit.getFin()) pos = [unit.getDeb()]
+			else pos = (unit.getDeb()..unit.getFin())
+			def first2= true
+			q = ""
+			pos.each {
+				if (first2) { first2 = false } else { q = q+" " }
+				int[] pos2 = [it]
+				q = q+"["+word_prop+"=\""+CQI.cpos2Str(word_prop.getQualifiedName(), pos2)[0]+"\"]"
+			}
+			if (first) { first = false } else { print "|" }
+			print "("+q+")"
+		} else {
+			if (word_prop == null) { // word_property is the analec unit property to use
+				forme = unit.getProp(word_property)
+			} else {
+				int[] pos = null
+				if (unit.getDeb() == unit.getFin()) pos = [unit.getDeb()]
+				else pos = (unit.getDeb()..unit.getFin())
+				
+					forme = StringUtils.join(CQI.cpos2Str(word_prop.getQualifiedName(), pos), " ") // ids is enough
+			}
+
+			if (first) { first = false } else { print separator }
+			print forme
+		}
+	}
+	println ""
+
+	nSchemas++
+}
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/MeanDistanceMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/MeanDistanceMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/MeanDistanceMacro.groovy	(revision 2082)
@@ -0,0 +1,138 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.macro.urs.AnalecUtils
+import visuAnalec.elements.*
+import org.txm.searchengine.cqp.corpus.*
+import org.txm.Toolbox
+import org.txm.rcp.commands.*
+import org.txm.statsengine.r.core.RWorkspace
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=REGEX", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="schema_property_display", usage="schema property to show", widget="String", required=true, def="REF")
+String schema_property_display
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=REGEX", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+def corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+
+int nSchemas = 0;
+
+def lens = [:]
+def lensnames = [:]
+for (def schema : schemas) {
+
+	def allUnites = schema.getUnitesSousjacentesNonTriees()
+	
+	def units = AnalecUtils.filterElements(debug, allUnites, unit_ursql)
+	
+	int nUnites = units.size();
+		
+	if (!lens.containsKey(nUnites)) {
+		lens[nUnites] = 0;
+		lensnames[nUnites] = [];
+	}
+	
+	lens[nUnites] = lens[nUnites] + 1;
+	lensnames[nUnites] << schema.getProp(schema_property_display)
+	nSchemas++;
+}
+
+//println "nSchemas=$nSchemas"
+def freqs = lens.keySet();
+freqs.sort();
+int t = 0;
+int n = 0;
+//println "Fréquences ("+freqs.size()+")"
+for (def f : freqs) {
+	t += f * lens[f]
+	n += lens[f]
+}
+
+coef = (t/n)
+def slens = lens.sort { a, b -> -a.value <=> -b.value ?: -a.key <=> -b.key }
+def flens = []
+slens.each { key, value -> value.times { flens << key } }
+def nbins = flens.size()*2
+
+def cfreq = 0
+println "Longueur moyenne des chaînes de référence : $t/$n = "+coef
+println "Index hiérarchique des longueurs de chaînes :\nlen\tfreq\tcfreq"
+slens.each { println it.key+"	"+it.value+"	"+(cfreq+=it.value)+"	"+lensnames[it.key] }
+
+def slens2 = slens.sort { a, b -> -a.key <=> -b.key }
+
+def r = RWorkspace.getRWorkspaceInstance()
+
+r.addVectorToWorkspace("len", slens2.keySet() as int[])
+r.addVectorToWorkspace("freq", slens2.values() as int[])
+r.addVectorToWorkspace("flen", flens as int[])
+
+def corpusName = corpus.getID()
+
+def PNGFile = File.createTempFile("txm", ".png", new File(Toolbox.getTxmHomePath(), "results"))
+def PNGFilePath = PNGFile.getAbsolutePath()
+println "PNG file: "+PNGFilePath
+
+def SVGFile = File.createTempFile("txm", ".svg", new File(Toolbox.getTxmHomePath(), "results"))
+def SVGFilePath = SVGFile.getAbsolutePath()
+println "SVG file: "+SVGFilePath
+
+/// BEGINNING OF R SCRIPT
+def script ="""
+hist(flen, xaxt='n', col="gray", xlab="Length", breaks=$nbins, main="$corpusName Longueur des chaînes ($nbins bins)")
+axis(side=1, at=len)
+dev.off()
+"""
+/// END OF R SCRIPT
+
+// execute R script
+r.plot(PNGFile, "png(file = \"${PNGFilePath}\"); "+script)
+r.plot(SVGFile, "svglite(file = \"${SVGFilePath}\"); "+script)
+
+//display the SVG results graphic
+monitor.syncExec(new Runnable() {
+	@Override
+	public void run() { OpenBrowser.openfile(SVGFilePath, corpusName+" Longueur des chaînes") }
+})
+
+return ["result":coef, "data":lens]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/InterDistanceMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/InterDistanceMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/InterDistanceMacro.groovy	(revision 2082)
@@ -0,0 +1,103 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.*
+import org.txm.macro.urs.AnalecUtils
+import visuAnalec.elements.*
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.searchengine.cqp.corpus.*
+import org.apache.commons.lang.StringUtils;
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+// BEGINNING OF PARAMETERS
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=REGEX", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="schema_display_property_name",usage="", widget="String", required=false, def="REF")
+String schema_display_property_name
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=REGEX", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+CQPCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+def distances = [];
+def nDistances = 0
+def cadences = [];
+for (def schema : schemas) {
+	
+	def allUnites = schema.getUnitesSousjacentesNonTriees()
+
+	def units = AnalecUtils.filterElements(debug, allUnites, unit_ursql)
+	
+	Collections.sort(units)
+		
+	for (int i = 0 ; i < units.size() ; i++) {
+		int d1 = 0;
+		int d2 = 0;
+		if (i < units.size()-1) d1 = units[i+1].getDeb() - units[i].getFin();
+		if (d1 < 0) {
+			//println "D1 "+units[i+1].getDeb()+" - "+units[i].getFin()+" = "+d1
+			d1 = 0; // the first unit pass the next one ?
+		}
+		if (i > 0) d2 = units[i].getDeb() - units[i-1].getFin();
+		if (d2 < 0) {
+			//println "D2 "+units[i].getDeb()+" - "+units[i-1].getFin()+" = "+d2
+			d2 = 0; // the first unit pass the next one ?
+		}
+		distances << d1
+		
+		if (d1 < d2) cadences << d1 else cadences << d2
+		
+		nDistances++
+	}
+}
+distances = distances.sort()
+cadences = cadences.sort()
+
+int distances_total = distances.sum()
+int cadences_total = cadences.sum()
+coef = (distances_total / nDistances)
+cadence = (cadences_total / nDistances)
+println "distances $distances"
+println "distance moyenne inter-mayonnaise : $distances_total / $nDistances = $coef"
+println "distance medianne inter-mayonnaise : "+distances[(int)(distances.size() / 2)]
+println "distance quartils : "+distances[0]+" "+distances[(int)(distances.size() / 4)] + " "+distances[(int)(distances.size() / 2)]+" "+distances[(int)(3*distances.size() / 4)]+" "+distances[(int)(distances.size() -1)]
+println "cadences $cadences"
+println "cadence moyenne : $cadences_total / $nDistances = $cadence"
+println "cadence medianne : "+cadences[(int)(cadences.size() / 2)]
+println "cadence quartils : "+cadences[0]+" "+cadences[(int)(cadences.size() / 4)] + " "+cadences[(int)(cadences.size() / 2)]+" "+cadences[(int)(3*cadences.size() / 4)]+" "+cadences[(int)(cadences.size() -1)]
+
+return ["result":coef, "result2":cadence, "data":["distances":distances, "nDistances":nDistances, "cadences":cadences]]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/NatureOfTheFirstUnitMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/NatureOfTheFirstUnitMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/NatureOfTheFirstUnitMacro.groovy	(revision 2082)
@@ -0,0 +1,105 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.*
+import org.txm.macro.urs.AnalecUtils
+import visuAnalec.elements.*
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.searchengine.cqp.corpus.*
+import org.txm.searchengine.cqp.CQPSearchEngine
+import org.apache.commons.lang.StringUtils;
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+// BEGINNING OF PARAMETERS
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=REGEX", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=REGEX", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="word_property", usage="", widget="String", required=false, def="CATEGORIE")
+String word_property
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+
+CQPCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def CQI = CQPSearchEngine.getCqiClient()
+
+def prop = corpus.getProperty(word_property)
+
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+def freqs = [:]
+
+def distances = 0;
+def nDistances = 0
+for (def schema : schemas) {
+	
+	def allUnites = schema.getUnitesSousjacentesNonTriees()
+	
+	def units = AnalecUtils.filterElements(debug, allUnites, unit_ursql)
+	
+	int nUnites = units.size();
+	
+	if (units.size() == 0) continue;
+	
+	def unit = units[0]
+	
+	String forme =  null;
+	if (prop == null) { // word_property is the analec unit property to use
+		forme = unit.getProp(word_property)
+	} else {
+		int[] pos = null;
+		if (unit.getDeb() == unit.getFin()) pos = [unit.getDeb()]
+		else pos = unit.getDeb()..unit.getFin()
+			
+		forme = StringUtils.join(CQI.cpos2Str(prop.getQualifiedName(), pos), " ") // ids is enough
+	}
+	
+	if (!freqs.containsKey(forme)) freqs[forme] = 0;
+	
+	freqs[forme] = freqs[forme] + 1;
+}
+
+println "Index des natures de premier maillon :"
+int max = 0;
+def result = "";
+for (def forme : freqs.keySet().sort() {it -> -freqs[it]}) {
+	println "$forme\t"+freqs[forme]
+	if (max < freqs[forme]) {
+		max = freqs[forme]
+		result = "$forme: "+freqs[forme]
+	}
+}
+
+["result": result, "data": freqs]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/NumberOfSchemaMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/NumberOfSchemaMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/NumberOfSchemaMacro.groovy	(revision 2082)
@@ -0,0 +1,58 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import visuAnalec.elements.*
+import org.txm.searchengine.cqp.corpus.*
+import org.txm.macro.urs.AnalecUtils
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+// BEGINNING OF PARAMETERS
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=REGEX", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=REGEX", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+
+CQPCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+// check Schema parameters
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+
+int nSchemas = schemas.size();
+
+println "Nombre de chaînes de référence d'un texte : $nSchemas"
+
+["result":nSchemas, "data":schemas]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/ReferentialDensityMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/ReferentialDensityMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/ReferentialDensityMacro.groovy	(revision 2082)
@@ -0,0 +1,52 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import visuAnalec.elements.*
+import org.txm.searchengine.cqp.corpus.*
+import org.txm.macro.urs.AnalecUtils
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=VALUE", widget="String", required=false, def="MENTION")
+String unit_ursql
+@Field @Option(name="limit_cql", usage="CQL to build structure limits", widget="Query", required=true, def="<div> [] expand to div")
+limit_cql
+@Field @Option(name="strict_inclusion", usage="Units must be strictly included into corpus matches", widget="Boolean", required=true, def="true")
+strict_inclusion
+@Field @Option(name="limit_distance", usage="Unit distance to structure limit (0 = no selection, 1 = first after limit, -1 = last before limit, etc.)", widget="Integer", required=true, def="0")
+limit_distance
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+
+CQPCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus);
+
+int nMots = corpus.getSize();
+
+def units = AnalecUtils.selectUnitsInSchema(debug, analecCorpus, corpus, "", 0, 0,
+	unit_ursql, 0, limit_cql, strict_inclusion, limit_distance);
+
+int nUnites = units.size();
+
+coef = (nUnites /nMots)
+println "Densité référentielle : nUnites/nMots = $nUnites/$nMots = $coef = ${coef*100}%"
+if (nUnites >= nMots) {
+	println "WARNING: possible encoding error. Number of units ($nUnites) is greater than number of words ($nMots)"
+}
+return ["result":coef, "data":["nUnites":nUnites, "nMots":nMots]]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/StabilityScoreMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/StabilityScoreMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/exploit/StabilityScoreMacro.groovy	(revision 2082)
@@ -0,0 +1,112 @@
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.exploit
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.*
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.searchengine.cqp.corpus.*
+import org.apache.commons.lang.StringUtils;
+import org.txm.macro.urs.AnalecUtils
+import visuAnalec.elements.*
+import org.txm.searchengine.cqp.CQPSearchEngine
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=REGEX", widget="String", required=true, def="CHAINE")
+String schema_ursql
+
+@Field @Option(name="minimum_schema_size", usage="minimal schema size", widget="Integer", required=true, def="3")
+int minimum_schema_size
+
+@Field @Option(name="schema_display_property_name",usage="", widget="String", required=false, def="REF")
+String schema_display_property_name
+
+@Field @Option(name="unit_ursql", usage="TYPE@PROP=REGEX", widget="String", required=false, def="MENTION")
+String unit_ursql
+
+@Field @Option(name="word_property", usage="", widget="String", required=false, def="word")
+String word_property
+
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+debug
+
+if (!ParametersDialog.open(this)) return;
+if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+
+def corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (!AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql)) {
+	println "** The $schema_ursql schema URSQL cannot be computed in the corpus."
+	return;
+}
+
+if (!AnalecUtils.isPropertyDefined(Unite.class, analecCorpus, unit_ursql)) {
+	println "** $unit_ursql unit URSQL cannot be computed in the corpus."
+	return;
+}
+
+def CQI = CQPSearchEngine.getCqiClient()
+
+def prop = corpus.getProperty(word_property)
+
+def schemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus, schema_ursql, minimum_schema_size, 999999);
+allFormesSet = new HashSet();
+nUnitesGrandTotal = 0;
+def coefs = []
+int n = 1
+for (def schema : schemas) {
+	def formesSet = new HashSet(); // contient toutes les formes du CR courant
+	nUnitesTotal = 0;
+	
+	def allUnites = schema.getUnitesSousjacentesNonTriees()
+
+	def units = AnalecUtils.filterElements(debug, allUnites, unit_ursql)
+	def nUnites = units.size()
+	for (def unit : units) {
+	
+		String forme =  null;
+		if (prop == null) { // word_property is the analec unit property to use
+			forme = unit.getProp(word_property)
+		} else {
+			int[] pos = null;
+			if (unit.getDeb() == unit.getFin()) pos = [unit.getDeb()]
+			else pos = unit.getDeb()..unit.getFin()
+				
+			forme = StringUtils.join(CQI.cpos2Str(prop.getQualifiedName(), pos), " ") // ids is enough
+		}
+		
+		formesSet.add(forme)
+		
+		nUnitesTotal++
+	}
+	if (formesSet.size() == 0) {
+		coef = -1
+	} else {
+		coef = (nUnitesTotal/formesSet.size())
+	}
+	coefs << coef
+	nUnitesGrandTotal += nUnitesTotal;
+	allFormesSet.addAll(formesSet)
+	
+	if (schema_display_property_name != null) {
+		print schema.getProp(schema_display_property_name)
+	} else {
+		print schema_ursql+"-"+n+" : "
+	}
+	
+	println " ($nUnites units) : $nUnitesTotal selected units / ${formesSet.size()} forms = $coef"
+	n++
+}
+
+return ["result":coefs, "data":["nUnitesTotal":nUnitesGrandTotal, "allFormesSet":allFormesSet], "coef":(nUnitesGrandTotal/allFormesSet.size())]
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/edit/CheckDuplicatesInSchemasMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/edit/CheckDuplicatesInSchemasMacro.groovy	(revision 2081)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/edit/CheckDuplicatesInSchemasMacro.groovy	(revision 2082)
@@ -1,102 +0,0 @@
-package org.txm.macro.urs.edit
-
-// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
-// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
-// @author mdecorde
-// @author sheiden
-// STANDARD DECLARATIONS
-
-import groovy.transform.Field
-
-import org.jfree.chart.JFreeChart
-import org.kohsuke.args4j.*
-import org.txm.Toolbox
-import org.txm.annotation.urs.*
-import org.txm.macro.urs.AnalecUtils
-import org.txm.rcp.Application
-import org.txm.rcp.IImageKeys
-import org.txm.rcp.swt.widget.parameters.*
-import org.txm.searchengine.cqp.CQPSearchEngine
-import org.txm.searchengine.cqp.corpus.*
-import org.txm.searchengine.cqp.corpus.query.CQLQuery
-
-import visuAnalec.elements.*
-
-def scriptName = this.class.getSimpleName()
-
-if (!(corpusViewSelection instanceof CQPCorpus)) {
-	println "** $scriptName please select a Corpus to run the macro"
-	return;
-}
-
-// BEGINNING OF PARAMETERS
-@Field @Option(name="schema_ursql", usage="TYPE@PROP=VALUE", widget="String", required=true, def="CHAINE")
-		String schema_ursql
-@Field @Option(name="schema_property_display", usage="PROP", widget="String", required=true, def="REF")
-		String schema_property_display
-@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
-		debug
-if (!ParametersDialog.open(this)) return
-	if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
-
-def CQI = CQPSearchEngine.getCqiClient()
-
-def corpus = corpusViewSelection
-
-def word = corpus.getWordProperty()
-def analecCorpus = URSCorpora.getCorpus(corpus)
-
-if (schema_property_display.length() > 0) {
-	def errors = AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql, schema_property_display).size()
-	if (errors > 0) {
-		println "Error: some Schema types don't contain the $schema_property_display property: $errors"
-		return
-	}
-}
-
-def allUnits = [:]
-
-def allSchemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus , schema_ursql, -1, Integer.MAX_VALUE)
-
-if (allSchemas.size() == 0) {
-	println "No schema match for '$schema_ursql' selection. Aborting"
-	return
-}
-
-allUnits = AnalecUtils.groupAllUnitesInElements(debug, allSchemas)
-
-if (allUnits.size() == 0) {
-	println "No unit selection. Aborting"
-	return
-}
-
-if (debug) println "allUnits=${allUnits.size()}"
-
-def duplicates = [:]
-for (Schema schema : allSchemas) {
-	def units = allUnits[schema];
-	for (def unit : units) {
-		if (!duplicates.containsKey(unit)) duplicates[unit] = []
-		duplicates[unit] << schema
-	}
-}
-
-def units = []
-units.addAll(duplicates.keySet()) // remove non duplicates from hash
-for (def unit : units) {
-	if (duplicates[unit].size() < 2) duplicates.remove(unit)
-}
-
-if (duplicates.size() > 0) {
-	println "Duplicates found"
-	for (def unit : duplicates.keySet()) {
-		println AnalecUtils.toString(CQI, word, unit)+" in: "
-		for (Schema schema : duplicates[unit]) {
-			println " '"+schema.getProp(schema_property_display)+"'\t"+schema.getProps()
-		}
-	}
-} else {
-	println "No duplicates found in $schema_ursql units"
-}
-
-return duplicates
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/edit/CheckAnnotationStructureValuesMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/edit/CheckAnnotationStructureValuesMacro.groovy	(revision 2081)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/edit/CheckAnnotationStructureValuesMacro.groovy	(revision 2082)
@@ -1,69 +0,0 @@
-// STANDARD DECLARATIONS
-package org.txm.macro.urs.edit
-
-import org.kohsuke.args4j.*
-import groovy.transform.Field
-import org.txm.rcp.swt.widget.parameters.*
-import org.txm.annotation.urs.*
-import org.txm.searchengine.cqp.corpus.*
-import visuAnalec.elements.*
-
-if (!(corpusViewSelection instanceof MainCorpus)) {
-	println "Corpora selection is not a Corpus"
-	return;
-}
-
-@Field @Option(name="unit_type",usage="", widget="String", required=false, def="MENTION")
-String unit_type
-
-@Field @Option(name="unit_property_name", usage="", widget="String", required=false, def="REF")
-String unit_property_name
-
-@Field @Option(name="pruneUnusedValues", usage="", widget="Boolean", required=false, def="false")
-boolean pruneUnusedValues
-
-// Open the parameters input dialog box
-if (!ParametersDialog.open(this)) return;
-
-// END OF PARAMETERS
-
-MainCorpus corpus = corpusViewSelection
-def analecCorpus = URSCorpora.getCorpus(corpus);
-def structure = analecCorpus.getStructure()
-
-def unit_types = structure.getTypes(Unite.class);
-if (!unit_types.contains(unit_type)) {
-	println "Missing unit type: $unit_type"
-	return
-}
-
-def props = analecCorpus.getStructure().getUniteProperties(unit_type);
-if (!props.contains(unit_property_name)) {
-	println "No properties '$unit_property_name' in '$unit_type' unit."
-	return
-}
-
-def prop  = unit_property_name
-	
-def tmpvalues = new HashSet()
-tmpvalues.addAll(structure.getValeursProp(Unite.class, unit_type, prop));
-println "Values stored in the structure: $tmpvalues"
-	
-def used_values = new HashSet();
-def unites = analecCorpus.getUnites(unit_type);
-for (Unite unite : unites) {
-	used_values.add(unite.getProp(prop))
-}
-	
-tmpvalues.removeAll(used_values);
-if (tmpvalues.size() > 0) {
-	println "The following values ("+tmpvalues.size()+") are not used: "+tmpvalues.join(", ")
-	if (pruneUnusedValues) {
-		println "Pruning the values..."
-		for (String val : tmpvalues) {
-			structure.supprimerVal(Unite.class, unit_type, unit_property_name, val);
-		}
-	} 
-} else {
-	println "All the values are used."
-}
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/check/CheckDuplicatesInSchemasMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/check/CheckDuplicatesInSchemasMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/check/CheckDuplicatesInSchemasMacro.groovy	(revision 2082)
@@ -0,0 +1,102 @@
+package org.txm.macro.urs.check
+
+// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
+// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
+// @author mdecorde
+// @author sheiden
+// STANDARD DECLARATIONS
+
+import groovy.transform.Field
+
+import org.jfree.chart.JFreeChart
+import org.kohsuke.args4j.*
+import org.txm.Toolbox
+import org.txm.annotation.urs.*
+import org.txm.macro.urs.AnalecUtils
+import org.txm.rcp.Application
+import org.txm.rcp.IImageKeys
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.searchengine.cqp.CQPSearchEngine
+import org.txm.searchengine.cqp.corpus.*
+import org.txm.searchengine.cqp.corpus.query.CQLQuery
+
+import visuAnalec.elements.*
+
+def scriptName = this.class.getSimpleName()
+
+if (!(corpusViewSelection instanceof CQPCorpus)) {
+	println "** $scriptName please select a Corpus to run the macro"
+	return;
+}
+
+// BEGINNING OF PARAMETERS
+@Field @Option(name="schema_ursql", usage="TYPE@PROP=VALUE", widget="String", required=true, def="CHAINE")
+		String schema_ursql
+@Field @Option(name="schema_property_display", usage="PROP", widget="String", required=true, def="REF")
+		String schema_property_display
+@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF	ON	ALL	REALLY ALL", required=true, def="OFF")
+		debug
+if (!ParametersDialog.open(this)) return
+	if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3
+
+def CQI = CQPSearchEngine.getCqiClient()
+
+def corpus = corpusViewSelection
+
+def word = corpus.getWordProperty()
+def analecCorpus = URSCorpora.getCorpus(corpus)
+
+if (schema_property_display.length() > 0) {
+	def errors = AnalecUtils.isPropertyDefined(Schema.class, analecCorpus, schema_ursql, schema_property_display).size()
+	if (errors > 0) {
+		println "Error: some Schema types don't contain the $schema_property_display property: $errors"
+		return
+	}
+}
+
+def allUnits = [:]
+
+def allSchemas = AnalecUtils.selectSchemasInCorpus(debug, analecCorpus, corpus , schema_ursql, -1, Integer.MAX_VALUE)
+
+if (allSchemas.size() == 0) {
+	println "No schema match for '$schema_ursql' selection. Aborting"
+	return
+}
+
+allUnits = AnalecUtils.groupAllUnitesInElements(debug, allSchemas)
+
+if (allUnits.size() == 0) {
+	println "No unit selection. Aborting"
+	return
+}
+
+if (debug) println "allUnits=${allUnits.size()}"
+
+def duplicates = [:]
+for (Schema schema : allSchemas) {
+	def units = allUnits[schema];
+	for (def unit : units) {
+		if (!duplicates.containsKey(unit)) duplicates[unit] = []
+		duplicates[unit] << schema
+	}
+}
+
+def units = []
+units.addAll(duplicates.keySet()) // remove non duplicates from hash
+for (def unit : units) {
+	if (duplicates[unit].size() < 2) duplicates.remove(unit)
+}
+
+if (duplicates.size() > 0) {
+	println "Duplicates found"
+	for (def unit : duplicates.keySet()) {
+		println AnalecUtils.toString(CQI, word, unit)+" in: "
+		for (Schema schema : duplicates[unit]) {
+			println " '"+schema.getProp(schema_property_display)+"'\t"+schema.getProps()
+		}
+	}
+} else {
+	println "No duplicates found in $schema_ursql units"
+}
+
+return duplicates
\ No newline at end of file
Index: tmp/org.txm.analec.rcp/src/org/txm/macro/urs/check/CheckAnnotationStructureValuesMacro.groovy
===================================================================
--- tmp/org.txm.analec.rcp/src/org/txm/macro/urs/check/CheckAnnotationStructureValuesMacro.groovy	(revision 0)
+++ tmp/org.txm.analec.rcp/src/org/txm/macro/urs/check/CheckAnnotationStructureValuesMacro.groovy	(revision 2082)
@@ -0,0 +1,69 @@
+// STANDARD DECLARATIONS
+package org.txm.macro.urs.check
+
+import org.kohsuke.args4j.*
+import groovy.transform.Field
+import org.txm.rcp.swt.widget.parameters.*
+import org.txm.annotation.urs.*
+import org.txm.searchengine.cqp.corpus.*
+import visuAnalec.elements.*
+
+if (!(corpusViewSelection instanceof MainCorpus)) {
+	println "Corpora selection is not a Corpus"
+	return;
+}
+
+@Field @Option(name="unit_type",usage="", widget="String", required=false, def="MENTION")
+String unit_type
+
+@Field @Option(name="unit_property_name", usage="", widget="String", required=false, def="REF")
+String unit_property_name
+
+@Field @Option(name="pruneUnusedValues", usage="", widget="Boolean", required=false, def="false")
+boolean pruneUnusedValues
+
+// Open the parameters input dialog box
+if (!ParametersDialog.open(this)) return;
+
+// END OF PARAMETERS
+
+MainCorpus corpus = corpusViewSelection
+def analecCorpus = URSCorpora.getCorpus(corpus);
+def structure = analecCorpus.getStructure()
+
+def unit_types = structure.getTypes(Unite.class);
+if (!unit_types.contains(unit_type)) {
+	println "Missing unit type: $unit_type"
+	return
+}
+
+def props = analecCorpus.getStructure().getUniteProperties(unit_type);
+if (!props.contains(unit_property_name)) {
+	println "No properties '$unit_property_name' in '$unit_type' unit."
+	return
+}
+
+def prop  = unit_property_name
+	
+def tmpvalues = new HashSet()
+tmpvalues.addAll(structure.getValeursProp(Unite.class, unit_type, prop));
+println "Values stored in the structure: $tmpvalues"
+	
+def used_values = new HashSet();
+def unites = analecCorpus.getUnites(unit_type);
+for (Unite unite : unites) {
+	used_values.add(unite.getProp(prop))
+}
+	
+tmpvalues.removeAll(used_values);
+if (tmpvalues.size() > 0) {
+	println "The following values ("+tmpvalues.size()+") are not used: "+tmpvalues.join(", ")
+	if (pruneUnusedValues) {
+		println "Pruning the values..."
+		for (String val : tmpvalues) {
+			structure.supprimerVal(Unite.class, unit_type, unit_property_name, val);
+		}
+	} 
+} else {
+	println "All the values are used."
+}
\ No newline at end of file
