Ignore:
Timestamp:
07/04/13 20:29:50 (11 years ago)
Author:
psniegowski
Message:

HIGHLIGHTS:

  • cleanup Instance management
    • extract Instance interface
    • extract Instance common algorithms to InstanceUtils?
  • fix closing issues: Ctrl+C or window close button

properly shutdown whole program

by Java Framsticks framework

  • fix parsing and printing of all request types
  • hide exception passing in special handle method of closures
    • substantially improve readability of closures
    • basically enable use of exception in asynchronous closures

(thrown exception is transported back to the caller)

  • implement call request on both sides

CHANGELOG:
Further improve calling.

Improve instance calling.

Calling is working on both sides.

Improve exception handling in testing.

Waiters do not supercede other apllication exception being thrown.

Finished parsing and printing of all request types (with tests).

Move implementation and tests of request parsing to Request.

Add tests for Requests.

Improve waits in asynchronours tests.

Extract more algorithms to InstanceUtils?.

Extract Instance.resolve to InstanceUtils?.

Improve naming.

Improve passing exception in InstanceClient?.

Hide calling of passed functor in StateCallback?.

Hide Exception passing in asynchronous closures.

Hide exception passing in Future.

Make ResponseCallback? an abstract class.

Make Future an abstract class.

Minor change.

Move getPath to Path.to()

Move bindAccess to InstanceUtils?.

Extract common things to InstanceUtils?.

Fix synchronization bug in Connection.

Move resolve to InstanceUtils?.

Allow names of Joinable to be dynamic.

Add support for set request server side.

More fixes in communication.

Fix issues with parsing in connection.

Cut new line characters when reading.

More improvements.

Migrate closures to FramsticksException?.

Several changes.

Extract resolveAndFetch to InstanceUtils? algorithms.

Test resolving and fetching.

More fixes with function signature deduction.

Do not print default values in SimpleAbstractAccess?.

Add test of FramsClass? printing.

Improve FramsticksException? messages.

Add explicit dispatcher synchronization feature.

Rework assertions in tests.

Previous solution was not generic enough.

Allow addition of joinables to collection after start.

Extract SimulatorInstance? from RemoteInstance?.

Remove PrivateJoinableCollection?.

Improve connections.

Move shutdown hook to inside the Monitor.

It should work in TestNG tests, but it seems that
hooks are not called.

In ServerTest? client connects to testing server.

Move socket initialization to receiver thread.

Add proper closing on Ctrl+C (don't use signals).

Fix bugs with server accepting connections.

Merge Entity into Joinable.

Reworking ServerInstance?.

Extract more algorithm to InstanceUtils?.

Extract some common functionality from AbstractInstance?.

Functions were placed in InstanceUtils?.

Hide registry of Instance.

Use ValueParam? in Instance interface.

Minor change.

Extract Instance interface.

Old Instance is now AbstractInstance?.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • java/main/src/main/java/com/framsticks/core/Instance.java

    r90 r96  
    11package 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;
    82
    93import javax.annotation.Nonnull;
    104
    11 import org.apache.log4j.Logger;
    12 
    13 import com.framsticks.communication.File;
    145import com.framsticks.params.AccessInterface;
    156import com.framsticks.params.CompositeParam;
    16 import com.framsticks.params.ConstructionException;
    177import com.framsticks.params.FramsClass;
    18 import com.framsticks.params.ListAccess;
    19 import com.framsticks.params.Param;
    20 import com.framsticks.params.ParamsPackage;
    218import com.framsticks.params.Registry;
    229import 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;
    2610import com.framsticks.params.types.ProcedureParam;
    27 import com.framsticks.parsers.Loaders;
    28 import com.framsticks.parsers.MultiParamLoader;
    29 import com.framsticks.util.FramsticksException;
    3011import com.framsticks.util.StateFunctor;
    31 import com.framsticks.util.UnsupportedOperationException;
    32 import com.framsticks.util.dispatching.Dispatching;
     12import com.framsticks.util.dispatching.Dispatcher;
    3313import 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;
     14import com.framsticks.util.dispatching.Joinable;
    3715
    38 /**
    39  * @author Piotr Sniegowski
    40  */
    41 @FramsClassAnnotation
    42 public abstract class Instance extends Thread<Instance> implements Entity {
     16public interface Instance extends Dispatcher<Instance>, Joinable {
    4317
    44         private static final Logger log = Logger.getLogger(Instance.class.getName());
     18        public @Nonnull Node getRoot();
     19        public @Nonnull void setRoot(Node node);
    4520
    46         private Node root;
     21        public @Nonnull AccessInterface prepareAccess(CompositeParam param);
     22        public void takeAllFrom(Registry source);
    4723
    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);
    5626
    57         protected @Nonnull Node getRoot() {
    58                 // assert isActive();
    59                 assert root != null;
    60                 return root;
    61         }
     27        public void notifyOfFetch(Path path);
    6228
    63         public boolean isRootAssigned() {
    64                 // assert isActive();
    65                 return root != null;
    66         }
     29        public FramsClass getInfoFromCache(String id);
    6730
    68         protected Set<InstanceListener> listeners = new HashSet<InstanceListener>();
     31        public void putInfoIntoCache(FramsClass framclass);
    6932
    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);
    9334
    9435        /** This is part of the Instance interface.
    9536         *
    9637         */
    97         public abstract void fetchValue(Path path, Param param, StateFunctor stateFunctor);
     38        public void fetchValue(Path path, ValueParam param, StateFunctor stateFunctor);
    9839
    9940        /** This is part of the Instance interface.
    10041         *
    10142         */
    102         public abstract void fetchValues(Path path, StateFunctor stateFunctor);
     43        public void fetchValues(Path path, StateFunctor stateFunctor);
    10344
    10445        /** This is part of the Instance interface.
    10546         *
    10647         */
    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);
    10849
    109         protected void tryRegisterOnChangeEvents(Path path) {
     50        public void storeValue(Path path, ValueParam param, Object value, StateFunctor stateFunctor);
    11051
    111         }
     52        public void fetchInfo(Path path, Future<FramsClass> future);
    11253
    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);
    41955}
    420 
Note: See TracChangeset for help on using the changeset viewer.