]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph.loader/src/org/simantics/scenegraph/loader/ScenegraphLoaderProcess.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scenegraph.loader / src / org / simantics / scenegraph / loader / ScenegraphLoaderProcess.java
1 package org.simantics.scenegraph.loader;
2
3 import java.util.Set;
4
5 import org.simantics.Simantics;
6 import org.simantics.db.Disposable;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.RequestProcessor;
9 import org.simantics.db.Resource;
10 import org.simantics.db.common.primitiverequest.PossibleResource;
11 import org.simantics.db.common.procedure.adapter.ListenerSupport;
12 import org.simantics.db.common.request.TernaryRead;
13 import org.simantics.db.common.request.UnaryRead;
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.db.layer0.request.ResourceVariable;
16 import org.simantics.db.layer0.variable.Variable;
17 import org.simantics.db.layer0.variable.VariableRepository;
18 import org.simantics.scenegraph.INode;
19 import org.simantics.scenegraph.ParentNode;
20 import org.simantics.utils.datastructures.Pair;
21 import org.slf4j.LoggerFactory;
22
23 import gnu.trove.set.hash.THashSet;
24
25 public class ScenegraphLoaderProcess implements Disposable, ListenerSupport {
26
27         private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ScenegraphLoaderProcess.class);
28
29         final private String name;
30         final Class<?> loaderClass;
31
32         protected INode root;
33
34         private boolean disposed = false;
35         
36         final protected Set<String> registeredURIs = new THashSet<String>();
37         
38         public ScenegraphLoaderProcess(String name) {
39                 this(null, ScenegraphLoader.class, name);
40         }
41
42         public ScenegraphLoaderProcess(INode root, String name) {
43                 this(root, ScenegraphLoader.class, name);
44         }
45         
46         public ScenegraphLoaderProcess(INode root, Class<?> loaderClass, String name) {
47                 this.root = root;
48                 this.loaderClass = loaderClass;
49                 this.name = name;
50                 //System.out.println("NEW ScenegraphLoaderProcess(" + name + "): " + this);
51                 //new Exception("NEW ScenegraphLoaderProcess(" + name + "): " + this).printStackTrace();
52         }
53
54         public INode getRoot() {
55                 return root;
56         }
57         
58         @Override
59         public String toString() {
60                 return name;
61         }
62
63         protected void initialize(RequestProcessor processor, Variable configuration) throws DatabaseException {
64                 
65         }
66         
67         final public <N extends ParentNode<?>> N load(final String curi, final Resource runtime) throws DatabaseException {
68                 return load(Simantics.getSession(), curi, runtime);
69         }
70
71         final public <N extends ParentNode<?>> N load(RequestProcessor processor, final String curi, final Resource runtime) throws DatabaseException {
72                 Resource resource = processor.sync(new PossibleResource(curi));
73                 if(resource == null) throw new IllegalArgumentException("The given URI is invalid: " + curi);
74                 return load(processor, resource, runtime);
75         }
76
77         final public <N extends ParentNode<?>> N load(Resource configuration, Resource runtime) throws DatabaseException {
78                 return load(Simantics.getSession(), configuration, runtime);
79         }
80
81         final public <N extends ParentNode<?>> N load(RequestProcessor processor, Resource configuration, Resource runtime) throws DatabaseException {
82                 N root = (N)getRoot();
83                 return load(processor, getVariable(processor, this, configuration, runtime, root));
84         }
85         
86         final public Variable getVariable(RequestProcessor processor, String curi, Resource runtime) throws DatabaseException {
87                 Resource resource = processor.sync(new PossibleResource(curi));
88                 if(resource == null) throw new IllegalArgumentException("The given URI is invalid: " + curi);
89                 return getVariable(processor, this, resource, runtime, root);
90         }
91         
92         final static public Variable getVariable(RequestProcessor processor, final ScenegraphLoaderProcess process, final Resource configuration, final Resource runtime, final INode root) throws DatabaseException {
93                 
94                 assert(root != null);
95
96                 Pair<Variable,String> result = processor.sync(new TernaryRead<INode, Resource, Resource, Pair<Variable,String>>(root, runtime, configuration) {
97
98                         @Override
99                         public Pair<Variable,String> perform(ReadGraph graph) throws DatabaseException {
100                                 Variable conf = graph.sync(new ResourceVariable(parameter3));
101                                 Variable result = new ScenegraphVariable(conf, parameter3, parameter2, parameter);
102                                 return Pair.make(result, result.getURI(graph));
103                         }
104                         
105                 });
106
107                 VariableRepository.register(result.second, result.first);
108                 if(process != null) process.registeredURIs.add(result.second);
109                 return result.first;
110                 
111         }
112         
113         final public <N extends ParentNode<?>> N load(RequestProcessor processor, final Variable configuration) throws DatabaseException {
114                 
115                 initialize(processor, configuration);
116                 N root = (N)getRoot();
117                 load(processor, configuration, root);
118                 return root;
119                 
120         }
121
122         <T extends ScenegraphLoader> Class<T> getLoaderClass() {
123                 return (Class<T>)ScenegraphLoader.class;
124         }
125         
126         protected ScenegraphLoader getLoader(RequestProcessor processor, Variable configuration) throws DatabaseException {
127                 
128                 return processor.sync(new UnaryRead<Variable, ScenegraphLoader>(configuration) {
129
130                         @Override
131                         public ScenegraphLoader perform(ReadGraph graph) throws DatabaseException {
132                                 return parameter.adapt(graph, getLoaderClass());
133                         }
134
135                 });
136         }
137         
138         @SuppressWarnings("unchecked")
139         final private INode load(RequestProcessor processor, Variable configuration, ParentNode<?> current) throws DatabaseException {
140                 
141                 ScenegraphLoader loader = getLoader(processor, configuration);
142                 
143                 INode node = loader.create(processor, this, current, configuration);
144                 if(node instanceof ParentNode) {
145                 
146                         for(Variable child : ScenegraphLoaderUtils.getChildren(processor, configuration)) {
147                                 load(processor, child, (ParentNode<INode>)node);
148                         }
149                         
150                 }
151                 
152                 return node;
153                 
154         }
155
156         @Override
157         public void exception(Throwable t) {
158                 LOGGER.error("Unexpected problem encountered", t);
159         }
160
161         @Override
162         public boolean isDisposed() {
163                 return disposed;
164         }
165
166         @Override
167         public void dispose() {
168                 //System.out.println("DISPOSE ScenegraphLoaderProcess(" + name + "): " + this);
169                 //new Exception("DISPOSED ScenegraphLoaderProcess(" + name + "): " + this).printStackTrace();
170                 disposed = true;
171         }
172         
173 }