--- /dev/null
+package org.splat.som;
+/**
+ *
+ * @author Daniel Brunier-Coulin
+ * @copyright OPEN CASCADE 2012
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+import java.util.Iterator;
+
+import org.hibernate.Session;
+import org.splat.kernel.InvalidPropertyException;
+import org.splat.kernel.MismatchException;
+import org.splat.kernel.MissedPropertyException;
+import org.splat.kernel.MultiplyDefinedException;
+import org.splat.kernel.NotApplicableException;
+import org.splat.kernel.Relation;
+import org.splat.kernel.User;
+import org.splat.som.Database;
+
+
+public class Step {
+
+ private ProjectSettings.Step step;
+ private ProjectElement owner;
+ private List<SimulationContext> contex;
+ private List<Publication> docums;
+ private User actor; // Actor involved in operations on published documents and requiring a time-stamp
+
+// ==============================================================================================================================
+// Constructor
+// ==============================================================================================================================
+
+ protected Step (ProjectSettings.Step step, ProjectElement owner) {
+// ----------------------------------------------------------------
+ this.step = step;
+ this.owner = owner;
+ this.contex = new Vector<SimulationContext>();
+ this.docums = new Vector<Publication>();
+ this.actor = null;
+
+// Filtering of Simulation contexts, if exist
+ for (Iterator<SimulationContext> i=owner.SimulationContextIterator(); i.hasNext();) {
+ SimulationContext adoc = i.next();
+ if (!adoc.isInto(this)) continue;
+ this.contex.add(adoc);
+ }
+// Filtering of Documents, if exist
+ for (Iterator<Publication> i=owner.PublicationIterator(); i.hasNext();) {
+ Publication mydoc = i.next();
+ if (!mydoc.value().isInto(this)) continue;
+ this.docums.add(mydoc);
+ }
+ }
+
+// ==============================================================================================================================
+// Public member functions
+// ==============================================================================================================================
+
+ public Publication createDocument (Document.Properties dprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, IOException {
+// -------------------------------------------------------------
+ Document newdoc = new Document(dprop.setOwner(owner).setStep(step));
+
+// Creation of the save directory
+ File wdir = newdoc.getSaveDirectory();
+ if (!wdir.exists()) if (!wdir.mkdirs()) throw new IOException("Cannot create the repository vault directory");
+
+// Identification and save
+ newdoc.buildReferenceFrom(getOwnerStudy());
+ Database.getSession().save(newdoc);
+
+ return new Publication(newdoc, owner);
+ }
+
+ public Publication assignDocument (Document.Properties dprop) throws MissedPropertyException, InvalidPropertyException, NotApplicableException {
+// -------------------------------------------------------------
+ String refid = dprop.getReference();
+ if (refid == null) return null;
+
+ Document slot = Database.selectDocument(refid, new Revision().toString());
+ if ( slot == null ) return null;
+ if (!slot.isUndefined()) return null; // Should not happen
+
+ slot.initialize(dprop.setOwner(getOwnerStudy()));
+ return new Publication(slot, owner);
+ }
+
+ public Publication versionDocument (Publication base) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, IOException, MismatchException {
+// -----------------------------------------------------
+ return versionDocument(base, new Document.Properties());
+ }
+
+ public Publication versionDocument (Publication base, String reason) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, IOException, MismatchException {
+// --------------------------------------------------------------------
+ return versionDocument(base, new Document.Properties().setDescription(reason));
+ }
+
+ public Publication versionDocument (Publication base, Document.Properties dprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, IOException, MismatchException {
+// --------------------------------------------------------------------------------
+ Document previous = base.value();
+
+ dprop.setDocument(previous); // Initializes the Step property
+ if (dprop.getStep().getNumber() != this.step.getNumber()) throw new MismatchException();
+
+ if (dprop.getAuthor() == null) dprop.setAuthor(previous.getAuthor());
+ String summary = dprop.getDescription();
+
+// Creation of the document
+ Document newdoc = new Document(dprop.setOwner(owner).setStep(step));
+ newdoc.buildReferenceFrom(getOwner(), previous);
+ Database.getSession().save(newdoc);
+
+// Versioning
+ if (summary == null) newdoc.addRelation( new VersionsRelation(newdoc, previous) );
+ else newdoc.addRelation( new VersionsRelation(newdoc, previous, summary) );
+
+// Update of usedby relations, if exist
+ List<Relation> relist = previous.getRelations(UsedByRelation.class);
+ Study scope = getOwnerStudy();
+ for (Iterator<Relation> i=relist.iterator(); i.hasNext();) {
+ UsedByRelation relation = (UsedByRelation)i.next();
+ Document relatedoc = relation.getTo();
+ if (scope.shares(relatedoc)) relatedoc.addRelation( new UsesRelation(relatedoc, newdoc) );
+ else relation.moveTo(newdoc);
+ }
+ return new Publication(newdoc, owner);
+ }
+
+ public SimulationContext addSimulationContext (SimulationContext.Properties dprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, RuntimeException {
+// ----------------------------------------------------------------------------------
+ SimulationContext context = new SimulationContext(dprop.setStep(step));
+ return addSimulationContext(context);
+ }
+
+ public SimulationContext addSimulationContext (SimulationContext context) {
+// -------------------------------------------------------------------------
+ context.hold(); // Increments the reference count of simulation context
+ if (owner.isSaved()) try {
+ Session session = Database.getSession();
+ Index lucin = Database.getIndex();
+
+ if (!context.isSaved()) session.save(context);
+ owner.add(context);
+ contex.add(context); // The context is also referenced from this (transient) Step
+ session.update(owner);
+ updateKnowledgeElementsIndex(lucin);
+ }
+ catch (Exception error) {
+ return null;
+ }
+ else { // Happens when copying a scenario
+ owner.add(context);
+ contex.add(context); // The context is also referenced from this (transient) Step
+// In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
+ }
+ return context;
+ }
+
+ public User getActor () {
+// -----------------------
+ return actor;
+ }
+
+ public List<Publication> getAllDocuments () {
+// -------------------------------------------
+ return Collections.unmodifiableList(docums);
+ }
+
+ public List<SimulationContext> getAllSimulationContexts () {
+// ----------------------------------------------------------
+ return Collections.unmodifiableList(contex);
+ }
+
+ public Publication getDocument (int index) {
+// ------------------------------------------
+ for (Iterator<Publication> i=docums.iterator(); i.hasNext();) {
+ Publication found = i.next(); // In a given study step,
+ if (found.value().getIndex() == index) return found; // there is only one publication of a given document
+ }
+ return null;
+ }
+
+ public int getNumber () {
+// -----------------------
+ return step.getNumber();
+ }
+
+ public ProjectElement getOwner () {
+// ---------------------------------
+ return owner; // May be a Study or a Scenario
+ }
+
+ public Study getOwnerStudy () {
+// -----------------------------
+ if (owner instanceof Study) return (Study)owner;
+ else return ((Scenario)owner).getOwnerStudy();
+ }
+
+ public String getPath () {
+// ------------------------
+ return step.getPath();
+ }
+
+ public List<Publication> getResultDocuments () {
+// ----------------------------------------------
+ List<Publication> result = new Vector<Publication>();
+
+ if (!docums.isEmpty()) for (Iterator<Publication> i=docums.iterator(); i.hasNext(); ) {
+ Publication content = i.next();
+ DocumentType type = content.value().getType();
+ if (!type.isResultOf(this.getStep())) continue;
+ result.add(content);
+ }
+ return result;
+ }
+
+ public ProjectSettings.Step getStep () {
+// --------------------------------------
+ return step;
+ }
+
+ public SimulationContext getSimulationContext (int index) {
+// ---------------------------------------------------------
+ for (Iterator<SimulationContext> i=owner.SimulationContextIterator(); i.hasNext();) {
+ SimulationContext myctex = i.next();
+ if (myctex.getIndex() == index) return myctex;
+ }
+ return null;
+ }
+
+ public List<SimulationContext> getSimulationContext (SimulationContextType type) {
+// --------------------------------------------------------------------------------
+ Vector<SimulationContext> result = new Vector<SimulationContext>();
+
+ for (Iterator<SimulationContext> i=owner.SimulationContextIterator(); i.hasNext();) {
+ SimulationContext myctex = i.next();
+ if (myctex.getType().equals(type)) result.add(myctex);
+ }
+ return result;
+ }
+
+ public List<DocumentType> getValidDocumentTypes () {
+// --------------------------------------------------
+ return Document.selectTypesOf(step);
+ }
+
+ public boolean isStarted () {
+// ---------------------------
+ if (!step.mayContain(KnowledgeElement.class)) return !docums.isEmpty();
+
+ List<KnowledgeElement> kelm = ((Scenario)owner).getAllKnowledgeElements();
+ if (kelm.isEmpty() && docums.isEmpty()) return false;
+ return true;
+ }
+
+ public boolean isFinished () {
+// ----------------------------
+ if (!step.mayContain(KnowledgeElement.class)) { // Check if all result documents are approved
+ if (docums.isEmpty()) return false;
+ boolean result = false;
+ for (Iterator<Publication> i=docums.iterator(); i.hasNext(); ) {
+ Document content = i.next().value();
+ DocumentType type = content.getType();
+ if (!type.isResultOf(this.getStep())) continue;
+ if (content.getProgressState() == ProgressState.EXTERN) continue;
+ result = true; // There is at least 1 non external result document
+ if (content.getProgressState() != ProgressState.APPROVED) return false;
+ }
+ return result;
+ }
+ else { // Check if all existing knowledges are approved
+ List<KnowledgeElement> kelm = ((Scenario)owner).getAllKnowledgeElements();
+ if (kelm.isEmpty()) return false;
+ for (Iterator<KnowledgeElement> i=kelm.iterator(); i.hasNext(); ) {
+ KnowledgeElement content = i.next();
+ if (content.getProgressState() != ProgressState.APPROVED) return false;
+ }
+ return true;
+ }
+ }
+
+ public boolean mayContain (@SuppressWarnings("rawtypes") Class type) {
+// --------------------------------------------------------------------
+ return step.mayContain(type);
+ }
+
+ public boolean removeDocument (Publication doctag) {
+// --------------------------------------------------
+ Document value = doctag.value();
+ Publication torem = getDocument(value.getIndex());
+ Session session = Database.getSession();
+
+ if (torem == null) return false;
+
+ this.remove(torem);
+ session.update(owner);
+ if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
+ Set<Relation> links = value.getAllRelations();
+ List<Document> using = new Vector<Document>();
+ for (Iterator<Relation> i=links.iterator(); i.hasNext(); ) {
+ Relation link = i.next();
+ if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
+ session.delete(link.getTo()); // The corresponding physical file is not removed from the vault
+ } else
+ if (link.getClass().equals(UsesRelation.class)) { // Document dependency
+ using.add((Document)link.getTo());
+ }
+ }
+ for (Iterator<Document> i=using.iterator(); i.hasNext(); ) {
+ i.next().removeRelation(UsedByRelation.class, value);
+ }
+ session.delete(value); // The corresponding physical file is not removed from the vault
+ }
+ return true;
+ }
+
+ public boolean removeSimulationContext (SimulationContext context) {
+// ------------------------------------------------------------------
+ SimulationContext torem = getSimulationContext(context.getIndex());
+ Session session = Database.getSession();
+
+ if (torem == null) return false;
+ if (!owner.remove(torem)) return false;
+
+ contex.remove(torem);
+ session.update(owner);
+ if (torem.isShared()) {
+ torem.release();
+ session.update(torem);
+ } else {
+ session.delete(torem);
+ }
+ return true;
+ }
+
+ public void setActor (User user) {
+// --------------------------------
+ actor = user;
+ }
+// ==============================================================================================================================
+// Protected member functions
+// ==============================================================================================================================
+
+ protected boolean add (Publication newdoc) {
+// ------------------------------------------
+ if (!owner.add(newdoc)) return false; // Updates the study in memory
+ docums.add(0, newdoc); // Updates this step
+ newdoc.value().hold(); // Increments the configuration tag count of document
+// If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
+// database (it will be saved later by cascading the update of owner scenario).
+ return true;
+ }
+
+ protected boolean remove (Publication oldoc) {
+// --------------------------------------------
+ if (!owner.remove(oldoc)) return false; // Updates the study in memory
+ docums.remove(oldoc); // Updates this step
+ oldoc.value().release(); // Decrements the configuration tag count of document
+// The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
+ return true;
+ }
+
+// ==============================================================================================================================
+// Private services
+// ==============================================================================================================================
+
+ private void updateKnowledgeElementsIndex(Index lucin) {
+// ------------------------------------------------------
+ Scenario[] scenarii;
+ if (owner instanceof Scenario) {
+ scenarii = new Scenario[1];
+ scenarii[0] = (Scenario)owner;
+ } else {
+ scenarii = getOwnerStudy().getScenarii();
+ }
+ try {
+ for (int i=0; i<scenarii.length; i++) {
+ Scenario scene = scenarii[i];
+ List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
+ for (Iterator<KnowledgeElement> j=knelm.iterator(); j.hasNext(); ) {
+ KnowledgeElement kelm = j.next();
+ lucin.update(kelm);
+ }
+ scene.updateMyIndex(lucin);
+ }
+ }
+ catch (Exception error) {
+// logger.error("Unable to re-index Knowledge Elements, reason:", error);
+ }
+ }
+}
\ No newline at end of file