Ignore:
Timestamp:
07/10/13 22:41:02 (11 years ago)
Author:
psniegowski
Message:

HIGHLIGTS:

  • complete events implementation
  • add CLI in Java Framsticks server
  • add automatic registration for events in GUI
  • improve objects fetching (object are never overwritten with new instances)
  • properly react for ListChange? events
  • add ListPanel? with table view
    • columns to be shown may be statically specified in configuration
    • currently modyfying data through tables is not available
  • improve maven configuration
    • configuration file may be specified without touching pom.xml

CHANGELOG:
Extract constants from Flags into ParamFlags? and SetStateFlags?.

Extract flags I/O to FlagsUtils? class.

Configured maven to exec given resource configuration.

For example:
mvn exec:exec -Dframsticks.config=/configs/managed-console.xml

Cleanup pom.xml

Rename ObjectTree? to LocalTree? (also make LocalTree? and RemoteTree? final).

Minor change.

Add maximum number of columns in ListPanelProvider?.

Improve ColumnsConfig? interpretation.

Automatically fill FramsClass?.name if trying to construct empty.

Improve identitifer case mangling in XmlLoader?.

Introduce configurable ColumnsConfig?.

Draft working version of ListPanel?.

Table is being shown (although empty).

More improvements to table building.

Move some functionality from Frame to TreeModel?.

Move tree classes in gui to separate package.

Remove old table related classes.

Add draft implementation of TableModel?.

Redirect ParamBuilder?.forAccess to AccessInterface?.

Optimize ParamBuilder?.forAccess()

Do not clear list when loading.

Do not load fetched values directly.

Implement different AccessInterface? copying policy.

Optimize fetching values routine.

Remove Mode enum (work out get semantics).

Some improvements to ListChange? handling.

Improve UniqueListAccess?.

Add reaction for ListChanges? in the TreeNode?.

EventListeners? are being added in the TreeNode?.

Listeners for ListParams? are now very naive (they download
whole list).

Automatially register on events in GUI.

Events are working in RemoteTree? and Server.

Move listeners to the ClientSideManagedConnection?.

Remove old classes responsible for event subscriptions.

Improve event reading.

Improve events handling at server side.

Add register attribute in FramsClassAnnotation?
to automatically also register other classes.

Registering events works.

Setup for remote listeners registration.

More improvements.

Minor changes.

Add rootTree to the ClientAtServer?.

Moving CLI to the ClientAtServer?.

Fix bug: use Void.TYPE instead of Void.class

More development around CLI.

  • Improve Path resolving.

Add synthetic root to ObjectTree?.

It is needed to allow sybling for the original root
that would containg CLI.

Some work with registering events in RemoteTree?.

Draft implementation of listener registering in RemoteTree?.

Support events registration in the ObjectTree?.

Add events support to ReflectionAccess?.

EventParam? is recognized by ParamCandidate?.

Prepare interface for Events across project.

Add EventListener? and API for listeners in Tree.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • java/main/src/main/java/com/framsticks/remote/RemoteTree.java

    r98 r99  
    77import com.framsticks.communication.queries.SetRequest;
    88import com.framsticks.core.AbstractTree;
    9 import com.framsticks.core.Mode;
    10 import com.framsticks.core.ListChange;
    119import com.framsticks.core.Path;
    1210import com.framsticks.params.*;
     11import com.framsticks.params.EventListener;
    1312import com.framsticks.params.annotations.AutoAppendAnnotation;
    1413import com.framsticks.params.annotations.FramsClassAnnotation;
     
    2827import com.framsticks.util.dispatching.ThrowExceptionHandler;
    2928import com.framsticks.util.lang.Casting;
    30 import com.framsticks.util.lang.Pair;
    3129import com.framsticks.util.dispatching.RunAt;
    3230import static com.framsticks.core.TreeOperations.*;
     
    4240 */
    4341@FramsClassAnnotation
    44 public class RemoteTree extends AbstractTree implements JoinableParent {
     42public final class RemoteTree extends AbstractTree implements JoinableParent {
    4543
    4644        private final static Logger log = Logger.getLogger(RemoteTree.class);
    4745
    4846        protected ClientSideManagedConnection connection;
    49 
    50         protected final Set<Pair<Path, Subscription<?>>> subscriptions = new HashSet<>();
    51 
    52         public Pair<Path, Subscription<?>> getSubscription(Path path) {
    53                 for (Pair<Path, Subscription<?>> s : subscriptions) {
    54                         if (s.first.isTheSameObjects(path)) {
    55                                 return s;
    56                         }
    57                 }
    58                 return null;
    59         }
    6047
    6148        public RemoteTree() {
     
    8875
    8976        @Override
    90         public void get(final Path path, final ValueParam param, Mode mode, final Future<Object> future) {
     77        public void get(final Path path, final ValueParam param, final Future<Object> future) {
    9178                assert isActive();
    9279                assert param != null;
     
    166153
    167154        @Override
    168         public void get(final Path path, final Mode mode, final Future<Path> future) {
     155        public void get(final Path path, final Future<Path> future) {
    169156                assert isActive();
    170157
     
    187174        }
    188175
    189 
    190         @Override
    191         protected void tryRegisterOnChangeEvents(final Path path) {
    192                 assert isActive();
    193                 AccessInterface access = bindAccess(path);
    194                 if (!(access instanceof ListAccess)) {
    195                         return;
    196                 }
    197 
    198                 assert path.size() >= 2;
    199                 FramsClass underFramsClass = getInfoFromCache(path.getUnder().getParam().getContainedTypeName());
    200 
    201                 EventParam changedEvent;
    202                 try {
    203                         changedEvent = underFramsClass.getParamEntry(path.getTop().getParam().getId() + "_changed", EventParam.class);
    204                 } catch (FramsticksException e) {
    205                         return;
    206                 }
    207 
    208                 log.debug("registering for " + changedEvent);
    209                 if (getSubscription(path) != null) {
    210                         return;
    211                 }
    212 
    213                 final Pair<Path, Subscription<?>> temporary = new Pair<>(path, null);
    214                 subscriptions.add(temporary);
    215 
    216                 connection.subscribe(path.getTextual() + "_changed", this, new SubscriptionCallback<Tree>() {
    217                         @Override
    218                         public EventCallback subscribed(final Subscription<? super Tree> subscription) {
    219                                 if (subscription == null) {
    220                                         log.error("failed to subscribe for change event for " + path);
    221                                         return null;
    222                                 }
    223                                 log.debug("subscribed for change event for " + path);
    224                                 // subscription.setDispatcher(RemoteInstance.this);
    225                                 RemoteTree.this.dispatch(new RunAt<Tree>(this) {
    226                                         @Override
    227                                         protected void runAt() {
    228                                                 subscriptions.remove(temporary);
    229                                                 subscriptions.add(new Pair<Path, Subscription<?>>(path, subscription));
    230                                         }
    231                                 });
    232                                 return new EventCallback() {
    233                                         @Override
    234                                         public void call(List<File> files) {
    235                                                 assert isActive();
    236                                                 assert files.size() == 1;
    237                                                 final MultiParamLoader loader = new MultiParamLoader();
    238                                                 loader.setNewSource(files.get(0).getContent());
    239                                                 loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
    240                                                 loader.addListener(MultiParamLoader.Status.OnComment, new MultiParamLoader.StatusListener() {
    241 
    242                                                         @Override
    243                                                         public void onStatusChange() {
    244                                                                 throw new FramsticksException().msg("multi param loader error").arg("line", loader.getCurrentLine());
    245                                                         }
    246                                                 });
    247                                                 ReflectionAccess access = new ReflectionAccess(ListChange.class, FramsClass.build().forClass(ListChange.class));
    248                                                 loader.addAccessInterface(access);
    249 
    250                                                 MultiParamLoader.Status status;
    251                                                 while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
    252                                                         if (status == MultiParamLoader.Status.AfterObject) {
    253                                                                 AccessInterface accessInterface = loader.getLastAccessInterface();
    254                                                                 reactToChange(path, (ListChange) accessInterface.getSelected());
    255                                                         }
    256                                                 }
    257                                         }
    258                                 };
    259                         }
    260                 });
    261         }
    262 
    263         protected Future<Path> futureListChanger(final ListChange listChange, final String path) {
    264                 return new FutureHandler<Path>(Logging.logger(log, "failed to " + listChange, path)) {
    265                         @Override
    266                         protected void result(Path result) {
    267                                 log.debug(listChange + ": " + result);
    268                         }
    269                 };
    270         }
    271 
    272         protected void reactToChange(final Path path, final ListChange listChange) {
    273                 assert isActive();
    274                 log.debug("reacting to change " + listChange + " in " + path);
    275                 AccessInterface access = bindAccess(path);
    276                 assert access != null;
    277 
    278                 if ((listChange.getAction() == ListChange.Action.Modify) && (listChange.getPosition() == -1)) {
    279                         final String p = path.getTextual();
    280                         tryGet(this, p, futureListChanger(listChange, p));
    281                         return;
    282                 }
    283 
    284                 CompositeParam childParam = Casting.tryCast(CompositeParam.class, access.getParam(listChange.getBestIdentifier()));
    285                 assert childParam != null;
    286                 switch (listChange.getAction()) {
    287                         case Add: {
    288                                 final String p = path.getTextual() + "/" + childParam.getId();
    289                                 tryGet(this, p, futureListChanger(listChange, p));
    290                                 break;
    291                         }
    292                         case Remove: {
    293                                 access.set(childParam, null);
    294                                 break;
    295                         }
    296                         case Modify: {
    297                                 final String p = path.getTextual() + "/" + childParam.getId();
    298                                 tryGet(this, p, futureListChanger(listChange, p));
    299                                 break;
    300                         }
    301                 }
    302         }
    303 
    304176        @Override
    305177        public void set(final Path path, final PrimitiveParam<?> param, final Object value, final Future<Integer> future) {
     
    380252        }
    381253
    382         // @Override
    383         // public Path create(Path path) {
    384         //      assert isActive();
    385         //      assert !path.isResolved();
    386         //      Path resolved = path.tryFindResolution();
    387         //      if (!resolved.isResolved()) {
    388         //              log.debug("creating: " + path);
    389         //              //TODO: access parent here, check if it is valid, only then create
    390         //              AccessInterface access = registry.prepareAccess(path.getTop().getParam());
    391         //              assert access != null;
    392         //              Object child = access.createAccessee();
    393         //              assert child != null;
    394         //              if (path.size() == 1) {
    395         //                      setRoot(new Node(getRoot().getParam(), child));
    396         //              } else {
    397         //                      bindAccess(this, path.getUnder()).set(path.getTop().getParam(), child);
    398         //              }
    399         //              resolved = path.appendResolution(child);
    400         //      }
    401         //      tryRegisterOnChangeEvents(resolved);
    402         //      return resolved;
    403         // }
     254        protected final Map<EventListener<?>, EventListener<File>> proxyListeners = new IdentityHashMap<>();
     255
     256        public <A> void addListener(Path path, EventParam param, final EventListener<A> listener, final Class<A> argumentType, final Future<Void> future) {
     257                assert isActive();
     258                assert path.isResolved();
     259                if ((!argumentType.equals(Object.class)) && (null == registry.getFramsClassForJavaClass(argumentType))) {
     260                        registry.registerAndBuild(argumentType);
     261                }
     262
     263                final EventListener<File> proxyListener = new EventListener<File>() {
     264
     265                        @Override
     266                        public void action(final File file) {
     267                                Dispatching.dispatchIfNotActive(RemoteTree.this, new RunAt<RemoteTree>(RemoteTree.this) {
     268
     269                                        @Override
     270                                        protected void runAt() {
     271                                                assert isActive();
     272                                                if (argumentType.equals(Object.class)) {
     273                                                        listener.action(Casting.tryCast(argumentType, file));
     274                                                        return;
     275                                                }
     276                                                AccessInterface access = registry.createAccess(argumentType);
     277                                                Object argument = access.createAccessee();
     278                                                access.select(argument);
     279                                                if (!argumentType.isInstance(argument)) {
     280                                                        throw new FramsticksException().msg("created argument is of wrond type").arg("expected", argumentType).arg("created", argument.getClass());
     281                                                }
     282                                                A typedArgument = argumentType.cast(argument);
     283
     284                                                // log.info("executing event with argument " + argumentType);
     285                                                MultiParamLoader loader = new MultiParamLoader();
     286                                                loader.setNewSource(file.getContent());
     287                                                loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
     288                                                loader.addAccessInterface(access);
     289                                                loader.go();
     290
     291                                                listener.action(typedArgument);
     292                                        }
     293                                });
     294                        }
     295                };
     296
     297                proxyListeners.put(listener, proxyListener);
     298
     299                connection.addListener(Path.appendString(path.getTextual(), param.getId()), proxyListener, this, future);
     300        }
     301
     302        public void removeListener(Path path, EventParam param, EventListener<?> listener, Future<Void> future) {
     303                assert isActive();
     304                EventListener<File> proxyListener = proxyListeners.get(listener);
     305                connection.removeListener(proxyListener, this, future);
     306        }
    404307
    405308}
Note: See TracChangeset for help on using the changeset viewer.