Salome HOME
SIMAN Eclipse workspace first version
[tools/siman.git] / Workspace / SPlat / src / org / splat / som / Scenario.java
1 package org.splat.som;
2 /**
3  * 
4  * @author    Daniel Brunier-Coulin
5  * @copyright OPEN CASCADE 2012
6  */
7
8 import java.io.IOException;
9 import java.util.Calendar;
10 import java.util.Collections;
11 import java.util.Date;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.HashSet;
17 import java.util.Vector;
18
19 import org.hibernate.HibernateException;
20 import org.hibernate.Session;
21 import org.hibernate.Transaction;
22 import org.splat.kernel.Persistent;
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
28
29 public class Scenario extends ProjectElement {
30
31 //  Persistent fields
32     private Study                 owner;
33         private int                   sid;               // Identifier unique in the scope of owner study
34         private User                  cuser;             // User having checked-out the scenario, if done
35     private Set<KnowledgeElement> kelms;
36
37 //  Transient fields
38     private HashMap<Integer, List<KnowledgeElement>> known;
39     private List<KnowledgeElement>                   knowl;  // Copy of kelms excluding the internal Knowledge Element (ucase below)
40         private KnowledgeElement                         ucase;  // Internal Knowledge Element for accessing to all used simulation contexts
41
42
43 //  ==============================================================================================================================
44 //  Construction
45 //  ==============================================================================================================================
46
47 //  Fields initialization class
48     public static class Properties extends Persistent.Properties {
49 //  ------------------------------------------------------------
50       private Study    owner    = null;
51       private Scenario previous = null;
52       private Step     base     = null;
53       private String   title    = null;
54       private String   summary  = null;
55       private User     manager  = null;
56       private Date     date     = null;
57
58 //  - Public services
59
60       public void clear () {
61         super.clear();
62         owner    = null;
63         previous = null;
64         base     = null;
65         title    = null;
66         summary  = null;
67         manager  = null;
68         date     = null;
69       }
70 //  - Protected services
71
72       protected Step getBaseStep () {
73         return base;         // May be null
74       }
75       protected Scenario getInsertAfter () {
76         return previous;     // May be null
77       }
78           protected User getManager () {
79                 return manager;
80           }
81       protected Properties setOwnerStudy (Study owner)
82       {
83         this.owner = owner;
84         return this;
85       }
86 //  - Setters of Scenario properties
87
88       public Properties setBaseStep (Step base) throws InvalidPropertyException
89       {
90         if (!(base.getOwner() instanceof Scenario)) throw new InvalidPropertyException("step");
91         this.base = base;
92         return this;
93       }
94       public Properties setDate (Date date)
95       {
96         this.date = date;
97         return this;
98       }
99       public Properties setDescription (String summary)
100       {
101         if (summary.length() > 0) this.summary = summary;
102         return this;
103       }
104       public Properties setInsertAfter (Scenario previous)
105       {
106         this.previous = previous;
107         return this;
108       }
109       public Properties setManager (User user)
110       {
111         this.manager = user;
112         return this;
113       }
114       public Properties setTitle (String title) throws InvalidPropertyException
115       {
116         if (title.length() == 0) throw new InvalidPropertyException("title");
117         this.title = title;
118         return this;
119       }
120 //  - Global validity check
121       
122       public void checkValidity() throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException
123       {
124         if (owner == null)   throw new MissedPropertyException("owner");
125         if (title == null)   throw new MissedPropertyException("title");
126         if (manager == null) throw new MissedPropertyException("manager");
127       }
128     }
129 //  Database fetch constructor
130     protected Scenario () {
131 //  ---------------------
132       known = null;
133       knowl = null;
134       ucase = null;
135     }
136 //  Internal constructor
137     protected Scenario (Properties sprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException {
138 //  -------------------------------------
139       super(sprop);                // Throws one of the above exception if not valid
140       owner   = sprop.owner;
141       sid     = 0;
142       cuser   = null;
143       title   = sprop.title;       // Inherited attribute
144       known   = null;
145       knowl   = null;              // Initialized when getting all Knowledge Elements
146       ucase   = null;
147       kelms   = new HashSet<KnowledgeElement>();
148
149       manager = sprop.manager;
150       if (!owner.isStaffedBy(manager)) throw new InvalidPropertyException("manager");
151
152       credate = sprop.date;        // Inherited attribute
153       if (credate == null) {
154         Calendar current = Calendar.getInstance();
155         credate = current.getTime();  // Today
156       }
157       lasdate = credate;           // Inherited attribute
158
159       if (sprop.summary != null) this.setAttribute( new DescriptionAttribute(this, sprop.summary) );
160
161       Scenario[] scene = owner.getScenarii();
162       for (int i=0; i<scene.length; i++) if (scene[i].sid > this.sid) this.sid = scene[i].sid;
163       sid += 1;
164       if (sprop.base != null) copyContentsUpTo(sprop.base);
165     }
166
167 //  ==============================================================================================================================
168 //  Public member functions
169 //  ==============================================================================================================================
170
171     public KnowledgeElement addKnowledgeElement (KnowledgeElement.Properties kprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException {
172 //  -------------------------------------------------------------------------------
173       KnowledgeElement kelm    = new KnowledgeElement(kprop.setOwnerScenario(this));
174       Session          session = Database.getSession();
175           Transaction      transax = session.getTransaction();
176       try {                
177         session.save(kelm);
178 //      Update of my persistent data
179         kelms.add(kelm);
180 //      Update of my transient data
181         List<KnowledgeElement> known = getKnowledgeElementsOf(kelm.getType());   // Initializes this.known, if not yet done
182         known.add(kelm);
183         if (kelm.getType().equals("usecase")) {
184           ucase = kelm;
185         } else
186         if (knowl != null)  {                                                    // If null, knowl will be initialized when needed
187           knowl.add(kelm);
188         }
189 //      Update of the index of Knowledge Elements          
190         Database.getIndex().add(kelm);                       
191         updateMe();        
192         return kelm;
193       }
194       catch (RuntimeException e) {
195         if (transax != null && transax.isActive()) {
196 //        Second try-catch as the rollback could fail as well
197           try {
198                 transax.rollback();
199           } catch (HibernateException error) {
200             Study.logger.debug("Error rolling back transaction", error);
201           }
202 //          Throw again the first exception
203           throw e;
204         }
205         return null;
206       }
207       catch (IOException error) {
208         logger.error("Unable to index the knowedge element '" + kelm.getIndex() + "', reason:", error);
209         return null;
210       }
211     }
212
213     public void checkin () {
214 //  ----------------------
215       cuser   = null;
216       lasdate = Calendar.getInstance().getTime();
217       Database.getSession().update(this);
218     }
219
220     public boolean checkout (User user) {
221 //  -----------------------------------
222       if (!owner.isStaffedBy(user)) return false;
223
224       cuser   = user;
225       lasdate = Calendar.getInstance().getTime();
226       Database.getSession().update(this);
227       return true;
228     }
229
230     public List<KnowledgeElement> getAllKnowledgeElements () {
231 //  --------------------------------------------------------
232       if (knowl == null) {
233         knowl = new Vector<KnowledgeElement>(kelms.size());
234         for (Iterator<KnowledgeElement> i=kelms.iterator(); i.hasNext(); ) {
235           KnowledgeElement  kelm = i.next();
236           if (kelm.getType().equals("usecase")) ucase = kelm;
237           else                                  knowl.add(kelm);
238         }
239       }
240       return  Collections.unmodifiableList(knowl);
241     }
242
243     public KnowledgeElement getKnowledgeElement (int index) {
244 //  -------------------------------------------------------
245       for (Iterator<KnowledgeElement> i=kelms.iterator(); i.hasNext();) {
246             KnowledgeElement mykelm = i.next();
247         if (mykelm.getIndex() == index) return mykelm;
248       }
249       return null;
250     }
251
252     public List<KnowledgeElement> getKnowledgeElementsOf (KnowledgeElementType type) {
253 //  --------------------------------------------------------------------------------
254       if (kelms.isEmpty()) return  new Vector<KnowledgeElement>();   // Smarter than returning null
255       if (known == null)   known = new HashMap<Integer, List<KnowledgeElement>>();
256
257       int                    numtype = type.getIndex();
258       List<KnowledgeElement> listype = known.get(numtype);
259       if (listype == null) {
260         listype = new Vector<KnowledgeElement>();
261         for (Iterator<KnowledgeElement> i=kelms.iterator(); i.hasNext();) {
262           KnowledgeElement kelm = i.next();
263           if (kelm.getType().getIndex() == numtype) listype.add(kelm);
264         }
265         known.put(numtype, listype);
266       }
267       return listype;   // No protection against this object corruption as it would not corrupt the database
268     }
269
270     public Study getOwnerStudy () {
271 //  -----------------------------
272       return  owner;
273     }
274 /**
275  * Returns the local reference of this scenario. This reference is unique in the scope of the owner study.
276  */
277     public String getReference () {
278 //  -----------------------------
279       return  String.valueOf(sid);
280     }
281
282     public User getUser () {
283 //  ----------------------
284       return  cuser;    // Null if the scenario has not been checked-out
285     }
286
287     public boolean removeKnowledgeElement (KnowledgeElement kelm) {
288 //  -------------------------------------------------------------
289           KnowledgeElement torem = getKnowledgeElement(kelm.getIndex());
290       if (torem == null) return false;
291       boolean done = kelms.remove(torem);
292       if (done) {
293 //      Update of my transient data
294         List<KnowledgeElement> kelms = known.get(kelm.getType().getIndex());
295         kelms.remove(torem);
296         if (knowl != null) knowl.remove(torem);
297         Database.getSession().update(this);
298 //TODO: If the owner study is not private, remove the knowledge from the Lucene index
299         return true;
300       } else {
301         return false;
302       }
303     }
304
305     public boolean isCheckedout () {
306 //  ------------------------------
307       return (cuser != null);
308     }
309
310     public boolean isEmpty () {
311 //  -------------------------
312       Step[] mystep = this.getSteps();
313       for (int i=0; i<mystep.length; i++) if (mystep[i].isStarted()) return false;
314       return true;
315     }
316
317     public boolean isFinished () {
318 //  ----------------------------
319       Step[]  mystep   = this.getSteps();
320       boolean notempty = false;   // If this is empty, this is not finished
321       for (int i=0; i<mystep.length; i++) {
322         if (!mystep[i].isStarted())  continue;
323         if (!mystep[i].isFinished()) return false;
324         notempty = true;
325       }
326       return notempty;
327     }
328
329 //  ==============================================================================================================================
330 //  Protected member function
331 //  ==============================================================================================================================
332
333     protected void updateMyIndex (Index lucin) throws IOException {
334 //  ------------------------------------------
335       if (ucase == null) for (Iterator<KnowledgeElement> i=kelms.iterator(); i.hasNext(); ) {
336         KnowledgeElement  kelm = i.next();
337         if (!kelm.getType().equals("usecase")) continue;
338         ucase = kelm;
339         break;
340       }
341       lucin.update(ucase);
342     }
343
344 //  ==============================================================================================================================
345 //  Private services
346 //  ==============================================================================================================================
347
348     private void copyContentsUpTo (Step lastep) {
349 //  -------------------------------------------
350       Scenario base = (Scenario)lastep.getOwner();
351       Step[]   from = base.getSteps();
352       Step[]   to   = this.getSteps();
353       for (int i=0; i<from.length; i++) {
354         Step step = from[i];
355         if (step.getNumber() > lastep.getNumber()) break;
356
357         List<Publication> docs = step.getAllDocuments();
358         for (Iterator<Publication> j=docs.iterator(); j.hasNext(); ) {
359           Publication doc = j.next().copy(this);   // Creation of a new reference to the document
360 //        Database.getSession().save(doc);            Publications MUST be saved later through cascading when saving the scenario
361           to[i].add(doc);
362         }
363         List<SimulationContext> ctex = step.getAllSimulationContexts();
364         for (Iterator<SimulationContext> j=ctex.iterator(); j.hasNext(); ) {
365           to[i].addSimulationContext(j.next());
366         }
367       }
368     }
369
370     private boolean updateMe () {
371 //  ---------------------------
372       try {      
373         Database.getSession().update(this);   // Update of relational base
374         return true;
375       }
376       catch (Exception error) {
377         logger.error("Unable to re-index the knowledge element '" + getIndex() + "', reason:", error);
378         return false;
379       }
380     }
381 }