Changeset 96 for java/main/src/main/java/com/framsticks/core/Instance.java
- Timestamp:
- 07/04/13 20:29:50 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
java/main/src/main/java/com/framsticks/core/Instance.java
r90 r96 1 1 package com.framsticks.core; 2 3 import java.util.HashSet;4 import java.util.Iterator;5 import java.util.LinkedList;6 import java.util.List;7 import java.util.Set;8 2 9 3 import javax.annotation.Nonnull; 10 4 11 import org.apache.log4j.Logger;12 13 import com.framsticks.communication.File;14 5 import com.framsticks.params.AccessInterface; 15 6 import com.framsticks.params.CompositeParam; 16 import com.framsticks.params.ConstructionException;17 7 import com.framsticks.params.FramsClass; 18 import com.framsticks.params.ListAccess;19 import com.framsticks.params.Param;20 import com.framsticks.params.ParamsPackage;21 8 import com.framsticks.params.Registry; 22 9 import com.framsticks.params.ValueParam; 23 import com.framsticks.params.annotations.AutoAppendAnnotation;24 import com.framsticks.params.annotations.FramsClassAnnotation;25 import com.framsticks.params.types.ObjectParam;26 10 import com.framsticks.params.types.ProcedureParam; 27 import com.framsticks.parsers.Loaders;28 import com.framsticks.parsers.MultiParamLoader;29 import com.framsticks.util.FramsticksException;30 11 import com.framsticks.util.StateFunctor; 31 import com.framsticks.util.UnsupportedOperationException; 32 import com.framsticks.util.dispatching.Dispatching; 12 import com.framsticks.util.dispatching.Dispatcher; 33 13 import com.framsticks.util.dispatching.Future; 34 import com.framsticks.util.dispatching.RunAt; 35 import com.framsticks.util.dispatching.Thread; 36 import com.framsticks.util.lang.Casting; 14 import com.framsticks.util.dispatching.Joinable; 37 15 38 /** 39 * @author Piotr Sniegowski 40 */ 41 @FramsClassAnnotation 42 public abstract class Instance extends Thread<Instance> implements Entity { 16 public interface Instance extends Dispatcher<Instance>, Joinable { 43 17 44 private static final Logger log = Logger.getLogger(Instance.class.getName()); 18 public @Nonnull Node getRoot(); 19 public @Nonnull void setRoot(Node node); 45 20 46 private Node root; 21 public @Nonnull AccessInterface prepareAccess(CompositeParam param); 22 public void takeAllFrom(Registry source); 47 23 48 protected @Nonnull Node setRoot(CompositeParam param, Object object) { 49 // if (isRootAssigned()) { 50 // throw new FramsticksException().msg("root is already assigned"); 51 // } 52 // assert isActive(); 53 root = new Node(param, object); 54 return root; 55 } 24 public void addListener(InstanceListener listener); 25 public void removeListener(InstanceListener listener); 56 26 57 protected @Nonnull Node getRoot() { 58 // assert isActive(); 59 assert root != null; 60 return root; 61 } 27 public void notifyOfFetch(Path path); 62 28 63 public boolean isRootAssigned() { 64 // assert isActive(); 65 return root != null; 66 } 29 public FramsClass getInfoFromCache(String id); 67 30 68 p rotected Set<InstanceListener> listeners = new HashSet<InstanceListener>();31 public void putInfoIntoCache(FramsClass framclass); 69 32 70 public Instance() { 71 setName("entity"); 72 } 73 74 protected void fetchInfo(Path path, Future<FramsClass> future) { 75 future.result(null, new UnsupportedOperationException()); 76 } 77 78 public void resolve(Path path, Future<Path> future) { 79 assert isActive(); 80 assert path.isOwner(this); 81 if (path.getTop().getObject() != null) { 82 future.result(path, null); 83 return; 84 } 85 AccessInterface access = bindAccess(path.getUnder()); 86 Object object = access.get(path.getTop().getParam(), Object.class); 87 if (object == null) { 88 future.result(path, null); 89 return; 90 } 91 future.result(path.appendResolution(object), null); 92 } 33 public void resolve(Path path, Future<Path> future); 93 34 94 35 /** This is part of the Instance interface. 95 36 * 96 37 */ 97 public abstract void fetchValue(Path path,Param param, StateFunctor stateFunctor);38 public void fetchValue(Path path, ValueParam param, StateFunctor stateFunctor); 98 39 99 40 /** This is part of the Instance interface. 100 41 * 101 42 */ 102 public abstractvoid fetchValues(Path path, StateFunctor stateFunctor);43 public void fetchValues(Path path, StateFunctor stateFunctor); 103 44 104 45 /** This is part of the Instance interface. 105 46 * 106 47 */ 107 public abstract void call(Path path, ProcedureParam param, Object[] arguments, StateFunctor stateFunctor);48 public void call(Path path, ProcedureParam param, Object[] arguments, Future<Object> future); 108 49 109 p rotected void tryRegisterOnChangeEvents(Path path) {50 public void storeValue(Path path, ValueParam param, Object value, StateFunctor stateFunctor); 110 51 111 }52 public void fetchInfo(Path path, Future<FramsClass> future); 112 53 113 public void storeValue(Path path, Param param, Object value, final StateFunctor stateFunctor) { 114 assert isActive(); 115 dispatch(new RunAt<Instance>() { 116 @Override 117 public void run() { 118 stateFunctor.call(new UnsupportedOperationException()); 119 } 120 }); 121 } 122 123 protected void fireRun(Exception e) { 124 for (InstanceListener l : this.listeners) { 125 l.onRun(e); 126 } 127 } 128 129 protected void fireStop(Exception e) { 130 for (InstanceListener l : this.listeners) { 131 l.onStop(e); 132 } 133 } 134 135 public void addListener(final InstanceListener listener) { 136 assert Dispatching.isThreadSafe(); 137 Dispatching.dispatchIfNotActive(this, new RunAt<Instance>() { 138 @Override 139 public void run() { 140 listeners.add(listener); 141 } 142 }); 143 } 144 145 public void removeListener(final InstanceListener listener) { 146 assert Dispatching.isThreadSafe(); 147 Dispatching.dispatchIfNotActive(this, new RunAt<Instance>() { 148 @Override 149 public void run() { 150 listeners.remove(listener); 151 } 152 }); 153 } 154 155 protected void fireListChange(Path path, ListChange change) { 156 assert isActive(); 157 for (InstanceListener l : this.listeners) { 158 l.onListChange(path, change); 159 } 160 } 161 162 protected void fireFetch(Path path) { 163 assert isActive(); 164 for (InstanceListener l : this.listeners) { 165 l.onFetch(path); 166 } 167 } 168 169 public final FramsClass getInfoFromCache(Path path) { 170 return getInfoFromCache(path.getTop().getParam().getContainedTypeName()); 171 } 172 173 public FramsClass getInfoFromCache(String id) { 174 assert isActive(); 175 return registry.getFramsClass(id); 176 } 177 178 protected Registry registry = new Registry(); 179 180 public AccessInterface createAccess(String name) throws ConstructionException { 181 assert isActive(); 182 return registry.createAccess(name); 183 } 184 185 // TODO: make ValueParam 186 public <T> T get(Node node, Param childParam, Class<T> type) { 187 return bindAccess(node).get((ValueParam) childParam, type); 188 } 189 190 public void findInfo(final Path path, final Future<FramsClass> future) { 191 assert isActive(); 192 final String name = path.getTop().getParam().getContainedTypeName(); 193 final FramsClass framsClass = getInfoFromCache(name); 194 if (framsClass != null) { 195 log.trace("info for " + name + " found in cache"); 196 future.result(framsClass, null); 197 return; 198 } 199 fetchInfo(path, future); 200 } 201 202 public final AccessInterface bindAccess(String path) { 203 return bindAccess(getPath(path)); 204 } 205 206 public final AccessInterface bindAccess(Node node) { 207 assert isActive(); 208 assert node.getObject() != null; 209 210 try { 211 AccessInterface access = registry.prepareAccess(node.getParam()); 212 if (access == null) { 213 throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam()); 214 } 215 return access.select(node.getObject()); 216 } catch (ConstructionException e) { 217 log.error("failed to bind access for " + node.getParam() + ": " + e); 218 } 219 return null; 220 } 221 222 public final <T> T getParam(Path path, String id, Class<T> type) { 223 return Casting.tryCast(type, registry.prepareAccess(path.getTop().getParam()).getParam(id)); 224 } 225 226 public final AccessInterface bindAccess(Path path) { 227 path.assureResolved(); 228 return bindAccess(path.getTop()); 229 } 230 231 public void resolve(final String targetPath, final Future<Path> future) { 232 assert isActive(); 233 final Path path = getPath(targetPath); 234 resolve(path, new Future<Path>() { 235 @Override 236 public void result(Path result, Exception e) { 237 assert isActive(); 238 if (e != null) { 239 future.result(path, e); 240 return; 241 } 242 if (path.isResolved(targetPath)) { 243 future.result(path, null); 244 return; 245 } 246 if (path.isResolved()) { 247 future.result(path, new Exception("testing")); 248 return; 249 } 250 resolve(targetPath, future); 251 } 252 }); 253 } 254 255 public void resolveAndFetch(final String targetPath, final Future<Path> future) { 256 assert isActive(); 257 resolve(targetPath, new Future<Path>() { 258 @Override 259 public void result(final Path path, Exception e) { 260 if (e != null) { 261 future.result(path, e); 262 return; 263 } 264 assert path.isResolved(targetPath); 265 fetchValues(path, new StateFunctor() { 266 @Override 267 public void call(Exception e) { 268 future.result(path, e); 269 } 270 }); 271 } 272 }); 273 } 274 275 public Path createIfNeeded(String path) { 276 Path p; 277 while (!(p = getPath(path)).isResolved(path)) { 278 create(p); 279 } 280 return p; 281 } 282 283 public Path createIfNeeded(Path path) { 284 assert isActive(); 285 if (path.isResolved()) { 286 return path; 287 } 288 return create(path); 289 } 290 291 public Path create(Path path) { 292 assert isActive(); 293 assert !path.isResolved(); 294 Path resolved = path.tryFindResolution(); 295 if (!resolved.isResolved()) { 296 log.debug("creating: " + path); 297 AccessInterface access = registry.prepareAccess(path.getTop().getParam()); 298 assert access != null; 299 Object child = access.createAccessee(); 300 assert child != null; 301 if (path.size() == 1) { 302 setRoot(getRoot().getParam(), child); 303 } else { 304 bindAccess(path.getUnder()).set(path.getTop().getParam(), child); 305 } 306 resolved = path.appendResolution(child); 307 } 308 tryRegisterOnChangeEvents(resolved); 309 return resolved; 310 } 311 312 313 314 315 public @Nonnull FramsClass processFetchedInfo(File file) { 316 assert isActive(); 317 FramsClass framsClass = Loaders.loadFramsClass(file.getContent()); 318 if ("/".equals(file.getPath())) { 319 if (getRoot().getParam().getContainedTypeName() == null) { 320 setRoot(Param.build().name("Instance").id(getName()).type("o " + framsClass.getId()).finish(CompositeParam.class), getRoot().getObject()); 321 } 322 } 323 registry.putFramsClass(framsClass); 324 return framsClass; 325 } 326 327 public void processFetchedValues(Path path, List<File> files) { 328 assert isActive(); 329 assert files.size() == 1; 330 assert path.isTheSame(files.get(0).getPath()); 331 Node node = path.getTop(); 332 MultiParamLoader loader = new MultiParamLoader(); 333 loader.setNewSource(files.get(0).getContent()); 334 loader.addBreakCondition(MultiParamLoader.Status.AfterObject); 335 336 try { 337 if (node.getParam() instanceof ObjectParam) { 338 loader.addAccessInterface(bindAccess(node)); 339 loader.go(); 340 fireFetch(path); 341 return; 342 } 343 344 ListAccess listAccess = ((ListAccess)bindAccess(node)); 345 assert listAccess != null; 346 listAccess.clearValues(); 347 348 AccessInterface elementAccess = listAccess.getElementAccess(); 349 loader.addAccessInterface(elementAccess); 350 MultiParamLoader.Status status; 351 while ((status = loader.go()) != MultiParamLoader.Status.Finished) { 352 if (status == MultiParamLoader.Status.AfterObject) { 353 AccessInterface accessInterface = loader.getLastAccessInterface(); 354 355 String id = listAccess.computeIdentifierFor(accessInterface.getSelected()); 356 //TODO listAccessParam 357 Param param = Param.build().forAccess(accessInterface).id(id).finish(); 358 Object child = accessInterface.getSelected(); 359 accessInterface.select(null); 360 assert child != null; 361 bindAccess(node).set((ValueParam) param, child); 362 } 363 } 364 365 fireFetch(path); 366 } catch (Exception e) { 367 log.error("exception occurred while loading: " + e); 368 } 369 370 } 371 372 public static Iterator<String> splitPath(String path) { 373 List<String> list = new LinkedList<String>(); 374 for (String s : path.split("/")) { 375 if (!s.isEmpty()) { 376 list.add(s); 377 } 378 } 379 return list.iterator(); 380 } 381 382 public Registry getRegistry() { 383 return registry; 384 } 385 386 public Path getPath(String textual) { 387 return Path.build().resolve(this, textual).finish(); 388 } 389 390 public Path getRootPath() { 391 return getPath("/"); 392 } 393 394 @AutoAppendAnnotation 395 public void usePackage(ParamsPackage paramsPackage) { 396 log.debug("using package " + paramsPackage + " in instance " + this); 397 paramsPackage.register(registry); 398 } 399 400 @AutoAppendAnnotation 401 public void takeFromRegistry(Registry registry) { 402 log.debug("taking from registry " + registry + " in instance " + this); 403 this.registry.takeAllFrom(registry); 404 } 405 406 @Override 407 protected void joinableStart() { 408 dispatch(new RunAt<Instance>() { 409 @Override 410 public void run() { 411 if (!isRootAssigned()) { 412 setRoot(Param.build().name("Instance").id(getName()).type("o").finish(CompositeParam.class), null); 413 } 414 } 415 }); 416 super.joinableStart(); 417 } 418 54 public Path create(Path path); 419 55 } 420
Note: See TracChangeset
for help on using the changeset viewer.