Ignore:
Timestamp:
07/12/13 23:41:06 (11 years ago)
Author:
psniegowski
Message:

HIGHLIGHTS:

  • add <include/> to configuration
  • add side notes to tree
    • used to store arbitrary information alongside the tree structure
  • migrate to log4j2
    • supports lazy string evaluation of passed arguments
  • improve GUI tree
    • it stays in synchronization with actual state (even in high load test scenario)
  • improve panel management in GUI
  • make loading objects in GUI more lazy
  • offload parsing to connection receiver thread
    • info parsing
    • first step of objects parsing
  • fix connection parsing bug (eof in long values)
  • support zero-arguments procedure in table view

CHANGELOG:
Implement procedure calls from table view.

Refactorization around procedures in tables.

Add table editor for buttons.

Render buttons in the the list view.

Further improve Columns.

Add Column class for TableModel?.

Accept also non-arguments ProcedureParams? in tableView.

Increase maximal TextAreaControl? size.

Add tooltip to ProcedureControl?.

Fix bug of interpreting eofs in long values by connection reader.

Further rework connection parsing.

Simplify client connection processing.

Test ListChange? modification.

Test ListChange? events with java server.

Add TestChild?.

Fix bug with fast deregistering when connecting to running server.

Another minor refactorization in TreeOperations?.

Fix bug in SimpleAbstractAccess? loading routine.

Another minor improvement.

Minor change.

Make reading of List objects two-phase.

Another minor change.

Dispatch parsing into receiver thread.

Another step.

Enclose passing value in ObjectParam? case in closure.

Minor step.

Minor change on way to offload parsing.

Temporarily comment out single ValueParam? get.

It will be generalized to multi ValueParam?.

Process info in receiver thread.

Add DispatchingExceptionHandler?.

Make waits in browser test longer.

Use FETCHED_MARK.

It is honored in GUI, where it used to decide whether to get values

after user action.

It is set in standard algorithm for processing fetched values.

Add remove operation to side notes.

Make loading more lazy.

Improve loading policy.

On node choose load itself, on node expansion, load children.

Minor improvement.

Fix bug with panel interleaving.

Minor improvements.

Improve panel management.

More cleaning around panels.

Reorganize panels.

Further improve tree.

Fix bug in TreeModel?.

Remove children from TreeNode?.

Implement TreeNode? hashCode and equals.

Make TreeNode? delegate equals and hashcode to internal reference.

Move listeners from TreeNode? to side notes.

Store path.textual as a side note.

Side note params instead of accesses for objects.

More refactorizations.

In TreeNode? bindAccess based on side notes.

Minor step.

Hide createAccess.

Rename AccessInterface? to Access.

Minor changes.

Several improvements in high load scenarios.

Change semantics of ArrayListAccess?.set(index, null);

It now removes the element, making list shorter
(it was set to null before).

Add path remove handler.

Handle exceptions in Connection.

Update .gitignore

Configure logging to file.

Move registration to TreeModel?.

Further refactorization.

Minor refactorization.

Minor improvements.

Use specialized event also for Modify action of ListChange?.

Use remove events.

Use the insertion events for tree.

Further improve tree refreshing.

Further improve reacting on events in GUI.

Fix problem with not adding objects on addition list change.

Migrate to log4j lazy String construction interface.

Migrate imports to log4j2.

Drop dependency on adapter to version 1.2.

Switch log4j implementation to log4j2.

Add dirty mark to the NodeAtFrame?.

Make selecting in AccessInterfaces? type safe.

Ignore containers size settings in Model and Genotype.

Use tree side notes to remember local changes and panels.

Add sideNotes to tree.

They will be used to store various accompanying information
right in the tree.

Use ReferenceIdentityMap? from apache in TreeNode?.

It suits the need perfectly (weak semantics on both key and value).

Make ArrayListParam? do not react size changes.

Guard in TableModel? before not yet loaded objects.

Add <include/> clause and AutoInjector?.

Extract common columns configuration to separate xml,
that can be included by other configurations.

File:
1 edited

Legend:

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

    r99 r100  
    88import javax.annotation.Nonnull;
    99
    10 import org.apache.log4j.Logger;
     10import org.apache.logging.log4j.Logger;
     11import org.apache.logging.log4j.LogManager;
    1112
    1213import com.framsticks.communication.File;
    13 import com.framsticks.params.AccessInterface;
     14import com.framsticks.params.Access;
     15import com.framsticks.params.CompositeParam;
    1416import com.framsticks.params.EventListener;
    1517import com.framsticks.params.FramsClass;
    1618import com.framsticks.params.ListAccess;
    1719import com.framsticks.params.Param;
     20import com.framsticks.params.ParamBuilder;
    1821import com.framsticks.params.PrimitiveParam;
     22import com.framsticks.params.PropertiesAccess;
    1923import com.framsticks.params.UniqueListAccess;
    2024import com.framsticks.params.Util;
     
    2529import com.framsticks.parsers.MultiParamLoader;
    2630import com.framsticks.util.FramsticksException;
     31import com.framsticks.util.dispatching.Dispatching;
    2732import com.framsticks.util.dispatching.Future;
    2833import com.framsticks.util.dispatching.FutureHandler;
     
    3338public final class TreeOperations {
    3439
    35         private static final Logger log = Logger.getLogger(TreeOperations.class);
     40        private static final Logger log = LogManager.getLogger(TreeOperations.class);
    3641
    3742        private TreeOperations() {
    3843        }
    3944
     45        public static final Object FETCHED_MARK = new Object();
     46
    4047        public static @Nonnull FramsClass processFetchedInfo(Tree tree, File file) {
    4148                assert tree.isActive();
    4249                FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
    43                 log.debug("process fetched info for " + tree + ": " + framsClass);
     50                log.debug("process fetched info for {}: {}", tree, framsClass);
    4451                tree.putInfoIntoCache(framsClass);
    4552                return framsClass;
    4653        }
    4754
    48         public static void processFetchedValues(Path path, List<File> files) {
    49                 Tree tree = path.getTree();
    50                 assert tree.isActive();
     55        public static Path create(Path path) {
     56                assert !path.isResolved();
     57
     58                Access access = path.getTree().prepareAccess(path.getTop().getParam());
     59                Object child = createAccessee(path.getTree(), access);
     60                assert child != null;
     61                if (path.size() == 1) {
     62                        path.getTree().assignRootObject(child);
     63                } else {
     64                        Access parentAccess = bindAccess(path.getUnder());
     65
     66                        /** this special case is not very good - maybe hide it in createAccessee? */
     67                        if (parentAccess instanceof UniqueListAccess) {
     68                                access.select(child);
     69                                access.set(((UniqueListAccess) parentAccess).getUidName(), path.getTop().getParam().getId());
     70                        }
     71
     72                        parentAccess.set(path.getTop().getParam(), child);
     73                }
     74                path = path.appendResolution(child);
     75                return path;
     76        }
     77
     78        public static void processFetchedValues(final Path path, final List<File> files, final Access access, final Future<Path> future) {
    5179                assert files.size() == 1;
    5280                assert path.isTheSame(files.get(0).getPath());
    5381
    54                 if (!path.isResolved()) {
    55                         AccessInterface access = tree.prepareAccess(path.getTop().getParam());
    56                         Object child = access.createAccessee();
    57                         assert child != null;
    58                         if (path.size() == 1) {
    59                                 tree.assignRootObject(child);
    60                         } else {
    61                                 bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
    62                         }
    63                         path = path.appendResolution(child);
    64                 }
    65 
    66                 log.debug("process fetched values: " + path);
    67                 Node node = path.getTop();
    68                 MultiParamLoader loader = new MultiParamLoader();
    69                 loader.setNewSource(files.get(0).getContent());
    70                 loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
    7182
    7283                try {
    73                         if (node.getParam() instanceof ObjectParam) {
    74                                 loader.addAccessInterface(bindAccess(node));
    75                                 loader.go();
    76                                 return;
    77                         }
    78 
    79                         ListAccess listAccess = (ListAccess) bindAccess(node);
    80 
    81                         Set<String> oldValuesIds = new HashSet<>();
    82                         for (Param p : listAccess.getParams()) {
    83                                 oldValuesIds.add(p.getId());
    84                         }
    85 
    86                         // listAccess.clearValues();
    87 
    88                         AccessInterface elementAccess = listAccess.getElementAccess();
    89                         AccessInterface clonerInterface = elementAccess.cloneAccess();
    90 
    91                         loader.addAccessInterface(elementAccess);
    92                         MultiParamLoader.Status status;
    93                         int number = 0;
    94                         while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
    95                                 if (status == MultiParamLoader.Status.AfterObject) {
    96                                         AccessInterface accessInterface = loader.getLastAccessInterface();
    97 
    98                                         String id;
    99                                         if (listAccess instanceof UniqueListAccess) {
    100                                                 id = ((UniqueListAccess) listAccess).computeIdentifierFor(accessInterface.getSelected());
    101                                         } else {
    102                                                 id = Integer.toString(number);
    103                                         }
    104                                         ++number;
    105 
    106                                         Object childTo = listAccess.get(id, Object.class);
    107                                         boolean newOne;
    108                                         if (childTo == null) {
    109                                                 childTo = clonerInterface.createAccessee();
    110                                                 newOne = true;
    111                                         } else {
    112                                                 assert oldValuesIds.contains(id);
    113                                                 newOne = false;
    114                                         }
    115                                         oldValuesIds.remove(id);
    116                                         clonerInterface.select(childTo);
    117                                         Util.takeAllNonNullValues(clonerInterface, accessInterface);
    118                                         if (newOne) {
    119                                                 listAccess.set(id, childTo);
    120                                         }
    121 
    122                                         // listAccess.set(id, accessInterface.getSelected());
    123                                         accessInterface.select(null);
    124 
     84                        log.debug("process fetched values: {}", path);
     85                        final Access parsingAccess = new PropertiesAccess(access.getFramsClass());
     86                        final List<Object> results = MultiParamLoader.loadAll(files.get(0).getContent(), parsingAccess);
     87
     88                        Dispatching.dispatchIfNotActive(path.getTree(), new RunAt<Tree>(future) {
     89                                @Override
     90                                protected void runAt() {
     91
     92                                        Path result = path.tryResolveIfNeeded();
     93
     94                                        if (!result.isResolved()) {
     95                                                result = create(result);
     96                                        }
     97
     98                                        if (path.getTop().getParam() instanceof ObjectParam) {
     99                                                assert results.size() == 1;
     100                                                Util.takeAllNonNullValues(bindAccess(result), parsingAccess.select(results.get(0)));
     101                                                mark(result.getTree(), result.getTopObject(), FETCHED_MARK, true);
     102                                                future.pass(result);
     103                                                return;
     104                                        }
     105
     106
     107                                        final ListAccess listAccess = (ListAccess) access;
     108
     109                                        listAccess.select(result.getTopObject());
     110                                        Set<String> oldValuesIds = new HashSet<>();
     111                                        for (Param p : listAccess.getParams()) {
     112                                                oldValuesIds.add(p.getId());
     113                                        }
     114
     115                                        Access targetAccess = listAccess.getElementAccess();//.cloneAccess();
     116
     117                                        int number = 0;
     118                                        for (Object r : results) {
     119
     120                                                parsingAccess.select(r);
     121                                                String id;
     122                                                if (listAccess instanceof UniqueListAccess) {
     123                                                        id = parsingAccess.get(((UniqueListAccess) listAccess).getUidName(), String.class);
     124                                                } else {
     125                                                        id = Integer.toString(number);
     126                                                }
     127                                                ++number;
     128
     129                                                Object childTo = listAccess.get(id, Object.class);
     130                                                boolean newOne;
     131                                                if (childTo == null) {
     132                                                        childTo = createAccessee(result.getTree(), targetAccess);
     133                                                        newOne = true;
     134                                                } else {
     135                                                        assert oldValuesIds.contains(id);
     136                                                        newOne = false;
     137                                                }
     138                                                oldValuesIds.remove(id);
     139
     140                                                targetAccess.select(childTo);
     141                                                Util.takeAllNonNullValues(targetAccess, parsingAccess);
     142                                                if (newOne) {
     143                                                        listAccess.set(id, childTo);
     144                                                }
     145                                                mark(result.getTree(), childTo, FETCHED_MARK, true);
     146
     147                                        }
     148                                        mark(result.getTree(), result.getTopObject(), FETCHED_MARK, true);
     149
     150                                        /** It looks tricky for ArrayListAccess but should also work.
     151                                         *
     152                                         * They should be sorted.
     153                                         */
     154                                        for (String id : oldValuesIds) {
     155                                                listAccess.set(id, null);
     156                                        }
     157                                        future.pass(result);
    125158                                }
    126                         }
    127                         /** It looks tricky for ArrayListAccess but should also work.
    128                          *
    129                          * They should be sorted.
    130                          */
    131                         for (String id : oldValuesIds) {
    132                                 listAccess.set(id, null);
    133                         }
     159                        });
    134160
    135161                } catch (FramsticksException e) {
     
    141167                Tree tree = path.getTree();
    142168                assert tree.isActive();
    143                 log.debug("get info for: " + path);
     169                log.debug("get info for: {}", path);
    144170                final String name = path.getTop().getParam().getContainedTypeName();
    145171                return tree.getInfoFromCache(name);
     
    147173
    148174        public static void findInfo(final Path path, final Future<FramsClass> future) {
    149                 log.debug("find info for: " + path);
     175                log.debug("find info for: {}", path);
    150176                try {
    151177                        Tree tree = path.getTree();
     
    163189
    164190
    165 
    166         public static @Nonnull AccessInterface bindAccess(Tree tree, String path) {
    167                 log.debug("bind access for textual: " + path + " in " + tree);
     191        public static @Nonnull Access bindAccessFromSideNote(Tree tree, Object object) {
     192                CompositeParam param = tree.getSideNote(object, CompositeParam.class, CompositeParam.class);
     193                if (param == null) {
     194                        throw new FramsticksException().msg("failed to bind access from side node").arg("tree", tree).arg("object", object).arg("type", object.getClass());
     195                }
     196                return tree.prepareAccess(param).select(object);
     197        }
     198
     199        public static @Nonnull Access bindAccess(Tree tree, String path) {
     200                log.debug("bind access for textual: {} in {}", path, tree);
    168201                return bindAccess(Path.to(tree, path));
    169202        }
    170203
    171         public static @Nonnull AccessInterface bindAccess(Node node) {
     204        public static @Nonnull Access bindAccess(Node node) {
    172205                Tree tree = node.getTree();
    173206                assert tree.isActive();
     
    175208
    176209                try {
    177                         return tree.prepareAccess(node.getParam()).select(node.getObject());
     210                        Access access = tree.prepareAccess(node.getParam());
     211                        tree.putSideNote(node.getObject(), CompositeParam.class, node.getParam());
     212
     213                        return access.select(node.getObject());
    178214                } catch (FramsticksException e) {
    179215                        throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam()).cause(e);
    180                         // log.error("failed to bind access for " + node.getParam() + ": " + e);
    181                 }
    182         }
    183 
    184         public static @Nonnull AccessInterface bindAccess(Path path) {
     216                        // log.error("failed to bind access for {}: ", node.getParam(), e);
     217                }
     218        }
     219
     220        public static @Nonnull Access bindAccess(Path path) {
    185221                assert path.getTree().isActive();
    186222                path.assureResolved();
    187                 log.debug("bind access for: " + path);
     223                log.debug("bind access for: {}", path);
    188224                return bindAccess(path.getTop());
    189225        }
     
    196232                        protected void runAt() {
    197233                                tree.set(path, param, value, future);
     234                        }
     235                });
     236        }
     237
     238        public static void call(final Path path, final String procedureName, final Object[] arguments, final Future<Object> future) {
     239                final Tree tree = path.getTree();
     240
     241                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
     242                        @Override
     243                        protected void runAt() {
     244                                path.assureResolved();
     245                                tree.call(path, tree.getRegistry().getFramsClass(path.getTop().getParam()).getParamEntry(procedureName, ProcedureParam.class), arguments, future);
    198246                        }
    199247                });
     
    241289         * */
    242290        public static void tryGet(final Tree tree, final String targetPath, final Future<Path> future) {
    243                 log.debug("resolve textual: " + targetPath + " for " + tree);
     291                log.debug("resolve textual: {} for {}", targetPath, tree);
    244292                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
    245293
     
    247295                        protected void runAt() {
    248296                                final Path path = Path.tryTo(tree, targetPath).tryResolveIfNeeded();
    249                                 log.debug("found: " + path);
     297                                log.debug("found: {}", path);
    250298                                if (path.isResolved()) {
    251299                                        future.pass(path);
     
    257305                                        protected void result(Path result) {
    258306                                                // if (result.isResolved(targetPath)) {
    259                                                 //      future.pass(result);
    260                                                 //      return;
     307                                                //      future.pass(result);
     308                                                //      return;
    261309                                                // }
    262                                                 log.debug("retrying resolve textual: " + targetPath + " for " + tree + " with " + result);
     310                                                log.debug("retrying resolve textual: {} for {} with {}", targetPath, tree, result);
    263311                                                tryGet(tree, targetPath, future);
    264312                                        }
     
    273321        }
    274322
     323        public static Object createAccessee(Tree tree, CompositeParam param) {
     324                Object object = tree.prepareAccess(param).createAccessee();
     325                tree.putSideNote(object, CompositeParam.class, param);
     326                return object;
     327        }
     328
     329        public static Object createAccessee(Tree tree, Access access) {
     330                Object object = access.createAccessee();
     331                tree.putSideNote(object, CompositeParam.class, access.buildParam(new ParamBuilder()).finish(CompositeParam.class));
     332                return object;
     333        }
     334
     335        public static boolean isMarked(Tree tree, Object object, Object mark, boolean defValue) {
     336                assert tree.isActive();
     337                Boolean v = tree.getSideNote(object, mark, Boolean.class);
     338                return (v != null ? v : defValue);
     339        }
     340
     341        public static void mark(Tree tree, Object object, Object mark, boolean value) {
     342                assert tree.isActive();
     343                tree.putSideNote(object, mark, value);
     344        }
     345
     346        public static FramsClass getFramsClass(Path path) {
     347                return path.getTree().getRegistry().getFramsClass(path.getTop().getParam());
     348        }
     349
    275350}
Note: See TracChangeset for help on using the changeset viewer.