package org.simantics.spreadsheet.graph; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.ProxyVariables; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.simulator.toolkit.StandardRealm; import org.simantics.simulator.toolkit.db.StandardSessionManager; import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment; import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler; import org.simantics.spreadsheet.resource.SpreadsheetResource; import org.simantics.structural.synchronization.Synchronizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SpreadsheetSessionManager extends StandardSessionManager { private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetSessionManager.class); private static SpreadsheetSessionManager INSTANCE; public static SpreadsheetSessionManager getInstance() { if(INSTANCE == null) { INSTANCE = new SpreadsheetSessionManager(); } return INSTANCE; } public class ClassLoaderObjectInputStream extends ObjectInputStream{ private ClassLoader classLoader; public ClassLoaderObjectInputStream(ClassLoader classLoader, InputStream in) throws IOException { super(in); this.classLoader = classLoader; } @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException{ try{ String name = desc.getName(); return Class.forName(name, false, classLoader); } catch(ClassNotFoundException e){ return super.resolveClass(desc); } } } private SpreadsheetBook getPossibleInitialCondition(ReadGraph graph, Resource context, Resource book) throws DatabaseException { SpreadsheetResource SR = SpreadsheetResource.getInstance(graph); Collection ics = graph.getObjects(context, SR.HasInitialCondition); Resource found = null; Set founds = new HashSet<>(); Set foundDefaults = new HashSet<>(); for (Resource initialCondition : ics) { if (graph.hasStatement(book, SR.Book_HasDefaultInitialCondition, initialCondition)) { foundDefaults.add(initialCondition); } if (graph.hasStatement(initialCondition, SR.InitialCondition_ConditionOf, book)) { founds.add(initialCondition); } } if (foundDefaults.size() == 1) { found = foundDefaults.iterator().next(); } else if (foundDefaults.size() == 0 && founds.size() == 1) { found = founds.iterator().next(); } else { System.err.println("Could not find IC for SpreadsheetBook " + graph.getPossibleURI(book)); System.err.println("foundDefaults : " + foundDefaults.size()); if (!foundDefaults.isEmpty()) { for (Resource foundDefault : foundDefaults) { System.err.println(graph.getPossibleURI(foundDefault)); } } System.err.println("founds : " + founds.size()); if (!founds.isEmpty()) { for (Resource foun : founds) { System.err.println(graph.getPossibleURI(foun)); } } } if (found != null) { try { File tmp = SpreadsheetGraphUtils.extractInitialCondition(graph, found); System.err.println("Extracting IC from " + tmp.getAbsolutePath()); InputStream fileIn = new BufferedInputStream(new FileInputStream(tmp)); ObjectInputStream in = new ClassLoaderObjectInputStream(getClass().getClassLoader(), fileIn); SpreadsheetBook srBook = (SpreadsheetBook) in.readObject(); in.close(); return srBook; } catch (IOException e) { throw new DatabaseException(e); } catch (ClassNotFoundException e) { throw new DatabaseException(e); } } return null; } @Override protected SpreadsheetBook createEngine(ReadGraph graph, String id) throws DatabaseException { Variable run = Variables.getVariable(graph, id); Variable context = ProxyVariables.proxyVariableInput(graph, run); if (context != null) { Variable base = ProxyVariables.proxyVariableBase(graph, run); Resource bookResource = base.getRepresents(graph); Resource contextResource = context.getRepresents(graph); if (contextResource != null) { SpreadsheetBook ic = getPossibleInitialCondition(graph, contextResource, bookResource); if (ic != null) return ic; } SpreadsheetBook ic = getPossibleInitialCondition(graph, bookResource, bookResource); if (ic != null) return ic; } SpreadsheetBook book = new SpreadsheetBook(); Variable base = ProxyVariables.proxyVariableBase(graph, run); Resource bookResource = base.getRepresents(graph); Variable configuration = Variables.getVariable(graph, bookResource); SpreadsheetSynchronizationEventHandler handler = new SpreadsheetSynchronizationEventHandler(graph, book); Synchronizer synchronizer = new Synchronizer(graph); synchronizer.fullSynchronization(configuration, handler); return book; } @Override protected StandardRealm createRealm(SpreadsheetBook engine, String id) { return new SpreadsheetRealm(engine, id); } @Override public void removeRealm(WriteGraph graph, String id) throws DatabaseException { StandardRealm realm = getOrCreateRealm(graph, id); SpreadsheetEvaluationEnvironment.removeInstance(realm.getEngine()); super.removeRealm(graph, id); } // Utility function for SCL, this should maybe be replaced with something better in the future public static void removeSpreadsheetSession(WriteGraph graph, Variable runVariable) throws DatabaseException { String uri = runVariable.getParent(graph).getURI(graph); getInstance().removeRealm(graph, uri); } }