Salome HOME
8275cb40257f7eed3a40e5468282a356a401aa2b
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / som / Document.java
1 package org.splat.som;
2 /**
3  * 
4  * @author    Daniel Brunier-Coulin
5  * @copyright OPEN CASCADE 2012
6  */
7
8 import java.text.DecimalFormat;
9 import java.text.SimpleDateFormat;
10 import java.util.Arrays;
11 import java.util.Calendar;
12 import java.util.Date;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Vector;
16
17 import org.hibernate.Hibernate;
18 import org.hibernate.Session;
19
20 import org.splat.kernel.NotApplicableException;
21 import org.splat.kernel.Persistent;
22 import org.splat.kernel.Relation;
23 import org.splat.kernel.InvalidPropertyException;
24 import org.splat.kernel.MissedPropertyException;
25 import org.splat.kernel.MultiplyDefinedException;
26 import org.splat.kernel.User;
27 import org.splat.manox.Reader;
28 import org.splat.manox.Toolbox;
29 import org.splat.som.ProjectSettings.FileNaming;
30 import org.splat.som.Timestamp.ComparatorByDate;
31
32
33 public class Document extends Entity {
34
35 //  Persistent fields
36         private DocumentType    type;              // User expendable types
37         private File            myfile;
38     private String          did;
39     private int             step;
40     private ProgressState   state;
41     private String          name;
42     private String          version;
43     private int             countag;
44     private int             history;
45     private User            author;
46     private Date            lasdate;
47
48 //  Transient fields
49     public static String    suformat = "00";   // Format of the suffix number of document did and file name
50
51 //  ==============================================================================================================================
52 //  Construction
53 //  ==============================================================================================================================
54
55 //  Fields initialization class
56     public static class Properties extends Persistent.Properties {
57 //  ------------------------------------------------------------
58       private   DocumentType         type    = null;
59       private   String               did     = null;   // Only for searching from a given reference
60       private   ProjectElement       owner   = null;   // Only for constructing a document
61       private   ProjectSettings.Step step    = null;
62       private   ProgressState        state   = null;
63       private   String               name    = null;
64       protected String               format  = null;
65       private   String               version = null;
66       private   User                 author  = null;
67       protected Date                 date    = null;
68       private   String               summary = null;   // Only for versioning a document
69       private   String               path    = null;   // Only for searching from a given path
70
71 //  - Public services
72
73       public void clear () {
74         super.clear();
75         type    = null;
76         did     = null;
77         owner   = null;
78         step    = null;
79         state   = null;
80         name    = null;
81         format  = null;
82         version = null;
83         author  = null;
84         date    = null;
85         summary = null;
86         path    = null;
87       }
88       public Properties copy () {
89         Properties copy = new Properties();
90         copy.type    = this.type;
91         copy.did     = this.did;
92         copy.owner   = this.owner;
93         copy.step    = this.step;
94         copy.state   = this.state;
95         copy.name    = this.name;
96         copy.format  = this.format;
97         copy.version = this.version;
98         copy.author  = this.author;
99         copy.date    = this.date;
100         copy.summary = this.summary;
101         copy.path    = this.path;
102         return copy;
103       }
104 //  - Protected services
105
106       protected User getAuthor () {
107         return author;
108       }
109       protected String getDescription () {
110         return summary;
111       }
112       protected String getLocalPath () {
113         return path;
114       }
115           protected String getReference () {
116                 return did;
117           }
118           protected ProjectSettings.Step getStep () {
119                 return step;
120           }
121           protected DocumentType getType () {
122         return type;
123       }
124 //  - Property setters
125       
126       public Properties setAuthor (User user)
127       {
128         this.author = user;
129         return this;
130       }
131       public Properties setDate (Date date)
132       {
133         this.date = date;
134         return this;
135       }
136       public Properties setDescription (String summary) throws InvalidPropertyException
137       {
138         if (summary.length() == 0) throw new InvalidPropertyException("description");
139         this.summary = summary;
140         return this;
141       }
142       protected Properties setDocument (Document base)
143       {
144         type    = base.type;
145         step    = ProjectSettings.getStep(base.step);
146         name    = base.name;
147         format  = base.getFormat();
148         state   = ProgressState.inWORK;   // For incrementing the version number at save time
149         version = base.version;
150         return this;
151       }
152       public Properties setExternReference (String ref) throws InvalidPropertyException
153       {
154         if (ref.length() == 0)                     throw new InvalidPropertyException("reference");
155         if (ref.equals(new Revision().toString())) throw new InvalidPropertyException("reference");   // Internal version number
156         this.version = ref;
157         return this;
158       }
159       public Properties setFormat (String format) throws InvalidPropertyException
160       {
161         if (format.length() == 0) throw new InvalidPropertyException("format");
162         this.format = format;
163         return this;
164       }
165 //    Required only for passing search arguments
166       public Properties setLocalPath (String path) throws InvalidPropertyException
167       {
168         if (path.length() == 0) throw new InvalidPropertyException("path");
169         this.path = path;
170         return this;
171       }
172       public Properties setName (String name) throws InvalidPropertyException
173       {
174         if (name.length() == 0) throw new InvalidPropertyException("name");
175         this.name = name;
176         return this;
177       }
178       protected Properties setOwner (ProjectElement owner)
179       {
180         this.owner = owner;
181         return this;
182       }
183 //    Required only for passing search arguments
184       public Properties setReference (String did) throws InvalidPropertyException
185       {
186         if (did.length() == 0) throw new InvalidPropertyException("reference");
187         this.did = did;
188         return this;
189       }
190       public Properties setState (ProgressState state) throws InvalidPropertyException
191       {
192         if (state == ProgressState.inPROGRESS || state == ProgressState.TEMPLATE) throw new InvalidPropertyException("state");  // Non document states
193         this.state = state;
194         return this;
195       }
196       protected Properties setStep (ProjectSettings.Step step)
197       {
198         this.step = step;
199         return this;
200       }
201       public Properties setType (DocumentType type)
202       {
203         this.type = type;
204         return this;
205       }
206 //  - Global validity check
207
208       public void checkValidity() throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException
209       {
210         if (type == null)   throw new MissedPropertyException("type");
211         if (owner == null)  throw new MissedPropertyException("owner");
212         if (step == null)   throw new MissedPropertyException("step");
213         if (author == null) throw new MissedPropertyException("author");
214         if (format == null) throw new MissedPropertyException("format");        
215         if (owner instanceof Study && !step.appliesTo(Study.class)) throw new InvalidPropertyException("step");
216         if (!type.isContentInto(step))                              throw new InvalidPropertyException("step");
217         if (state != null && state != ProgressState.EXTERN) {
218 //        inDRAFT, inCHECK or APPROVED + version = imposed version (future use)
219 //        inWORK + version = base version incremented at save time (used for versioning)
220           if (version == null) throw new InvalidPropertyException("state");
221         }
222         if (version != null) {
223           if (state == null) state = ProgressState.EXTERN;
224         }
225       }
226     }
227 //  Database fetch constructor
228     protected Document () {
229     }
230 //  Internal constructor
231     protected Document (Properties dprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException {
232 //  -------------------------------------
233       super(dprop);                                          // Throws one of the above exception if not valid
234       myfile    = new File(null, dprop.format, dprop.date);  // The path is initialized below
235       type      = dprop.type;
236       step      = dprop.step.getNumber();
237       name      = dprop.name;
238       version   = dprop.version;
239       author    = dprop.author;
240       countag   = 0;
241       history   = 0;
242       lasdate   = myfile.getDate();                          // Today if not defined in the properties
243
244       state = dprop.state;
245       if (state == null) {
246           state   = ProgressState.inWORK;                    // Promoted when saving this document
247           version = new Revision().toString();
248       }
249       Study owner = null;
250       if (dprop.owner instanceof Study)  owner =  (Study)dprop.owner;
251       else                               owner = ((Scenario)dprop.owner).getOwnerStudy();
252
253           ProjectSettings.Step step     = ProjectSettings.getStep(this.step);
254       SimpleDateFormat     tostring = new SimpleDateFormat("yyyy");
255           String               year     = tostring.format(owner.getDate());
256       if (name == null) {                                    // Newed document
257         this.name    = "%n";                                 // Named later at publication
258         this.history = -1;                                   // Marks the document as undefined for future assignment
259       }
260       String  filename = generateEncodedName(owner);
261       String  path;
262
263       path = owner.getReference();
264       did  = new StringBuffer(path).append(".%").append(suformat).toString();                       // Document reference
265       path = new StringBuffer(year).append("/").append(path).append("/").append(step.getPath())     // File path relative to the repository vault
266                                    .append(filename).append(".").append(myfile.getFormat())         // File name and extension
267                                    .toString();
268       myfile.changePath(path);
269     }
270
271 //  ==============================================================================================================================
272 //  Public member functions
273 //  ==============================================================================================================================
274
275     public File getAttachedFile (String format) {
276 //  -------------------------------------------
277       List<Relation> exports = getRelations(ConvertsRelation.class);
278
279       for (Iterator<Relation> i=exports.iterator(); i.hasNext(); ) {
280         File export = (File)i.next().getTo();
281         if  (export.getFormat().equals(format)) return export;
282       }
283       return null;
284     }
285
286     public User getAuthor () {
287 //  ------------------------
288       return author;
289     }
290
291     public Date getCreationDate () {
292 //  ------------------------------
293       return myfile.getDate();
294     }
295
296     public Date getLastModificationDate () {
297 //  --------------------------------------
298       return lasdate;
299     }
300
301     public String getFormat () {
302 //  --------------------------
303       return myfile.getFormat();
304     }
305
306     public Document getPreviousVersion () {
307 //  -------------------------------------
308       Relation previous = getFirstRelation(VersionsRelation.class);
309       if (previous != null) return (Document)previous.getTo();
310       else                  return null;
311     }
312
313     public ProgressState getProgressState () {
314 //  ----------------------------------------
315       return state;
316     }
317
318 /**
319  * Returns the path where all physical files attached to this document are saved.
320  * This path is relative to the vault of the repository and include the file name, without extension, common
321  * to all physical files attached to this document.
322  * 
323  * @return the path of the document
324  */
325     public String getRelativePath () {
326 //  --------------------------------
327       String[]     table = myfile.getRelativePath().split("\\x2E");
328       StringBuffer path  = new StringBuffer(table[0]);
329       for (int i=1; i<table.length-1; i++) path.append('.').append(table[i]);
330       return  path.toString();
331     }
332
333 /**
334  * Returns the global unique reference of this document lineage.
335  * The document reference is common to all versions of the document (versioning a document does not change its reference).
336  * It is made of the owner study reference suffixed by a document identifier unique in the scope of the study.
337  * 
338  * @return the document reference
339  */
340     public String getReference () {
341 //  -----------------------------
342       return did;
343     }
344
345     public java.io.File getSaveDirectory () {
346 //  ---------------------------------------
347       String   mypath = Database.getRepositoryVaultPath() + myfile.getRelativePath();
348       String[] table  = mypath.split("/");
349
350 //    Cutting the filename
351       StringBuffer path = new StringBuffer(table[0]);
352       for (int i=1; i<table.length-1; i++) path = path.append("/").append(table[i]);
353       return new java.io.File(path.append("/").toString());
354     }
355
356     public File getSourceFile () {
357 //  ----------------------------
358       return myfile;
359     }
360
361 /**
362  * Returns the stamps such as review and approval attached to this document, if exist.
363  * If several stamps exist, they are returned in ascending order of dates.
364  * 
365  * @return the stamps of the document in ascending order of dates, or an empty array if no stamp exist.
366  */
367     public Timestamp[] getStamps () {
368 //  -------------------------------
369       Vector<Timestamp> stamps = new Vector<Timestamp>();
370
371       for (Iterator<Relation> i=this.getAllRelations().iterator(); i.hasNext(); ) {
372         Relation link = i.next();
373         if (link instanceof StampRelation) stamps.add( ((StampRelation)link).getTo() );
374       } 
375       Timestamp[]       result = stamps.toArray( new Timestamp[stamps.size()] );
376       ComparatorByDate  bydate = new Timestamp.ComparatorByDate();
377
378       Arrays.sort(result, bydate);
379       return result;
380     }
381
382 /**
383  * Returns the title of this document.
384  * 
385  * @return the document title, or an empty string is this document is undefined.
386  * @see #isUndefined()
387  */
388     public String getTitle () {
389 //  -------------------------
390       if (this.isUndefined()) return  "";
391       else                    return  name;
392     }
393
394     public DocumentType getType () {
395 //  ------------------------------
396       return type;
397     }
398
399 /**
400  * Returns the version number of this document.
401  * The version number, when exists, is either of the internal form (m.n.s) usable for building a Revision object, or any string
402  * in case of external document (document with EXTERN state).<br/>
403  * <br/>
404  * Note: document slots have a version number equal to "0.0.0".
405  * 
406  * @return the version number of this document, or null if this is EXTERN.
407  * @see #isUndefined()
408  */
409     public String getVersion () {
410 //  ---------------------------
411       return version;
412     }
413
414 /**
415  * Returns true if this document is undefined.
416  * An undefined document is a meta-document created for reserving the persistent reference of a new document before saving
417  * (or importing) this later into the repository.
418  * The working copy of a such document may include this reference.
419  * 
420  * @see #getTitle()
421  * @see #getVersion()
422  * @see #initialize(Properties)
423  */
424     public boolean isUndefined () {
425 //  -----------------------------
426       return (history == -1);
427     }
428
429     public boolean isInto (Step container) {
430 //  --------------------------------------
431       return (step == container.getNumber());
432     }
433
434     public boolean isPublished () {
435 //  -----------------------------
436       return (countag > 0);
437     }
438
439     public boolean isShared () {
440 //  --------------------------
441       return (countag + history > 1);
442     }
443
444     public boolean isVersioned () {
445 //  -----------------------------
446       return (history > 0);
447     }
448     
449 //  ==============================================================================================================================
450 //  Public services
451 //  ==============================================================================================================================
452
453     public static DocumentType createType (DocumentType.Properties tprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, RuntimeException {
454 //  ---------------------------------------------------------------------
455 //TODO: Check for duplicate definition
456       DocumentType type    = new DocumentType(tprop);
457       Session      session = Database.getSession();
458       session.save(type);
459           
460       return type;
461     }
462
463     public static Properties extractProperties (java.io.File file) {
464 //  --------------------------------------------------------------
465       Properties fprop = new Properties();
466       Reader     tool  = Toolbox.getReader(file);
467       String     value;
468       if (tool != null) try {
469         value = tool.extractProperty("title");
470         if (value != null) fprop.setName(value);
471
472         value = tool.extractProperty("reference");
473         if (value != null) fprop.setReference(value);
474       }
475       catch (Exception e) {
476       }
477       return fprop;
478     }
479
480     @SuppressWarnings("unchecked")
481         public static List<DocumentType> selectAllTypes () {
482 //  --------------------------------------------------
483           String query = "from DocumentType";
484           
485           List<DocumentType>            types = Database.getSession().createQuery(query).list();
486       for (Iterator<DocumentType> i=types.iterator(); i.hasNext();) {
487         Hibernate.initialize(i.next());     // Supposed fetching document types
488       }
489       return types;
490     }
491
492     @SuppressWarnings("unchecked")
493         public static List<DocumentType> selectResultTypes () {
494 //  -----------------------------------------------------
495           String query = "from DocumentType where result is not null order by result asc";
496           
497       return Database.getSession().createQuery(query).list();
498     }
499
500     public static DocumentType selectType (String name) {
501 //  ---------------------------------------------------
502           String query = new StringBuffer("from DocumentType where name='").append(name).append("'").toString();
503           
504           return (DocumentType)Database.getSession().createQuery(query).uniqueResult();
505     }
506
507     public static DocumentType selectType (int index) {
508 //  -------------------------------------------------
509           String query = new StringBuffer("from DocumentType where rid='").append(index).append("'").toString();
510           
511           return (DocumentType)Database.getSession().createQuery(query).uniqueResult();
512     }
513
514     @SuppressWarnings("unchecked")
515         public static List<DocumentType> selectTypesOf (ProjectSettings.Step step) {
516 //  --------------------------------------------------------------------------
517           Integer number = step.getNumber();      
518           String  query  = new StringBuffer("from DocumentType").append(" where step like '%-").append(number).append("-%'").toString();
519           
520           List<DocumentType> types = Database.getSession().createQuery(query).list();
521       for (Iterator<DocumentType> i=types.iterator(); i.hasNext();) {
522         Hibernate.initialize(i.next());     // For fetching document types
523       }
524       return types;
525     }
526
527 //  ==============================================================================================================================
528 //  Protected services
529 //  ==============================================================================================================================
530
531     protected ConvertsRelation attach (String format) {
532 //  -------------------------------------------------
533       return attach(format, null);
534     }
535
536     protected ConvertsRelation attach (String format, String description) {
537 //  ---------------------------------------------------------------------
538       String            path    = this.getRelativePath();
539       File              export  = new File(path + "." + format);
540       ConvertsRelation  attach  = new ConvertsRelation(this, export, description);
541       Session           session = Database.getSession();
542
543       session.save(export);
544       session.save(attach);
545
546       this.addRelation(attach);     // Updates this
547
548       return attach;
549     }
550
551     protected boolean buildReferenceFrom (ProjectElement scope, Document lineage) {
552 //  -----------------------------------------------------------------------------
553       if (state != ProgressState.inWORK) return false;
554       Study          owner    = null;
555       Scenario       context  = null;
556       if (scope instanceof Study) owner = (Study)scope;
557       else {
558         context = ((Scenario)scope);
559         owner   = context.getOwnerStudy();
560       }
561       did  = lineage.did;
562       if (context != null && (lineage.isVersioned() || owner.shares(lineage))) {
563         version = new Revision(version).setBranch(context.getReference()).toString();
564       }
565       return true;
566     }
567
568     protected boolean buildReferenceFrom (Study scope) {
569 //  --------------------------------------------------
570       if (state != ProgressState.inWORK && state != ProgressState.EXTERN) return false;
571       DecimalFormat  tostring = new DecimalFormat(suformat);
572
573       did  = did.replace ("%" + suformat, tostring.format(scope.getLastLocalIndex()));
574       return true;
575     }
576
577     protected boolean demote () {
578 //  ---------------------------
579         ValidationStep torem;
580
581       if (state == ProgressState.inCHECK) {
582         state = ProgressState.inDRAFT;
583         torem = ValidationStep.REVIEW;
584 //      This operation must not change the version number of documents.
585 //      Consequently, inDRAFT documents may have a minor version number equal to zero.
586       } else
587       if (state == ProgressState.inDRAFT) {
588         state = ProgressState.inWORK;
589         torem = ValidationStep.PROMOTION;
590       } else {
591         return false;
592       }
593       for (Iterator<Relation> i=this.getAllRelations().iterator(); i.hasNext(); ) {
594         Relation link = i.next();
595         if (!(link instanceof StampRelation))              continue;
596         if (((StampRelation)link).getStampType() != torem) continue;
597         i.remove();
598         break;
599       }
600       Database.getSession().update(this);
601           return true;
602     }
603
604 /**
605  * Increments the reference count of this document following its publication into a Study step.
606  * 
607  * @see #release()
608  */
609     protected void hold () {
610 //  ----------------------
611       countag += 1;
612       if (this.isSaved()) Database.getSession().update(this);
613     }
614
615 /**
616  * Defines this document.
617  * 
618  * @param dprop the properties of the document
619  * 
620  * @see Step#createDocument(Properties)
621  * @see #isUndefined()
622  */
623     protected void initialize (Properties dprop) throws MissedPropertyException, InvalidPropertyException, NotApplicableException {
624 //  --------------------------------------------
625       if (!this.isUndefined())      throw new NotApplicableException("Cannot initialize an existing Document");
626       if (dprop.name  == null)      throw new MissedPropertyException("name");
627       if (dprop.name.length() == 0) throw new InvalidPropertyException("name");
628       if (dprop.owner == null)      throw new MissedPropertyException("owner");
629 //    if (dprop.owner instanceof Study && !ProjectSettings.getStep(step).appliesTo(Study.class)) {
630 //                                  throw new InvalidPropertyException("step");
631 //    }
632       name = dprop.name;
633       myfile.changePath( myfile.getRelativePath().replace("%n", getEncodedRootName((Study)dprop.owner)) );
634       if (history == -1) history = 0;
635       if (dprop.date == null) {
636         Calendar  current = Calendar.getInstance();
637         lasdate = current.getTime();             // Today
638       } else {
639         lasdate = dprop.date;
640       }
641       Database.getSession().update(this);
642     }
643
644     protected boolean promote (Timestamp stamp) {
645 //  -------------------------------------------
646       ProgressState  newstate = null;
647
648       if (state == ProgressState.inWORK) {
649         newstate = ProgressState.inDRAFT;        // Promotion to being reviewed
650       } else
651       if (state == ProgressState.inDRAFT) {
652         newstate = ProgressState.inCHECK;        // Promotion to approval
653             Revision  myvers = new Revision(version);
654         if (myvers.isMinor()) {
655                   version = myvers.incrementAs(newstate).toString();
656 //TODO:   If my physical file is programatically editable, update its (property) version number
657 //ISSUE:  What about attached files such as PDF if exist, should we remove them ?
658         }
659       } else
660       if (state == ProgressState.inCHECK) {
661         newstate = ProgressState.APPROVED;
662       }
663       this.state = newstate;
664       if (stamp != null) this.addRelation( stamp.getContext() );
665       Database.getSession().update(this);
666           return true;
667     }
668
669 /**
670  * Decrements the reference count of this document following the removal of a Publication from a Study step.
671  * 
672  * @see #hold()
673  */
674     protected void release () {
675 //  -------------------------
676       countag -= 1;
677       if (this.isSaved()) Database.getSession().update(this);
678     }
679
680     protected void rename (String title) throws InvalidPropertyException {
681 //  ------------------------------------
682       if (title.length() == 0) throw new InvalidPropertyException("name");
683
684       Calendar current = Calendar.getInstance();
685       this.name    = title;
686       this.lasdate = current.getTime();            // Today
687       Database.getSession().update(this);
688     }
689
690     protected void updateAs (Revision newvers) {
691 //  ------------------------------------------
692       version = newvers.setBranch(version).toString();   // Branch names are propagated by the versionning
693       ProgressState newstate = ProgressState.inCHECK;
694       if (newvers.isMinor()) newstate = ProgressState.inWORK;
695       state = null;                                      // Just to tell updateAs(sate) to not increment the version number
696       updateAs(newstate);
697     }
698
699     protected void updateAs (ProgressState state) {
700 //  ---------------------------------------------
701       Document previous = null;
702
703 //    Set of version number
704       if (state == ProgressState.EXTERN) {
705         if (this.state != ProgressState.EXTERN) this.version = null;   // Strange use-case...
706       } else {
707         Revision myvers = new Revision(version);
708         if (!myvers.isNull()) {                                        // Versionning context
709           for (Iterator<Relation> i=getAllRelations().iterator(); i.hasNext();) {
710                 Relation link = i.next();
711                 if (!link.getClass().equals(VersionsRelation.class)) continue;
712                 previous = (Document)link.getTo();                         // Versioned document
713                 break;
714           }
715         }
716         if (this.state != null) myvers.incrementAs(state);             // Incrementation if the reversion number is not imposed
717         this.version = myvers.toString();
718       }
719 //    Update this document and the previous version, if exit
720       Session  session = Database.getSession();
721       if (previous != null) {
722         previous.history += 1;
723         session.update(previous);
724       }
725       this.state   = state;
726       session.update(this);
727     }
728
729 //    protected void upgrade () {
730 //  -------------------------
731 //      if (this.state != ProgressState.inWORK) return;
732 //
733 //      Calendar  current = Calendar.getInstance();
734 //      for (Iterator<Relation> i=getAllRelations().iterator(); i.hasNext();) {
735 //        Relation link = i.next();
736 //        if (!link.getClass().equals(UsesRelation.class)) continue;
737 //
738 //        Document used = (Document)link.getTo();
739 //        if (!used.isVersioned()) continue;
740 //TODO:   Update the uses relation
741 //      }
742 //      this.promote();
743 //      this.lasdate = current.getTime();            // Today
744 //      Database.getSession().update(this);
745 //
746 //TODO: Promote documents using this one
747 //    }
748
749 //  ==============================================================================================================================
750 //  Private services
751 //  ==============================================================================================================================
752
753     private String generateEncodedName (Study scope) {
754 //  ------------------------------------------------
755       StringBuffer   encoding = new StringBuffer();
756       FileNaming     scheme   = ProjectSettings.getFileNamingScheme();
757       DecimalFormat  tostring = new DecimalFormat(suformat);
758
759       int            number   = scope.generateLocalIndex();
760
761       if (scheme == FileNaming.encoded) {
762         encoding.append(scope.getReference()).append(".").append(tostring.format(number));
763       } else {                              // title and (temporarily) asis
764         encoding.append(name).append(".").append(tostring.format(number));
765       }
766       return  encoding.toString();
767     }
768
769     private String getEncodedRootName (Study scope) {
770 //  -----------------------------------------------
771       FileNaming  scheme = ProjectSettings.getFileNamingScheme();
772
773       if (scheme == FileNaming.encoded) return scope.getReference();
774       else                              return name;
775     }
776 }