Changeset 84 for java/main


Ignore:
Timestamp:
06/22/13 21:51:33 (10 years ago)
Author:
psniegowski
Message:

HIGHLIGHTS:

  • simplification of entities management model
  • cleanup around params (improve hierarchy)
  • migrate from JUnit to TestNG
  • introduce FEST to automatically test GUI
  • improve slider control
  • loosen synchronization between gui tree and backend representation
  • and many other bug fixes

NOTICE:

  • a great many of lines is changed only because of substituting spaces with tabs

CHANGELOG (oldest changes at the bottom):

Some cleaning after fix found.

Fix bug with tree.

More changes with TreeNodes?.

Finally fix issue with tree.

Improve gui tree management.

Decouple update of values from fetch request in gui.

Minor changes.

Minor changes.

Minor change.

Change Path construction wording.

More fixes to SliderControl?.

Fix SliderControl?.

Fix SliderControl?.

Minor improvement.

Several changes.

Make NumberParam? a generic class.

Add robot to the gui test.

Setup common testing logging configuration.

Remove Parameters class.

Remove entityOwner from Parameters.

Move name out from Parameters class.

Move configuration to after the construction.

Simplify observers and endpoints.

Remove superfluous configureEntity overrides.

Add dependency on fest-swing-testng.

Use FEST for final print test.

Use FEST for more concise and readable assertions.

Divide test of F0Parser into multiple methods.

Migrate to TestNG

Minor change.

Change convention from LOGGER to log.

Fix reporting of errors during controls filling.

Bound maximal height of SliderControl?.

Minor improvements.

Improve tooltips for controls.

Also use Delimeted in more places.

Move static control utilities to Gui.

Rename package gui.components to controls.

Some cleaning in controls.

Improve Param classes placing.

Move ValueParam?, PrimitiveParam? and CompositeParam? one package up.

Improve ParamBuilder?.

Move getDef to ValueParam? and PrimitiveParam?.

Move getMax and getDef to ValueParam?.

Move getMin to ValueParam?.

Upgrade to laters apache commons versions.

Use filterInstanceof extensively.

Add instanceof filters.

Make ValueParam? in many places of Param.

Place assertions about ValueParam?.

Add ValueParam?

Rename ValueParam? to PrimitiveParam?

Minor changes.

Several improvements to params types.

Add NumberParam?.

Add TextControl? component.

Add .swp files to .gitignore

Greatly improved slider component.

Some improvements.

Make Param.reassign return also a state.

Add IterableIterator?.

Several changes.

  • Move util classes to better packages.
  • Remove warnings from eclim.

Several improvements.

Fix bug with BooleanParam?.

Some experiments with visualization.

Another fix to panel management.

Improve panel management.

Some refactorization around panels.

Add root class for panel.

Location:
java/main
Files:
62 added
22 deleted
110 edited

Legend:

Unmodified
Added
Removed
  • java/main

    • Property svn:ignore set to
      target
  • java/main/pom.xml

    r78 r84  
    11<?xml version="1.0" encoding="UTF-8"?>
    22<project xmlns="http://maven.apache.org/POM/4.0.0"
    3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5     <modelVersion>4.0.0</modelVersion>
     3                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4                xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5        <modelVersion>4.0.0</modelVersion>
    66
    7     <groupId>framsticks</groupId>
    8     <artifactId>framsticks</artifactId>
    9     <version>1.0</version>
     7        <groupId>framsticks</groupId>
     8        <artifactId>framsticks</artifactId>
     9        <version>1.0</version>
    1010
    1111        <repositories>
     
    1818                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    1919        </properties>
    20         <build>
    21                 <plugins>
    22                         <plugin>
    23                                 <groupId>org.apache.maven.plugins</groupId>
    24                                 <artifactId>maven-compiler-plugin</artifactId>
    25                                 <version>3.0</version>
    26                                 <configuration>
    27                                         <source>1.6</source>
    28                                         <target>1.6</target>
    29                                 </configuration>
    30                         </plugin>
    31                 </plugins>
    32         </build>
    33 
    3420        <dependencies>
    3521                <dependency>
     
    4228                        <groupId>commons-configuration</groupId>
    4329                        <artifactId>commons-configuration</artifactId>
    44                         <version>1.7</version>
     30                        <version>1.9</version>
     31                        <scope>compile</scope>
     32                </dependency>
     33                <dependency>
     34                        <groupId>commons-collections</groupId>
     35                        <artifactId>commons-collections</artifactId>
     36                        <version>3.2.1</version>
    4537                        <scope>compile</scope>
    4638                </dependency>
     
    6153                </dependency>
    6254
    63         <dependency>
    64             <groupId>junit</groupId>
    65             <artifactId>junit</artifactId>
    66             <version>4.8.1</version>
    67             <scope>test</scope>
    68         </dependency>
    69                 <!--dependency>
     55                <dependency>
     56                        <groupId>org.testng</groupId>
     57                        <artifactId>testng</artifactId>
     58                        <version>6.1.1</version>
     59                        <scope>test</scope>
    7060                </dependency>
    7161                <dependency>
    72                 </dependency-->
     62                        <groupId>org.easytesting</groupId>
     63                        <artifactId>fest-assert</artifactId>
     64                        <version>1.4</version>
     65                </dependency>
     66                <dependency>
     67                        <groupId>org.easytesting</groupId>
     68                        <artifactId>fest-swing-testng</artifactId>
     69                        <version>1.2.1</version>
     70                </dependency>
     71
     72                <!-- <dependency> -->
     73                <!--    <groupId>junit</groupId> -->
     74                <!--    <artifactId>junit</artifactId> -->
     75                <!--    <version>4.8.1</version> -->
     76                <!--    <scope>test</scope> -->
     77                <!-- </dependency> -->
     78
     79                <!--dependency>
     80                  </dependency>
     81                  <dependency>
     82                  </dependency-->
    7383        </dependencies>
     84        <build>
     85                <plugins>
     86                        <plugin>
     87                                <groupId>org.apache.maven.plugins</groupId>
     88                                <artifactId>maven-compiler-plugin</artifactId>
     89                                <version>3.0</version>
     90                                <configuration>
     91                                        <source>1.6</source>
     92                                        <target>1.6</target>
     93                                </configuration>
     94                        </plugin>
     95
     96                        <plugin>
     97                                <groupId>org.codehaus.mojo</groupId>
     98                                <artifactId>exec-maven-plugin</artifactId>
     99                                <version>1.2.1</version>
     100                                <executions>
     101                                        <execution>
     102                                                <goals>
     103                                                        <goal>exec</goal>
     104                                                </goals>
     105                                        </execution>
     106                                </executions>
     107                                <configuration>
     108                                        <executable>java</executable>
     109                                        <!-- optional -->
     110                                        <workingDirectory>/home/psniegowski/mgr/framsticks</workingDirectory>
     111                                        <arguments>
     112                                                <!-- <argument>-ea</argument> -->
     113                                                <argument>-Xdebug</argument>
     114                                                <argument>-Xrunjdwp:transport=dt_socket,address=4711,server=y,suspend=n</argument>
     115                                                <argument>-classpath</argument>
     116                                                <classpath />
     117                                                <argument>com.framsticks.core.Program</argument>
     118                                        </arguments>
     119                                </configuration>
     120                        </plugin>
     121
     122                </plugins>
     123        </build>
     124
    74125</project>
  • java/main/src/main/java/com/framsticks/communication/ClientConnection.java

    r77 r84  
    88import com.framsticks.params.ListSource;
    99import com.framsticks.util.*;
     10import com.framsticks.util.dispatching.AtOnceDispatcher;
     11import com.framsticks.util.dispatching.Dispatcher;
     12import com.framsticks.util.dispatching.Dispatching;
     13import com.framsticks.util.lang.Pair;
     14import com.framsticks.util.lang.Strings;
    1015import org.apache.log4j.Logger;
    1116
    12 import java.io.BufferedReader;
    1317import java.io.IOException;
    14 import java.io.InputStreamReader;
    15 import java.io.PrintWriter;
    1618import java.net.Socket;
    1719import java.net.SocketException;
     
    2527public class ClientConnection extends Connection {
    2628
    27     private final static Logger LOGGER = Logger.getLogger(ClientConnection.class);
    28 
    29     protected final Map<String, Subscription> subscriptions = new HashMap<String, Subscription>();
    30 
    31     public String getAddress() {
    32         return address;
    33     }
    34 
    35     public void connect(StateFunctor connectedFunctor) {
    36         try {
    37             LOGGER.info("connecting to " + address);
    38 
    39             socket = new Socket(hostName, port);
    40 
    41             socket.setSoTimeout(500);
    42 
    43             LOGGER.info("connected to " + hostName + ":" + port);
    44             connected = true;
    45 
    46             runThreads();
    47 
    48             connectedFunctor.call(null);
    49         } catch (SocketException e) {
    50             LOGGER.error("failed to connect: " + e);
    51             connectedFunctor.call(e);
    52         } catch (IOException e) {
    53             LOGGER.error("buffer creation failure");
    54             connectedFunctor.call(e);
    55             close();
    56         }
    57     }
    58 
    59     private static abstract class InboundMessage {
    60         protected String currentFilePath;
    61         protected List<String> currentFileContent;
    62         protected final List<File> files = new ArrayList<File>();
    63 
    64         public abstract void eof();
    65 
    66         protected void initCurrentFile(String path) {
    67             currentFileContent = new LinkedList<String>();
    68             currentFilePath = path;
    69         }
    70         protected void finishCurrentFile() {
    71             if (currentFileContent == null) {
    72                 return;
    73             }
    74             files.add(new File(currentFilePath, new ListSource(currentFileContent)));
    75             currentFilePath = null;
    76             currentFileContent= null;
    77         }
    78 
    79         public abstract void startFile(String path);
    80 
    81         public void addLine(String line) {
    82             assert line != null;
    83             assert currentFileContent != null;
    84             currentFileContent.add(line.substring(0, line.length() - 1));
    85         }
    86 
    87         public List<File> getFiles() {
    88             return files;
    89         }
    90     }
    91 
    92     private static class EventFire extends InboundMessage {
    93         public final Subscription subscription;
    94 
    95         private EventFire(Subscription subscription) {
    96             this.subscription = subscription;
    97         }
    98 
    99         public void startFile(String path) {
    100             assert path == null;
    101             initCurrentFile(null);
    102         }
    103 
    104         @Override
    105         public void eof() {
    106             finishCurrentFile();
    107             Dispatching.invokeLaterOrNow(subscription.getDispatcher(), new Runnable() {
    108                 @Override
    109                 public void run() {
    110                     subscription.getEventCallback().call(getFiles());
    111                 }
    112             });
    113         }
    114     }
    115 
    116     private static class SentQuery extends InboundMessage {
    117         Request request;
    118         ResponseCallback callback;
    119         Dispatcher dispatcher;
    120 
    121         public void startFile(String path) {
    122             finishCurrentFile();
    123             if (path == null) {
    124                 assert request instanceof ApplicationRequest;
    125                 path = ((ApplicationRequest)request).getPath();
    126             }
    127             initCurrentFile(path);
    128         }
    129 
    130         public void eof() {
    131             finishCurrentFile();
    132             //no-operation
    133         }
    134 
    135         @Override
    136         public String toString() {
    137             return request.toString();
    138         }
    139     }
    140     private Map<Integer, SentQuery> queryMap = new HashMap<Integer, SentQuery>();
    141 
    142 
    143     protected final String address;
    144     protected final String hostName;
    145     protected final int port;
    146 
    147     private static Pattern addressPattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
    148 
    149     public ClientConnection(String address) {
    150         assert address != null;
    151         this.address = address;
    152         Matcher matcher = addressPattern.matcher(address);
    153         if (!matcher.matches()) {
    154             LOGGER.fatal("invalid address: " + address);
    155             hostName = null;
    156             port = 0;
    157             return;
    158         }
    159         hostName = matcher.group(1);
    160         port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
    161     }
    162 
    163     private SentQuery currentlySentQuery;
    164 
    165     public void send(Request request, ResponseCallback callback) {
    166         send(request, AtOnceDispatcher.instance, callback);
    167     }
    168 
    169     public void send(Request request, Dispatcher dispatcher, ResponseCallback callback) {
    170 
    171         if (!isConnected()) {
    172             LOGGER.fatal("not connected");
    173             return;
    174         }
    175         final SentQuery sentQuery = new SentQuery();
    176         sentQuery.request = request;
    177         sentQuery.callback = callback;
    178         sentQuery.dispatcher = dispatcher;
    179 
    180         senderThread.invokeLater(new Runnable(){
    181             @Override
    182             public void run() {
    183                 synchronized (ClientConnection.this) {
    184 
    185                     while (!(requestIdEnabled || currentlySentQuery == null)) {
    186                         try {
    187                             ClientConnection.this.wait();
    188                         } catch (InterruptedException ignored) {
    189                             break;
    190                         }
    191                     }
    192                 }
    193                 Integer id = stashQuery(sentQuery);
    194                 String command = sentQuery.request.getCommand();
    195                 StringBuilder message = new StringBuilder();
    196                 message.append(command);
    197                 if (id != null) {
    198                     message.append(" ").append(id);
    199                 }
    200                 sentQuery.request.construct(message);
    201                 String out = message.toString();
    202 
    203                 output.println(out);
    204                 LOGGER.debug("sending query: " + out);
    205 
    206             }
    207         });
    208         /*
    209         synchronized (this) {
    210             LOGGER.debug("queueing query: " + query);
    211             queryQueue.offer(sentQuery);
    212             notifyAll();
    213         }
    214         */
    215     }
    216 
    217 
    218     @Override
    219     public String toString() {
    220         return address;
    221     }
    222 
    223     public void subscribe(final String path, final SubscriptionCallback callback) {
    224         send(new RegistrationRequest().setPath(path), new ResponseCallback() {
    225             @Override
    226             public void process(Response response) {
    227                 if (!response.getOk()) {
    228                     LOGGER.error("failed to register on event: " + path);
    229                     callback.subscribed(null);
    230                     return;
    231                 }
    232                 assert response.getFiles().isEmpty();
    233                 Subscription subscription = new Subscription(ClientConnection.this, path, response.getComment());
    234                 LOGGER.debug("registered on event: " + subscription);
    235                 synchronized (subscriptions) {
    236                     subscriptions.put(subscription.getRegisteredPath(), subscription);
    237                 }
    238                 subscription.setEventCallback(callback.subscribed(subscription));
    239                 if (subscription.getEventCallback() == null) {
    240                     LOGGER.info("subscription for " + path + " aborted");
    241                     subscription.unsubscribe(new LoggingStateCallback(LOGGER, "abort subscription"));
    242                 }
    243             }
    244         });
    245     }
    246 
    247     public void negotiateProtocolVersion(StateFunctor stateFunctor) {
    248         protocolVersion = -1;
    249         sendQueryVersion(1, stateFunctor);
    250     }
    251 
    252     public void sendQueryVersion(final int version, final StateFunctor stateFunctor) {
    253         send(new VersionRequest().version(version), new StateCallback() {
    254             @Override
    255             public void call(Exception e) {
    256                 if (e != null) {
    257                     LOGGER.fatal("failed to upgrade protocol to version: " + version);
    258                     return;
    259                 }
    260                 protocolVersion = version;
    261                 if (version < 4) {
    262                     /** it is an implicit loop here*/
    263                     sendQueryVersion(version + 1, stateFunctor);
    264                     return;
    265                 }
    266                 send(new UseRequest().feature("request_id"), new StateCallback() {
    267                     @Override
    268                     public void call(Exception e) {
    269                         requestIdEnabled = e == null;
    270                         /*
    271                         synchronized (ClientConnection.this) {
    272                             ClientConnection.this.notifyAll();
    273                         }
    274                         */
    275                         if (!requestIdEnabled) {
    276                             LOGGER.fatal("protocol negotiation failed");
    277                             stateFunctor.call(new Exception("protocol negotiation failed", e));
    278                             return;
    279                         }
    280                         stateFunctor.call(null);
    281                     }
    282                 });
    283 
    284             }
    285         });
    286     }
    287 
    288 
    289     private synchronized SentQuery fetchQuery(Integer id, boolean remove) {
    290         if (id == null) {
    291             if (requestIdEnabled) {
    292                 return null;
    293             }
    294             SentQuery result = currentlySentQuery;
    295             if (remove) {
    296                 currentlySentQuery = null;
    297                 notifyAll();
    298             }
    299             return result;
    300         }
    301         if (queryMap.containsKey(id)) {
    302             SentQuery result = queryMap.get(id);
    303             if (remove) {
    304                 queryMap.remove(id);
    305             }
    306             return result;
    307         }
    308         return null;
    309     }
    310 
    311     private int nextQueryId = 0;
    312 
    313     private Integer stashQuery(SentQuery sentQuery) {
    314         if (!requestIdEnabled) {
    315             currentlySentQuery = sentQuery;
    316             return null;
    317         }
    318         queryMap.put(nextQueryId, sentQuery);
    319         return nextQueryId++;
    320     }
    321 
    322     protected void processMessage(InboundMessage inboundMessage) throws Exception {
    323         if (inboundMessage == null) {
    324             LOGGER.error("failed to use any inbound message");
    325             return;
    326         }
    327 
    328         String line;
    329         while (!(line = getLine()).startsWith("eof")) {
    330             inboundMessage.addLine(line);
    331         }
    332         inboundMessage.eof();
    333     }
    334 
    335     protected void processEvent(String rest) throws Exception {
    336         Matcher matcher = eventPattern.matcher(rest);
    337         if (!matcher.matches()) {
    338             LOGGER.error("invalid event line: " + rest);
    339             return;
    340         }
    341         Subscription subscription = subscriptions.get(matcher.group(1));
    342         if (subscription == null) {
    343             LOGGER.error("non subscribed event: " + matcher.group(1));
    344             return;
    345         }
    346         EventFire event = new EventFire(subscription);
    347         event.startFile(null);
    348         processMessage(event);
    349     }
    350 
    351 
    352     protected void processMessageStartingWith(String line) throws Exception {
    353         Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
    354         if (command.first.equals("event")) {
    355             processEvent(command.second);
    356             return;
    357         }
    358         Pair<Integer, String> rest = parseRest(command.second);
    359 
    360         if (command.first.equals("file")) {
    361             SentQuery sentQuery = fetchQuery(rest.first, false);
    362             sentQuery.startFile(rest.second);
    363             processMessage(sentQuery);
    364             return;
    365         }
    366 
    367         SentQuery sentQuery = fetchQuery(rest.first, true);
    368         if (sentQuery == null) {
    369             return;
    370         }
    371         LOGGER.debug("parsing response for request " + sentQuery);
    372 
    373         final Response response = new Response(command.first.equals("ok"), rest.second, sentQuery.getFiles());
    374         final ResponseCallback callback = sentQuery.callback;
    375 
    376         Dispatching.invokeLaterOrNow(sentQuery.dispatcher, new Runnable() {
    377             @Override
    378             public void run() {
    379                 callback.process(response);
    380             }
    381         });
    382     }
    383 
    384     @Override
    385     protected void receiverThreadRoutine() throws Exception {
    386         while (connected) {
    387             processMessageStartingWith(getLine());
    388         }
    389     }
     29        private final static Logger log = Logger.getLogger(ClientConnection.class);
     30
     31        protected final Map<String, Subscription> subscriptions = new HashMap<String, Subscription>();
     32
     33        public String getAddress() {
     34                return address;
     35        }
     36
     37        public void connect(StateFunctor connectedFunctor) {
     38                try {
     39                        log.info("connecting to " + address);
     40
     41                        socket = new Socket(hostName, port);
     42
     43                        socket.setSoTimeout(500);
     44
     45                        log.info("connected to " + hostName + ":" + port);
     46                        connected = true;
     47
     48                        runThreads();
     49
     50                        connectedFunctor.call(null);
     51                } catch (SocketException e) {
     52                        log.error("failed to connect: " + e);
     53                        connectedFunctor.call(e);
     54                } catch (IOException e) {
     55                        log.error("buffer creation failure");
     56                        connectedFunctor.call(e);
     57                        close();
     58                }
     59        }
     60
     61        private static abstract class InboundMessage {
     62                protected String currentFilePath;
     63                protected List<String> currentFileContent;
     64                protected final List<File> files = new ArrayList<File>();
     65
     66                public abstract void eof();
     67
     68                protected void initCurrentFile(String path) {
     69                        currentFileContent = new LinkedList<String>();
     70                        currentFilePath = path;
     71                }
     72                protected void finishCurrentFile() {
     73                        if (currentFileContent == null) {
     74                                return;
     75                        }
     76                        files.add(new File(currentFilePath, new ListSource(currentFileContent)));
     77                        currentFilePath = null;
     78                        currentFileContent= null;
     79                }
     80
     81                public abstract void startFile(String path);
     82
     83                public void addLine(String line) {
     84                        assert line != null;
     85                        assert currentFileContent != null;
     86                        currentFileContent.add(line.substring(0, line.length() - 1));
     87                }
     88
     89                public List<File> getFiles() {
     90                        return files;
     91                }
     92        }
     93
     94        private static class EventFire extends InboundMessage {
     95                public final Subscription subscription;
     96
     97                private EventFire(Subscription subscription) {
     98                        this.subscription = subscription;
     99                }
     100
     101                public void startFile(String path) {
     102                        assert path == null;
     103                        initCurrentFile(null);
     104                }
     105
     106                @Override
     107                public void eof() {
     108                        finishCurrentFile();
     109                        Dispatching.invokeLaterOrNow(subscription.getDispatcher(), new Runnable() {
     110                                @Override
     111                                public void run() {
     112                                        subscription.getEventCallback().call(getFiles());
     113                                }
     114                        });
     115                }
     116        }
     117
     118        private static class SentQuery extends InboundMessage {
     119                Request request;
     120                ResponseCallback callback;
     121                Dispatcher dispatcher;
     122
     123                public void startFile(String path) {
     124                        finishCurrentFile();
     125                        if (path == null) {
     126                                assert request instanceof ApplicationRequest;
     127                                path = ((ApplicationRequest)request).getPath();
     128                        }
     129                        initCurrentFile(path);
     130                }
     131
     132                public void eof() {
     133                        finishCurrentFile();
     134                        //no-operation
     135                }
     136
     137                @Override
     138                public String toString() {
     139                        return request.toString();
     140                }
     141        }
     142        private Map<Integer, SentQuery> queryMap = new HashMap<Integer, SentQuery>();
     143
     144
     145        protected final String address;
     146        protected final String hostName;
     147        protected final int port;
     148
     149        private static Pattern addressPattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
     150
     151        public ClientConnection(String address) {
     152                assert address != null;
     153                this.address = address;
     154                Matcher matcher = addressPattern.matcher(address);
     155                if (!matcher.matches()) {
     156                        log.fatal("invalid address: " + address);
     157                        hostName = null;
     158                        port = 0;
     159                        return;
     160                }
     161                hostName = matcher.group(1);
     162                port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
     163        }
     164
     165        private SentQuery currentlySentQuery;
     166
     167        public void send(Request request, ResponseCallback callback) {
     168                send(request, AtOnceDispatcher.instance, callback);
     169        }
     170
     171        public void send(Request request, Dispatcher dispatcher, ResponseCallback callback) {
     172
     173                if (!isConnected()) {
     174                        log.fatal("not connected");
     175                        return;
     176                }
     177                final SentQuery sentQuery = new SentQuery();
     178                sentQuery.request = request;
     179                sentQuery.callback = callback;
     180                sentQuery.dispatcher = dispatcher;
     181
     182                senderThread.invokeLater(new Runnable(){
     183                        @Override
     184                        public void run() {
     185                                synchronized (ClientConnection.this) {
     186
     187                                        while (!(requestIdEnabled || currentlySentQuery == null)) {
     188                                                try {
     189                                                        ClientConnection.this.wait();
     190                                                } catch (InterruptedException ignored) {
     191                                                        break;
     192                                                }
     193                                        }
     194                                }
     195                                Integer id = stashQuery(sentQuery);
     196                                String command = sentQuery.request.getCommand();
     197                                StringBuilder message = new StringBuilder();
     198                                message.append(command);
     199                                if (id != null) {
     200                                        message.append(" ").append(id);
     201                                }
     202                                sentQuery.request.construct(message);
     203                                String out = message.toString();
     204
     205                                output.println(out);
     206                                log.debug("sending query: " + out);
     207
     208                        }
     209                });
     210                /*
     211                synchronized (this) {
     212                        log.debug("queueing query: " + query);
     213                        queryQueue.offer(sentQuery);
     214                        notifyAll();
     215                }
     216                */
     217        }
     218
     219
     220        @Override
     221        public String toString() {
     222                return address;
     223        }
     224
     225        public void subscribe(final String path, final SubscriptionCallback callback) {
     226                send(new RegistrationRequest().setPath(path), new ResponseCallback() {
     227                        @Override
     228                        public void process(Response response) {
     229                                if (!response.getOk()) {
     230                                        log.error("failed to register on event: " + path);
     231                                        callback.subscribed(null);
     232                                        return;
     233                                }
     234                                assert response.getFiles().isEmpty();
     235                                Subscription subscription = new Subscription(ClientConnection.this, path, response.getComment());
     236                                log.debug("registered on event: " + subscription);
     237                                synchronized (subscriptions) {
     238                                        subscriptions.put(subscription.getRegisteredPath(), subscription);
     239                                }
     240                                subscription.setEventCallback(callback.subscribed(subscription));
     241                                if (subscription.getEventCallback() == null) {
     242                                        log.info("subscription for " + path + " aborted");
     243                                        subscription.unsubscribe(new LoggingStateCallback(log, "abort subscription"));
     244                                }
     245                        }
     246                });
     247        }
     248
     249        public void negotiateProtocolVersion(StateFunctor stateFunctor) {
     250                protocolVersion = -1;
     251                sendQueryVersion(1, stateFunctor);
     252        }
     253
     254        public void sendQueryVersion(final int version, final StateFunctor stateFunctor) {
     255                send(new VersionRequest().version(version), new StateCallback() {
     256                        @Override
     257                        public void call(Exception e) {
     258                                if (e != null) {
     259                                        log.fatal("failed to upgrade protocol to version: " + version);
     260                                        return;
     261                                }
     262                                protocolVersion = version;
     263                                if (version < 4) {
     264                                        /** it is an implicit loop here*/
     265                                        sendQueryVersion(version + 1, stateFunctor);
     266                                        return;
     267                                }
     268                                send(new UseRequest().feature("request_id"), new StateCallback() {
     269                                        @Override
     270                                        public void call(Exception e) {
     271                                                requestIdEnabled = e == null;
     272                                                /*
     273                                                synchronized (ClientConnection.this) {
     274                                                        ClientConnection.this.notifyAll();
     275                                                }
     276                                                */
     277                                                if (!requestIdEnabled) {
     278                                                        log.fatal("protocol negotiation failed");
     279                                                        stateFunctor.call(new Exception("protocol negotiation failed", e));
     280                                                        return;
     281                                                }
     282                                                stateFunctor.call(null);
     283                                        }
     284                                });
     285
     286                        }
     287                });
     288        }
     289
     290
     291        private synchronized SentQuery fetchQuery(Integer id, boolean remove) {
     292                if (id == null) {
     293                        if (requestIdEnabled) {
     294                                return null;
     295                        }
     296                        SentQuery result = currentlySentQuery;
     297                        if (remove) {
     298                                currentlySentQuery = null;
     299                                notifyAll();
     300                        }
     301                        return result;
     302                }
     303                if (queryMap.containsKey(id)) {
     304                        SentQuery result = queryMap.get(id);
     305                        if (remove) {
     306                                queryMap.remove(id);
     307                        }
     308                        return result;
     309                }
     310                return null;
     311        }
     312
     313        private int nextQueryId = 0;
     314
     315        private Integer stashQuery(SentQuery sentQuery) {
     316                if (!requestIdEnabled) {
     317                        currentlySentQuery = sentQuery;
     318                        return null;
     319                }
     320                queryMap.put(nextQueryId, sentQuery);
     321                return nextQueryId++;
     322        }
     323
     324        protected void processMessage(InboundMessage inboundMessage) throws Exception {
     325                if (inboundMessage == null) {
     326                        log.error("failed to use any inbound message");
     327                        return;
     328                }
     329
     330                String line;
     331                while (!(line = getLine()).startsWith("eof")) {
     332                        // log.debug("line: " + line);
     333                        inboundMessage.addLine(line);
     334                }
     335                inboundMessage.eof();
     336        }
     337
     338        protected void processEvent(String rest) throws Exception {
     339                Matcher matcher = eventPattern.matcher(rest);
     340                if (!matcher.matches()) {
     341                        log.error("invalid event line: " + rest);
     342                        return;
     343                }
     344                Subscription subscription = subscriptions.get(matcher.group(1));
     345                if (subscription == null) {
     346                        log.error("non subscribed event: " + matcher.group(1));
     347                        return;
     348                }
     349                EventFire event = new EventFire(subscription);
     350                event.startFile(null);
     351                processMessage(event);
     352        }
     353
     354
     355        protected void processMessageStartingWith(String line) throws Exception {
     356                Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
     357                if (command.first.equals("event")) {
     358                        processEvent(command.second);
     359                        return;
     360                }
     361                Pair<Integer, String> rest = parseRest(command.second);
     362
     363                if (command.first.equals("file")) {
     364                        SentQuery sentQuery = fetchQuery(rest.first, false);
     365                        sentQuery.startFile(rest.second);
     366                        processMessage(sentQuery);
     367                        return;
     368                }
     369
     370                SentQuery sentQuery = fetchQuery(rest.first, true);
     371                if (sentQuery == null) {
     372                        return;
     373                }
     374                log.debug("parsing response for request " + sentQuery);
     375
     376                final Response response = new Response(command.first.equals("ok"), rest.second, sentQuery.getFiles());
     377                final ResponseCallback callback = sentQuery.callback;
     378
     379                Dispatching.invokeLaterOrNow(sentQuery.dispatcher, new Runnable() {
     380                        @Override
     381                        public void run() {
     382                                callback.process(response);
     383                        }
     384                });
     385        }
     386
     387        @Override
     388        protected void receiverThreadRoutine() throws Exception {
     389                while (connected) {
     390                        processMessageStartingWith(getLine());
     391                }
     392        }
    390393
    391394}
  • java/main/src/main/java/com/framsticks/communication/Connection.java

    r77 r84  
    11package com.framsticks.communication;
    22
    3 import com.framsticks.util.Pair;
     3import com.framsticks.util.lang.Pair;
    44import org.apache.log4j.Logger;
    55import java.io.BufferedReader;
     
    1515public abstract class Connection {
    1616
    17         protected final static Logger LOGGER = Logger.getLogger(Connection.class);
     17        protected final static Logger log = Logger.getLogger(Connection.class);
    1818
    1919        protected PrintWriter output = null;
     
    2828        protected int protocolVersion = -1;
    2929
    30         protected final com.framsticks.util.Thread senderThread = new com.framsticks.util.Thread();
     30        protected final com.framsticks.util.dispatching.Thread senderThread = new com.framsticks.util.dispatching.Thread();
    3131        protected Thread receiverThread;
    3232
     
    4040                        connected = false;
    4141
    42             senderThread.interrupt();
    43             senderThread.join();
     42                        senderThread.interrupt();
     43                        senderThread.join();
    4444                        if (receiverThread != null) {
    4545                                receiverThread.interrupt();
     
    6464                        }
    6565
    66                         LOGGER.info("connection closed");
     66                        log.info("connection closed");
    6767                } catch (Exception e) {
    68                         LOGGER.error(e);
     68                        log.error(e);
    6969                }
    7070
     
    7777
    7878
    79     protected final Pair<Integer, String> parseRest(String rest) {
    80         Matcher matcher = (requestIdEnabled ? requestIdEnabledPattern : requestIDisabledPattern).matcher(rest);
    81         if (!matcher.matches()) {
    82             LOGGER.fatal("unmatched first line of input: " + rest);
    83             return null;
    84         }
    85         return new Pair<Integer, String>(requestIdEnabled ? Integer.parseInt(matcher.group(1)) : null, matcher.group(requestIdEnabled ? 2 : 1));
    86     }
     79        protected final Pair<Integer, String> parseRest(String rest) {
     80                Matcher matcher = (requestIdEnabled ? requestIdEnabledPattern : requestIDisabledPattern).matcher(rest);
     81                if (!matcher.matches()) {
     82                        log.fatal("unmatched first line of input: " + rest);
     83                        return null;
     84                }
     85                return new Pair<Integer, String>(requestIdEnabled ? Integer.parseInt(matcher.group(1)) : null, matcher.group(requestIdEnabled ? 2 : 1));
     86        }
    8787
    88     static final int BUFFER_LENGTH = 1024;
     88        static final int BUFFER_LENGTH = 1024;
    8989
    90     int readChars = 0;
    91     int iterator = 0;
    92     int bufferStart = 0;
    93     char[] readBuffer = new char[BUFFER_LENGTH];
     90        int readChars = 0;
     91        int iterator = 0;
     92        int bufferStart = 0;
     93        char[] readBuffer = new char[BUFFER_LENGTH];
    9494
    95     protected String getLine() throws Exception {
    96         StringBuilder lineBuffer = new StringBuilder();
    97         while (!Thread.interrupted()) {
    98             while (iterator < readChars) {
    99                 if (readBuffer[iterator] != '\n') {
    100                     ++iterator;
    101                     continue;
    102                 }
    103                 lineBuffer.append(readBuffer, bufferStart, iterator - bufferStart + 1);
    104                 ++iterator;
    105                 bufferStart = iterator;
    106                 return lineBuffer.toString();
    107             }
    108             lineBuffer.append(readBuffer, bufferStart, readChars - bufferStart);
     95        protected String getLine() throws Exception {
     96                StringBuilder lineBuffer = new StringBuilder();
     97                while (!Thread.interrupted()) {
     98                        while (iterator < readChars) {
     99                                if (readBuffer[iterator] != '\n') {
     100                                        ++iterator;
     101                                        continue;
     102                                }
     103                                lineBuffer.append(readBuffer, bufferStart, iterator - bufferStart + 1);
     104                                ++iterator;
     105                                bufferStart = iterator;
     106                                return lineBuffer.toString();
     107                        }
     108                        lineBuffer.append(readBuffer, bufferStart, readChars - bufferStart);
    109109
    110             readChars = 0;
    111             while (readChars == 0) {
    112                 try {
    113                     readChars = input.read(readBuffer);
    114                 } catch (SocketTimeoutException ignored) {
    115                     //timeout - continue
    116                 }
    117             }
    118             iterator = 0;
    119             bufferStart = 0;
    120         }
    121         throw new InterruptedException();
    122     }
     110                        readChars = 0;
     111                        while (readChars == 0) {
     112                                try {
     113                                        readChars = input.read(readBuffer);
     114                                } catch (SocketTimeoutException ignored) {
     115                                        //timeout - continue
     116                                }
     117                        }
     118                        iterator = 0;
     119                        bufferStart = 0;
     120                }
     121                throw new InterruptedException();
     122        }
    123123
    124     protected abstract void receiverThreadRoutine() throws Exception;
     124        protected abstract void receiverThreadRoutine() throws Exception;
    125125
    126     protected void runThreads() {
    127         try {
    128             output = new PrintWriter(socket.getOutputStream(), true);
    129             input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    130         } catch (IOException e) {
    131             LOGGER.error("buffer creation failure");
    132             close();
    133             return;
    134         }
     126        protected void runThreads() {
     127                try {
     128                        output = new PrintWriter(socket.getOutputStream(), true);
     129                        input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
     130                } catch (IOException e) {
     131                        log.error("buffer creation failure");
     132                        close();
     133                        return;
     134                }
    135135
    136         senderThread.setName(this + "-sender");
    137         receiverThread = new Thread(new Runnable() {
    138             @Override
    139             public void run() {
    140                 try {
    141                     receiverThreadRoutine();
    142                 } catch (InterruptedException ignored) {
    143                     LOGGER.debug("receiver thread interrupted");
    144                 } catch (Exception e) {
    145                     LOGGER.error("error: " + e);
    146                     close();
    147                 }
    148             }
    149         });
    150         receiverThread.setName(this + "-receiver");
     136                senderThread.setName(this + "-sender");
     137                receiverThread = new Thread(new Runnable() {
     138                        @Override
     139                        public void run() {
     140                                try {
     141                                        receiverThreadRoutine();
     142                                } catch (InterruptedException ignored) {
     143                                        log.debug("receiver thread interrupted");
     144                                } catch (Exception e) {
     145                                        log.error("error: " + e);
     146                                        close();
     147                                }
     148                        }
     149                });
     150                receiverThread.setName(this + "-receiver");
    151151
    152         senderThread.start();
    153         receiverThread.start();
    154     }
     152                senderThread.start();
     153                receiverThread.start();
     154        }
    155155
    156156
  • java/main/src/main/java/com/framsticks/communication/EventCallback.java

    r77 r84  
    11package com.framsticks.communication;
    2 
    3 import com.framsticks.params.SourceInterface;
    42
    53import java.util.List;
  • java/main/src/main/java/com/framsticks/communication/Request.java

    r77 r84  
    22
    33import com.framsticks.communication.queries.*;
    4 
    5 import java.util.Collection;
    6 import java.util.regex.Matcher;
    7 import java.util.regex.Pattern;
    84
    95/**
     
    128public abstract class Request {
    139
    14     public static void quoteValue(StringBuilder builder, String value) {
     10        public static void quoteValue(StringBuilder builder, String value) {
    1511                String quote = ((value.indexOf(' ') > 0) || (value.length() == 0) ? "\"" : "");
    1612                builder.append(quote).append(value).append(quote);
     
    1915        public abstract String getCommand();
    2016
    21     protected abstract StringBuilder construct(StringBuilder buffer);
     17        protected abstract StringBuilder construct(StringBuilder buffer);
    2218        //private static Pattern queryPattern = Pattern.compile("^(\\S+)\\s+(\\S+)(?:\\s+(\\S+))?$");
    2319
     
    3531                        return new CallRequest();
    3632                }
    37         if (type.equals("reg")) {
    38             return new RegistrationRequest();
    39         }
    40         if (type.equals("use")) {
    41             return new UseRequest();
    42         }
    43         if (type.equals("version")) {
    44             return new VersionRequest();
    45         }
    46         return null;
     33                if (type.equals("reg")) {
     34                        return new RegistrationRequest();
     35                }
     36                if (type.equals("use")) {
     37                        return new UseRequest();
     38                }
     39                if (type.equals("version")) {
     40                        return new VersionRequest();
     41                }
     42                return null;
    4743        }
    4844
    49     public abstract void parseRest(String rest);
     45        public abstract void parseRest(String rest);
    5046
    51     @Override
    52     public String toString() {
    53         return construct(new StringBuilder().append(getCommand())).toString();
    54     }
     47        @Override
     48        public String toString() {
     49                return construct(new StringBuilder().append(getCommand())).toString();
     50        }
    5551}
  • java/main/src/main/java/com/framsticks/communication/ResponseCallback.java

    r77 r84  
    11package com.framsticks.communication;
    2 
    3 import com.framsticks.params.SourceInterface;
    4 
    5 import java.util.List;
    62
    73/**
  • java/main/src/main/java/com/framsticks/communication/ServerConnection.java

    r77 r84  
    33import com.framsticks.communication.queries.*;
    44import com.framsticks.params.SourceInterface;
    5 import com.framsticks.util.Pair;
    6 import com.framsticks.util.Strings;
     5import com.framsticks.util.lang.Pair;
     6import com.framsticks.util.lang.Strings;
    77import org.apache.log4j.Logger;
    88
    9 import java.io.BufferedReader;
    10 import java.io.IOException;
    11 import java.io.InputStreamReader;
    12 import java.io.PrintWriter;
    139import java.net.Socket;
    1410
     
    1814public class ServerConnection extends Connection {
    1915
    20     private final static Logger LOGGER = Logger.getLogger(ServerConnection.class);
     16        private final static Logger log = Logger.getLogger(ServerConnection.class);
    2117
    22     RequestHandler requestHandler;
     18        RequestHandler requestHandler;
    2319
    24     public ServerConnection(Socket socket, RequestHandler requestHandler) {
    25         this.socket = socket;
    26         this.requestHandler = requestHandler;
    27         connected = true;
     20        public ServerConnection(Socket socket, RequestHandler requestHandler) {
     21                this.socket = socket;
     22                this.requestHandler = requestHandler;
     23                connected = true;
    2824
    29     }
     25        }
    3026
    31     public void start() {
     27        public void start() {
    3228
    3329
    34         runThreads();
    35     }
     30                runThreads();
     31        }
    3632
    37     @Override
    38     public String toString() {
    39         return socket.getInetAddress().getHostAddress();
    40     }
     33        @Override
     34        public String toString() {
     35                return socket.getInetAddress().getHostAddress();
     36        }
    4137
    42     @Override
    43     protected void receiverThreadRoutine() throws Exception {
    44         while (connected) {
    45             processNextRequest();
    46         }
    47     }
     38        @Override
     39        protected void receiverThreadRoutine() throws Exception {
     40                while (connected) {
     41                        processNextRequest();
     42                }
     43        }
    4844
    49     protected void handleRequest(Request request, ResponseCallback responseCallback) {
    50         if (request instanceof ApplicationRequest) {
    51             requestHandler.handle((ApplicationRequest)request, responseCallback);
    52             return;
    53         }
    54         if (request instanceof ProtocolRequest) {
    55             if (request instanceof VersionRequest) {
    56                 responseCallback.process(new Response(true, null, null));
    57                 return;
    58             }
    59             if (request instanceof UseRequest) {
    60                 String feature = ((UseRequest)request).getFeature();
    61                 if (feature.equals("request_id")) {
    62                     requestIdEnabled = true;
    63                     responseCallback.process(new Response(true, null, null));
    64                     return;
    65                 }
    66                 responseCallback.process(new Response(false, "\"unknown feature: " + feature + "\"", null));
    67                 return;
    68             }
     45        protected void handleRequest(Request request, ResponseCallback responseCallback) {
     46                if (request instanceof ApplicationRequest) {
     47                        requestHandler.handle((ApplicationRequest)request, responseCallback);
     48                        return;
     49                }
     50                if (request instanceof ProtocolRequest) {
     51                        if (request instanceof VersionRequest) {
     52                                responseCallback.process(new Response(true, null, null));
     53                                return;
     54                        }
     55                        if (request instanceof UseRequest) {
     56                                String feature = ((UseRequest)request).getFeature();
     57                                if (feature.equals("request_id")) {
     58                                        requestIdEnabled = true;
     59                                        responseCallback.process(new Response(true, null, null));
     60                                        return;
     61                                }
     62                                responseCallback.process(new Response(false, "\"unknown feature: " + feature + "\"", null));
     63                                return;
     64                        }
    6965
    70         }
    71         LOGGER.error("unhandled request: " + request);
    72         responseCallback.process(new Response(false, "unhandled", null));
    73     }
     66                }
     67                log.error("unhandled request: " + request);
     68                responseCallback.process(new Response(false, "unhandled", null));
     69        }
    7470
    75     protected final void respond(final Response response, final Integer id) {
    76         senderThread.invokeLater(new Runnable() {
    77             @Override
    78             public void run() {
    79                 String outId = id != null ? " " + id : "";
    80                 if (response.getFiles() != null) {
    81                     for (File f : response.getFiles()) {
    82                         output.print("file" + outId/* + " " + f.getPath()*/ + "\n");
    83                         SourceInterface content = f.getContent();
    84                         String line;
    85                         while ((line = content.readLine()) != null) {
    86                             output.print(line);
    87                             output.print('\n');
    88                         }
    89                         output.print("eof\n");
    90                     }
    91                 }
    92                 output.print(response.getOk() ? "ok" : "error");
    93                 output.print(outId);
    94                 if (Strings.notEmpty(response.getComment())) {
    95                     output.print(' ');
    96                     output.print(response.getComment());
    97                 }
    98                 output.print('\n');
    99                 output.flush();
    100             }
    101         });
     71        protected final void respond(final Response response, final Integer id) {
     72                senderThread.invokeLater(new Runnable() {
     73                        @Override
     74                        public void run() {
     75                                String outId = id != null ? " " + id : "";
     76                                if (response.getFiles() != null) {
     77                                        for (File f : response.getFiles()) {
     78                                                output.print("file" + outId/* + " " + f.getPath()*/ + "\n");
     79                                                SourceInterface content = f.getContent();
     80                                                String line;
     81                                                while ((line = content.readLine()) != null) {
     82                                                        output.print(line);
     83                                                        output.print('\n');
     84                                                }
     85                                                output.print("eof\n");
     86                                        }
     87                                }
     88                                output.print(response.getOk() ? "ok" : "error");
     89                                output.print(outId);
     90                                if (Strings.notEmpty(response.getComment())) {
     91                                        output.print(' ');
     92                                        output.print(response.getComment());
     93                                }
     94                                output.print('\n');
     95                                output.flush();
     96                        }
     97                });
    10298
    103     }
     99        }
    104100
    105     protected void processNextRequest() throws Exception {
    106         String line = getLine();
    107         Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
    108         final Pair<Integer, String> rest = parseRest(command.second);
    109         if (rest == null) {
    110             respond(new Response(false, "\"invalid input\"", null), null);
    111             return;
    112         }
     101        protected void processNextRequest() throws Exception {
     102                String line = getLine();
     103                Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
     104                final Pair<Integer, String> rest = parseRest(command.second);
     105                if (rest == null) {
     106                        respond(new Response(false, "\"invalid input\"", null), null);
     107                        return;
     108                }
    113109
    114         final Request request = Request.createRequestByTypeString(command.first);
    115         if (request == null) {
    116             respond(new Response(false, "\"invalid input\"", null), null);
    117             return;
    118         }
    119         request.parseRest(rest.second);
    120         if (LOGGER.isTraceEnabled()) {
    121             LOGGER.trace("read request: " + request);
    122         }
     110                final Request request = Request.createRequestByTypeString(command.first);
     111                if (request == null) {
     112                        respond(new Response(false, "\"invalid input\"", null), null);
     113                        return;
     114                }
     115                request.parseRest(rest.second);
     116                if (log.isTraceEnabled()) {
     117                        log.trace("read request: " + request);
     118                }
    123119
    124         handleRequest(request, new ResponseCallback() {
    125             @Override
    126             public void process(Response response) {
    127                 respond(response, rest.first);
    128             }
    129         });
    130     }
     120                handleRequest(request, new ResponseCallback() {
     121                        @Override
     122                        public void process(Response response) {
     123                                respond(response, rest.first);
     124                        }
     125                });
     126        }
    131127}
  • java/main/src/main/java/com/framsticks/communication/Subscription.java

    r77 r84  
    22
    33import com.framsticks.communication.queries.RegistrationRequest;
    4 import com.framsticks.util.AtOnceDispatcher;
    5 import com.framsticks.util.Dispatcher;
     4import com.framsticks.util.dispatching.AtOnceDispatcher;
     5import com.framsticks.util.dispatching.Dispatcher;
    66import com.framsticks.util.StateFunctor;
    77import org.apache.log4j.Logger;
     
    1313public class Subscription {
    1414
    15     private final static Logger LOGGER = Logger.getLogger(Subscription.class);
     15    private final static Logger log = Logger.getLogger(Subscription.class);
    1616
    1717    private final ClientConnection connection;
     
    5151            public void process(Response response) {
    5252                if (!response.getOk()) {
    53                     LOGGER.error("failed to unsunscribe " + this + ": " + response.getComment());
     53                    log.error("failed to unsunscribe " + this + ": " + response.getComment());
    5454                    stateFunctor.call(new Exception(response.getComment()));
    5555                    return;
    5656                }
    5757                assert response.hasFiles();
    58                 LOGGER.debug("unsunscribed " + this);
     58                log.debug("unsunscribed " + this);
    5959                stateFunctor.call(null);
    6060            }
  • java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java

    r77 r84  
    22
    33import com.framsticks.communication.Request;
     4import com.framsticks.util.lang.Delimeted;
    45
    56import java.util.Collection;
     
    1011public abstract class ApplicationRequest extends Request {
    1112
    12     protected String path;
    13     protected String fields;
     13        protected String path;
     14        protected String fields;
    1415
    15     public ApplicationRequest setPath(String path) {
    16         assert path != null;
    17         this.path = path;
    18         return this;
    19     }
     16        public ApplicationRequest setPath(String path) {
     17                assert path != null;
     18                this.path = path;
     19                return this;
     20        }
    2021
    21     public ApplicationRequest setField(String field) {
    22         this.fields = field;
    23         return this;
    24     }
     22        public ApplicationRequest setField(String field) {
     23                this.fields = field;
     24                return this;
     25        }
    2526
    26     public ApplicationRequest setFields(Collection<String> fields) {
    27         StringBuilder fieldString = new StringBuilder();
    28         boolean notFirst = false;
    29         for (String field : fields) {
    30             if (notFirst) {
    31                 fieldString.append(",");
    32 
    33             } else {
    34                 notFirst = true;
    35             }
    36             fieldString.append(field);
    37         }
    38         return setField(fieldString.toString());
    39     }
     27        public ApplicationRequest setFields(Collection<String> fields) {
     28                Delimeted d = new Delimeted(",", "");
     29                for (String f : fields) {
     30                        d.append(f);
     31                }
     32                return setField(d.build());
     33        }
    4034
    4135
    42     public String getPath() {
    43         return path;
    44     }
     36        public String getPath() {
     37                return path;
     38        }
    4539
    46     @Override
    47     protected StringBuilder construct(StringBuilder buffer) {
    48         buffer.append(' ').append(path);
    49         if (fields != null) {
    50             buffer.append(' ').append(fields);
    51         }
    52         return buffer;
    53     }
     40        @Override
     41        protected StringBuilder construct(StringBuilder buffer) {
     42                buffer.append(' ').append(path);
     43                if (fields != null) {
     44                        buffer.append(' ').append(fields);
     45                }
     46                return buffer;
     47        }
    5448
    55     @Override
    56     public void parseRest(String rest) {
    57         path = rest;
    58     }
     49        @Override
     50        public void parseRest(String rest) {
     51                path = rest;
     52        }
    5953
    6054}
  • java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java

    r77 r84  
    99 */
    1010public class CallRequest extends ApplicationRequest {
     11
    1112        protected String arguments;
    1213        protected String method;
    13 
    1414
    1515        public CallRequest setArguments(String arguments) {
     
    2121                StringBuilder buffer = new StringBuilder();
    2222                for (String a : arguments) {
    23                         String arg = a.trim();
    2423                        buffer.append(" ");
    25                         Request.quoteValue(buffer, arg);
     24                        Request.quoteValue(buffer, a.trim());
    2625                }
    2726                return this.setArguments(buffer.toString());
     
    4241                        buffer.append(arguments);
    4342                }
    44         return buffer;
     43                return buffer;
    4544        }
    4645
  • java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java

    r77 r84  
    11package com.framsticks.communication.queries;
    2 
    3 import com.framsticks.communication.Request;
    42
    53/**
  • java/main/src/main/java/com/framsticks/communication/queries/InfoRequest.java

    r77 r84  
    11package com.framsticks.communication.queries;
    2 
    3 import com.framsticks.communication.Request;
    42
    53/**
  • java/main/src/main/java/com/framsticks/communication/queries/RegistrationRequest.java

    r77 r84  
    11package com.framsticks.communication.queries;
    2 
    3 import com.framsticks.communication.Request;
    42
    53/**
     
    1715        }
    1816
    19     @Override
     17        @Override
    2018        protected StringBuilder construct(StringBuilder buffer) {
    21         super.construct(buffer);
     19                super.construct(buffer);
    2220                if (!register) {
    2321                        buffer.append(" remove");
    2422                }
    25         return buffer;
     23                return buffer;
    2624        }
    2725
  • java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java

    r77 r84  
    11package com.framsticks.communication.queries;
    2 
    3 import com.framsticks.communication.Request;
    42
    53/**
     
    2321                        buffer.append(" \"").append(value).append("\"");
    2422                }
    25         return buffer;
     23                return buffer;
    2624        }
    2725        @Override
  • java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java

    r77 r84  
    11package com.framsticks.communication.queries;
    2 
    3 import com.framsticks.communication.Request;
    42
    53/**
     
    1412        }
    1513
    16     @Override
     14        @Override
    1715        public String getCommand() {
    1816                return "use";
    1917        }
    2018
    21     @Override
     19        @Override
    2220        protected StringBuilder construct(StringBuilder buffer) {
    2321                return buffer.append(' ').append(feature);
    2422        }
    2523
    26     @Override
    27     public void parseRest(String rest) {
    28         feature = rest;
    29     }
     24        @Override
     25        public void parseRest(String rest) {
     26                feature = rest;
     27        }
    3028
    31     public final String getFeature() {
    32         return feature;
    33     }
     29        public final String getFeature() {
     30                return feature;
     31        }
    3432}
  • java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java

    r77 r84  
    11package com.framsticks.communication.queries;
    22
    3 import com.framsticks.communication.Request;
    4 import com.framsticks.util.Numbers;
    5 import com.sun.j3d.loaders.ParsingErrorException;
     3import com.framsticks.util.lang.Numbers;
    64
    75/**
     
    1917        }
    2018
    21     @Override
     19        @Override
    2220        public String getCommand() {
    2321                return "version";
    2422        }
    2523
    26     @Override
    27     public void parseRest(String rest) {
    28         version = Numbers.parse(rest, Integer.class);
    29     }
     24        @Override
     25        public void parseRest(String rest) {
     26                version = Numbers.parse(rest, Integer.class);
     27        }
    3028
    31     @Override
    32     protected StringBuilder construct(StringBuilder buffer) {
     29        @Override
     30        protected StringBuilder construct(StringBuilder buffer) {
    3331                return buffer.append(' ').append(version);
    3432        }
  • java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java

    r77 r84  
    33import com.framsticks.communication.StateCallback;
    44import org.apache.log4j.Logger;
    5 import org.apache.log4j.Priority;
    65
    76/**
  • java/main/src/main/java/com/framsticks/core/Entity.java

    r78 r84  
    11package com.framsticks.core;
    22
    3 import com.framsticks.util.*;
    4 import com.framsticks.util.Thread;
     3import com.framsticks.params.FramsClass;
     4import com.framsticks.util.dispatching.Thread;
     5import com.framsticks.util.dispatching.Dispatcher;
     6
     7import org.apache.commons.configuration.Configuration;
    58import org.apache.log4j.Logger;
    69
     
    811 * @author Piotr Sniegowski
    912 */
    10 public abstract class Entity extends Parameters implements Dispatcher {
     13public abstract class Entity implements Dispatcher {
    1114
    12     private final static Logger LOGGER = Logger.getLogger(Entity.class.getName());
     15        private final static Logger log = Logger.getLogger(Entity.class.getName());
    1316
    14     public Entity(Parameters parameters) {
    15         super(parameters);
    16         if (dispatcher == null) {
    17             dispatcher = new Thread(name);
    18         }
    19     }
     17        protected String name = "entity";
     18        protected EntityOwner owner;
     19        protected Dispatcher dispatcher;
    2020
    21     @Override
    22     public final boolean isActive() {
    23         return dispatcher.isActive();
    24     }
     21        public Entity() {
     22        }
    2523
    26     @Override
    27     public final void invokeLater(Runnable runnable) {
    28         dispatcher.invokeLater(runnable);
    29     }
     24        public final String getName() {
     25                return name;
     26        }
    3027
    31     protected void run() {
    32         assert isActive();
    33         LOGGER.info("running: " + this);
    34     }
     28        /**
     29         * @param name the name to set
     30         */
     31        public final void setName(String name) {
     32                this.name = name;
     33                if (dispatcher instanceof Thread) {
     34                        ((Thread) dispatcher).setName(name);
     35                }
     36        }
    3537
    36     public final void configurePublic() throws Exception {
    37         configure();
    38     }
     38        /**
     39         * @return the owner
     40         */
     41        public EntityOwner getOwner() {
     42                return owner;
     43        }
    3944
    40     protected void configure() throws Exception {
     45        /**
     46         * @param owner the owner to set
     47         */
     48        public void setOwner(EntityOwner owner) {
     49                this.owner = owner;
     50        }
    4151
    42     }
     52        @Override
     53        public final boolean isActive() {
     54                return dispatcher == null || dispatcher.isActive();
     55        }
    4356
    44     public Dispatcher getDispatcher() {
    45         return dispatcher;
    46     }
     57        @Override
     58        public final void invokeLater(Runnable runnable) {
     59                assert dispatcher != null;
     60                dispatcher.invokeLater(runnable);
     61        }
    4762
    48     public final void start() {
    49         invokeLater(new Runnable() {
    50             @Override
    51             public void run() {
    52                 Entity.this.run();
    53             }
    54         });
    55     }
     63        public Dispatcher createDefaultDispatcher() {
     64                return new Thread(name);
     65        }
     66
     67        protected void run() {
     68                assert isActive();
     69                log.info("running: " + this);
     70        }
     71
     72
     73        public void configure(Configuration config) {
     74        }
     75
     76        public Dispatcher getDispatcher() {
     77                return dispatcher;
     78        }
     79
     80        /**
     81         * @param dispatcher the dispatcher to set
     82         */
     83        public void setDispatcher(Dispatcher dispatcher) {
     84                this.dispatcher = dispatcher;
     85        }
     86
     87        public final void start() {
     88                if (dispatcher == null) {
     89                        log.debug("no dispatcher set for " + this + ", creating default one");
     90                        setDispatcher(createDefaultDispatcher());
     91                }
     92                invokeLater(new Runnable() {
     93                        @Override
     94                        public void run() {
     95                                Entity.this.run();
     96                        }
     97                });
     98        }
    5699
    57100        public final void done() {
    58                 LOGGER.info("stopping entity");
     101                log.info("stopping entity");
    59102                if (owner != null) {
    60103                        owner.onDone();
     
    62105        }
    63106
    64 
     107        public static void constructFramsClass(FramsClass.Constructor constructor) {
     108                constructor.method("getName");
     109        }
    65110}
  • java/main/src/main/java/com/framsticks/core/Instance.java

    r78 r84  
    33import com.framsticks.communication.*;
    44import com.framsticks.params.*;
    5 import com.framsticks.params.types.CompositeParam;
    65import com.framsticks.params.types.ObjectParam;
    76import com.framsticks.parsers.Loaders;
     
    98import com.framsticks.util.*;
    109import com.framsticks.util.UnsupportedOperationException;
     10import com.framsticks.util.dispatching.Dispatching;
     11import com.framsticks.util.dispatching.Future;
     12import com.framsticks.util.lang.Casting;
    1113import org.apache.log4j.Logger;
    1214
     
    1820public abstract class Instance extends Entity {
    1921
    20         private static final Logger LOGGER = Logger.getLogger(Instance.class.getName());
    21 
    22 
    23     protected Node root;
    24 
    25     public Set<InstanceListener> listeners = new HashSet<InstanceListener>();
    26 
    27     public Instance(Parameters parameters) {
    28         super(parameters);
    29         root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o").build(), null);
    30         }
    31 
    32     @Override
    33     protected void run() {
    34         super.run();
     22        private static final Logger log = Logger.getLogger(Instance.class.getName());
     23
     24
     25        protected Node root;
     26
     27        public Set<InstanceListener> listeners = new HashSet<InstanceListener>();
     28
     29        public Instance() {
     30        }
     31
     32        @Override
     33        protected void run() {
     34                super.run();
     35                root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o").build(), null);
    3536                com.framsticks.model.Package.register(registry);
    36     }
    37 
    38     @Override
    39     protected void configure() throws Exception {
    40         super.configure();
    41     }
    42 
    43     protected void fetchInfo(Path path, Future<FramsClass> future) {
     37        }
     38
     39        protected void fetchInfo(Path path, Future<FramsClass> future) {
    4440                future.result(null, new UnsupportedOperationException());
    4541        }
     
    6157        }
    6258
    63     public void fetchValue(Path path, Param param, StateFunctor stateFunctor) {
     59        public void fetchValue(Path path, Param param, StateFunctor stateFunctor) {
    6460                stateFunctor.call(null);
    6561        }
    6662
    67     public void fetchValues(Path path, StateFunctor stateFunctor) {
     63        public void fetchValues(Path path, StateFunctor stateFunctor) {
    6864                stateFunctor.call(null);
    6965        }
    7066
    71     protected void tryRegisterOnChangeEvents(Path path) {
     67        protected void tryRegisterOnChangeEvents(Path path) {
    7268
    7369        }
     
    8379        }
    8480
    85     protected void fireRun(Exception e) {
    86         for (InstanceListener l : this.listeners) {
    87             l.onRun(e);
    88         }
    89     }
    90 
    91     protected void fireStop(Exception e) {
    92         for (InstanceListener l : this.listeners) {
    93             l.onStop(e);
    94         }
    95     }
    96 
    97     public void addListener(final InstanceListener listener) {
    98         assert Dispatching.isThreadSafe();
    99         Dispatching.invokeLaterOrNow(this, new Runnable() {
    100             @Override
    101             public void run() {
    102                 listeners.add(listener);
    103             }
    104         });
    105     }
    106 
    107     public void removeListener(final InstanceListener listener) {
    108         assert Dispatching.isThreadSafe();
    109         Dispatching.invokeLaterOrNow(this, new Runnable() {
    110             @Override
    111             public void run() {
    112                 listeners.remove(listener);
    113             }
    114         });
    115     }
    116 
    117 
    118     protected void fireListChange(Path path, ListChange change) {
    119         assert isActive();
    120         for (InstanceListener l : this.listeners) {
     81        protected void fireRun(Exception e) {
     82                for (InstanceListener l : this.listeners) {
     83                        l.onRun(e);
     84                }
     85        }
     86
     87        protected void fireStop(Exception e) {
     88                for (InstanceListener l : this.listeners) {
     89                        l.onStop(e);
     90                }
     91        }
     92
     93        public void addListener(final InstanceListener listener) {
     94                assert Dispatching.isThreadSafe();
     95                Dispatching.invokeLaterOrNow(this, new Runnable() {
     96                        @Override
     97                        public void run() {
     98                                listeners.add(listener);
     99                        }
     100                });
     101        }
     102
     103        public void removeListener(final InstanceListener listener) {
     104                assert Dispatching.isThreadSafe();
     105                Dispatching.invokeLaterOrNow(this, new Runnable() {
     106                        @Override
     107                        public void run() {
     108                                listeners.remove(listener);
     109                        }
     110                });
     111        }
     112
     113
     114        protected void fireListChange(Path path, ListChange change) {
     115                assert isActive();
     116                for (InstanceListener l : this.listeners) {
    121117                        l.onListChange(path, change);
    122118                }
    123119        }
    124120
    125 
    126     public final FramsClass getInfoFromCache(Path path) {
    127         return getInfoFromCache(path.getTop().getParam().getContainedTypeName());
    128     }
    129 
    130 
    131     public FramsClass getInfoFromCache(String id) {
    132         assert isActive();
     121        protected void fireFetch(Path path) {
     122                assert isActive();
     123                for (InstanceListener l : this.listeners) {
     124                        l.onFetch(path);
     125                }
     126        }
     127
     128
     129        public final FramsClass getInfoFromCache(Path path) {
     130                return getInfoFromCache(path.getTop().getParam().getContainedTypeName());
     131        }
     132
     133
     134        public FramsClass getInfoFromCache(String id) {
     135                assert isActive();
    133136                return registry.getInfoFromCache(id);
    134137        }
     
    137140
    138141        public AccessInterface createAccess(String name) {
    139         assert isActive();
    140         if (name == null) {
     142                assert isActive();
     143                return registry.createAccess(name);
     144        }
     145
     146
     147        // TODO: make ValueParam
     148        public <T> T get(Node node, Param childParam, Class<T> type) {
     149                return bindAccess(node).get((ValueParam) childParam, type);
     150        }
     151
     152        public void findInfo(final Path path, final Future<FramsClass> future) {
     153                assert isActive();
     154                final String name = path.getTop().getParam().getContainedTypeName();
     155                final FramsClass framsClass = getInfoFromCache(name);
     156                if (framsClass != null) {
     157                        log.trace("info for " + name + " found in cache");
     158                        future.result(framsClass, null);
     159                        return;
     160                }
     161                fetchInfo(path, future);
     162        }
     163
     164        public final AccessInterface bindAccess(Node node) {
     165                assert node.getObject() != null;
     166                AccessInterface access = registry.prepareAccess(node.getParam());
     167                if (access == null) {
     168                        log.error("missing access for: " + node.getParam());
    141169                        return null;
    142170                }
    143                 FramsClass framsClass = getInfoFromCache(name);
    144                 if (framsClass == null) {
    145                         return null;
    146                 }
    147 
    148                 return registry.createAccess(name, framsClass);
    149         }
    150 
    151         public static AccessInterface wrapAccessWithListIfNeeded(CompositeParam param, AccessInterface access) {
    152         if (access == null) {
    153                         return null;
    154                 }
    155         return param.prepareAccessInterface(access);
    156         }
    157 
    158     public AccessInterface prepareAccess(CompositeParam param) {
    159         return wrapAccessWithListIfNeeded(param, createAccess(param.getContainedTypeName()));
    160     }
    161 
    162     public <T> T get(Node node, Param childParam, Class<T> type) {
    163         return bindAccess(node).get(childParam, type);
    164     }
    165 
    166     public void findInfo(final Path path, final Future<FramsClass> future) {
    167         assert isActive();
    168         final String name = path.getTop().getParam().getContainedTypeName();
    169         final FramsClass framsClass = getInfoFromCache(name);
    170         if (framsClass != null) {
    171             LOGGER.trace("info for " + name + " found in cache");
    172             future.result(framsClass, null);
    173             return;
    174         }
    175         fetchInfo(path, future);
    176     }
    177 
    178     public final AccessInterface bindAccess(Node node) {
    179         assert node.getObject() != null;
    180         AccessInterface access = prepareAccess(node.getParam());
    181         if (access == null) {
    182                         LOGGER.error("missing access for: " + node.getParam());
    183             return null;
    184         }
    185         access.select(node.getObject());
    186         return access;
    187     }
    188 
    189     public final <T> T getParam(Path path, String id, Class<T> type) {
    190         return Casting.tryCast(type, prepareAccess(path.getTop().getParam()).getParam(id));
    191     }
    192 
    193     public final AccessInterface bindAccess(Path path) {
    194         assert path.isResolved();
    195         return bindAccess(path.getTop());
    196     }
    197 
    198     public void resolve(final String targetPath, final Future<Path> future) {
    199         assert isActive();
    200         final Path path = new Path(this, targetPath);
    201         resolve(path, new Future<Path>() {
    202             @Override
    203             public void result(Path result, Exception e) {
    204                 assert isActive();
    205                 if (e != null) {
    206                     future.result(path, e);
    207                     return;
    208                 }
    209                 if (path.isResolved(targetPath)) {
    210                     future.result(path, null);
    211                     return;
    212                 }
    213                 if (path.isResolved()) {
    214                     future.result(path, new Exception("testing"));
    215                     return;
    216                 }
    217                 resolve(targetPath, future);
    218             }
    219         });
    220     }
    221 
    222     public void resolveAndFetch(final String targetPath, final Future<Path> future) {
    223         assert isActive();
    224         resolve(targetPath, new Future<Path>() {
    225             @Override
    226             public void result(final Path path, Exception e) {
    227                 if (e != null) {
    228                     future.result(path, e);
    229                     return;
    230                 }
    231                 assert path.isResolved(targetPath);
    232                 fetchValues(path, new StateFunctor() {
    233                     @Override
    234                     public void call(Exception e) {
    235                         future.result(path, e);
    236                     }
    237                 });
    238             }
    239         });
    240     }
    241 
    242     public Path createIfNeeded(String path) {
    243         Path p;
    244         while (!(p = new Path(this, path)).isResolved(path)) {
    245             create(p);
    246         }
    247         return p;
    248     }
    249 
    250     public Path create(Path path) {
    251         assert isActive();
    252         assert !path.isResolved();
    253         Path resolved = path.findResolution();
    254         if (!resolved.isResolved()) {
    255             LOGGER.debug("creating: " + path);
    256             AccessInterface access = prepareAccess(path.getTop().getParam());
    257             assert access != null;
    258             Object child = access.createAccessee();
    259             assert child != null;
    260             if (path.size() == 1) {
    261                 root = new Node(root.getParam(), child);
    262             } else {
    263                 bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
    264             }
    265             resolved = path.appendResolution(child);
    266         }
    267         tryRegisterOnChangeEvents(resolved);
    268         return resolved;
    269     }
    270 
    271 
    272 
    273 
    274     public FramsClass processFetchedInfo(File file) {
    275         assert isActive();
    276         FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
    277         if ("/".equals(file.getPath())) {
    278             if (root.getParam().getContainedTypeName() == null) {
    279                 root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o " + framsClass.getId()).build(), root.getObject());
    280             }
    281         }
    282         registry.putInfoIntoCache(framsClass);
    283         return framsClass;
    284     }
    285 
    286     public void processFetchedValues(Path path, List<File> files) {
    287         assert isActive();
    288         assert files.size() == 1;
    289         assert path.isTheSame(files.get(0).getPath());
    290         Node node = path.getTop();
    291         MultiParamLoader loader = new MultiParamLoader();
    292         loader.setNewSource(files.get(0).getContent());
    293         loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
    294 
    295         try {
    296             if (node.getParam() instanceof ObjectParam) {
    297                 loader.addAccessInterface(bindAccess(node));
    298                 loader.go();
    299     //            for (NodeListener l : listeners) {
    300     //                l.onChange(this);
    301     //            }
    302                 return;
    303             }
    304 
    305             ListAccess listAccess = ((ListAccess)bindAccess(node));
    306             assert listAccess != null;
    307             listAccess.clearValues();
    308 
    309             AccessInterface elementAccess = listAccess.getElementAccess();
    310             loader.addAccessInterface(elementAccess);
    311             MultiParamLoader.Status status;
    312             while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
    313                 if (status == MultiParamLoader.Status.AfterObject) {
    314                     AccessInterface accessInterface = loader.getLastAccessInterface();
    315 
    316                     String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
    317                     Param param = new ParamBuilder().setType("o " + accessInterface.getId()).setId(id).build();
    318                     Object child = accessInterface.getSelected();
    319                     accessInterface.select(null);
    320                     assert child != null;
    321                     bindAccess(node).set(param, child);
    322                 }
    323             }
    324     //        for (NodeListener l : listeners) {
    325     //            l.onChange(this);
    326     //        }
    327         } catch (Exception e) {
    328             LOGGER.error("exception occurred while loading: " + e);
    329         }
    330 
    331     }
    332 
    333     public static Iterator<String> splitPath(String path) {
    334         List<String> list = new LinkedList<String>();
    335         for (String s : path.split("/")) {
    336             if (!s.isEmpty()) {
    337                 list.add(s);
    338             }
    339         }
    340         return list.iterator();
    341     }
     171                access.select(node.getObject());
     172                return access;
     173        }
     174
     175        public final <T> T getParam(Path path, String id, Class<T> type) {
     176                return Casting.tryCast(type, registry.prepareAccess(path.getTop().getParam()).getParam(id));
     177        }
     178
     179        public final AccessInterface bindAccess(Path path) {
     180                assert path.isResolved();
     181                return bindAccess(path.getTop());
     182        }
     183
     184        public void resolve(final String targetPath, final Future<Path> future) {
     185                assert isActive();
     186                final Path path = getPath(targetPath);
     187                resolve(path, new Future<Path>() {
     188                        @Override
     189                        public void result(Path result, Exception e) {
     190                                assert isActive();
     191                                if (e != null) {
     192                                        future.result(path, e);
     193                                        return;
     194                                }
     195                                if (path.isResolved(targetPath)) {
     196                                        future.result(path, null);
     197                                        return;
     198                                }
     199                                if (path.isResolved()) {
     200                                        future.result(path, new Exception("testing"));
     201                                        return;
     202                                }
     203                                resolve(targetPath, future);
     204                        }
     205                });
     206        }
     207
     208        public void resolveAndFetch(final String targetPath, final Future<Path> future) {
     209                assert isActive();
     210                resolve(targetPath, new Future<Path>() {
     211                        @Override
     212                        public void result(final Path path, Exception e) {
     213                                if (e != null) {
     214                                        future.result(path, e);
     215                                        return;
     216                                }
     217                                assert path.isResolved(targetPath);
     218                                fetchValues(path, new StateFunctor() {
     219                                        @Override
     220                                        public void call(Exception e) {
     221                                                future.result(path, e);
     222                                        }
     223                                });
     224                        }
     225                });
     226        }
     227
     228        public Path createIfNeeded(String path) {
     229                Path p;
     230                while (!(p = getPath(path)).isResolved(path)) {
     231                        create(p);
     232                }
     233                return p;
     234        }
     235
     236        public Path createIfNeeded(Path path) {
     237                assert isActive();
     238                if (path.isResolved()) {
     239                        return path;
     240                }
     241                return create(path);
     242        }
     243
     244        public Path create(Path path) {
     245                assert isActive();
     246                assert !path.isResolved();
     247                Path resolved = path.tryFindResolution();
     248                if (!resolved.isResolved()) {
     249                        log.debug("creating: " + path);
     250                        AccessInterface access = registry.prepareAccess(path.getTop().getParam());
     251                        assert access != null;
     252                        Object child = access.createAccessee();
     253                        assert child != null;
     254                        if (path.size() == 1) {
     255                                root = new Node(root.getParam(), child);
     256                        } else {
     257                                bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
     258                        }
     259                        resolved = path.appendResolution(child);
     260                }
     261                tryRegisterOnChangeEvents(resolved);
     262                return resolved;
     263        }
     264
     265
     266
     267
     268        public FramsClass processFetchedInfo(File file) {
     269                assert isActive();
     270                FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
     271                if ("/".equals(file.getPath())) {
     272                        if (root.getParam().getContainedTypeName() == null) {
     273                                root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o " + framsClass.getId()).build(), root.getObject());
     274                        }
     275                }
     276                registry.putInfoIntoCache(framsClass);
     277                return framsClass;
     278        }
     279
     280        public void processFetchedValues(Path path, List<File> files) {
     281                assert isActive();
     282                assert files.size() == 1;
     283                assert path.isTheSame(files.get(0).getPath());
     284                Node node = path.getTop();
     285                MultiParamLoader loader = new MultiParamLoader();
     286                loader.setNewSource(files.get(0).getContent());
     287                loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
     288
     289                try {
     290                        if (node.getParam() instanceof ObjectParam) {
     291                                loader.addAccessInterface(bindAccess(node));
     292                                loader.go();
     293                                fireFetch(path);
     294        //            for (NodeListener l : listeners) {
     295        //                l.onChange(this);
     296        //            }
     297                                return;
     298                        }
     299
     300                        ListAccess listAccess = ((ListAccess)bindAccess(node));
     301                        assert listAccess != null;
     302                        listAccess.clearValues();
     303
     304                        AccessInterface elementAccess = listAccess.getElementAccess();
     305                        loader.addAccessInterface(elementAccess);
     306                        MultiParamLoader.Status status;
     307                        while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
     308                                if (status == MultiParamLoader.Status.AfterObject) {
     309                                        AccessInterface accessInterface = loader.getLastAccessInterface();
     310
     311                                        String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
     312                                        Param param = new ParamBuilder().setType("o " + accessInterface.getId()).setId(id).build();
     313                                        Object child = accessInterface.getSelected();
     314                                        accessInterface.select(null);
     315                                        assert child != null;
     316                                        bindAccess(node).set((ValueParam) param, child);
     317                                }
     318                        }
     319
     320                        fireFetch(path);
     321        //        for (NodeListener l : listeners) {
     322        //            l.onChange(this);
     323        //        }
     324                } catch (Exception e) {
     325                        log.error("exception occurred while loading: " + e);
     326                }
     327
     328        }
     329
     330        public static Iterator<String> splitPath(String path) {
     331                List<String> list = new LinkedList<String>();
     332                for (String s : path.split("/")) {
     333                        if (!s.isEmpty()) {
     334                                list.add(s);
     335                        }
     336                }
     337                return list.iterator();
     338        }
    342339
    343340        public Registry getRegistry() {
    344341                return registry;
    345342        }
     343
     344        public Path getPath(String textual) {
     345                return new Path(this, textual);
     346        }
     347
     348        public Path getRootPath() {
     349                return getPath("/");
     350        }
    346351}
    347352
  • java/main/src/main/java/com/framsticks/core/InstanceListener.java

    r77 r84  
    55 */
    66public interface InstanceListener {
    7     public void onListChange(Path path, ListChange change);
    8     public void onRun(Exception e);
    9     public void onStop(Exception e);
     7        public void onListChange(Path path, ListChange change);
     8        public void onFetch(Path path);
     9        public void onRun(Exception e);
     10        public void onStop(Exception e);
    1011}
  • java/main/src/main/java/com/framsticks/core/ListChange.java

    r77 r84  
    22
    33import com.framsticks.params.FramsClass;
    4 import com.framsticks.params.ListSource;
    54import com.framsticks.params.ParamBuilder;
    65import com.framsticks.params.types.DecimalParam;
    76import com.framsticks.params.types.EnumParam;
    87import com.framsticks.params.types.StringParam;
    9 import com.framsticks.util.Strings;
     8import com.framsticks.util.lang.Strings;
    109
    11 import java.util.ArrayList;
    1210import java.util.Arrays;
    1311
     
    1715public class ListChange {
    1816
    19     public Action getAction() {
    20         return action;
    21     }
     17        public Action getAction() {
     18                return action;
     19        }
    2220
    23     public Integer getPosition() {
    24         return position;
    25     }
     21        public Integer getPosition() {
     22                return position;
     23        }
    2624
    27     public String getIdentifier() {
    28         return identifier;
    29     }
     25        public String getIdentifier() {
     26                return identifier;
     27        }
    3028
    31     public static enum Action {
    32         Add,
    33         Remove,
    34         Modify
    35     }
     29        public static enum Action {
     30                Add,
     31                Remove,
     32                Modify
     33        }
    3634
    37     private Action action;
    38     private Integer position;
    39     private String identifier;
     35        private Action action;
     36        private Integer position;
     37        private String identifier;
    4038
    41     public Integer getType() { return action.ordinal(); }
    42     public void setType(Integer type) { action = Action.values()[type]; }
     39        public Integer getType() { return action.ordinal(); }
     40        public void setType(Integer type) { action = Action.values()[type]; }
    4341
    4442        public Integer getPos() { return position; }
     
    4846        public void setId(String id) { identifier = id; }
    4947
    50     public String getBestIdentifier() {
    51         if (Strings.notEmpty(identifier)) {
    52             return identifier;
    53         }
    54         return position.toString();
    55     }
     48        public String getBestIdentifier() {
     49                if (Strings.notEmpty(identifier)) {
     50                        return identifier;
     51                }
     52                return position.toString();
     53        }
    5654
    57     public static FramsClass getFramsClass() {
     55        public static FramsClass getFramsClass() {
     56                return new FramsClass("ListChange", "ListChange", null)
     57                                .append(new ParamBuilder().setId("type").setName("type").setType(new EnumParam(Arrays.asList("Add", "Remove", "Modify"))).build())
     58                                .append(new ParamBuilder().setId("id").setName("identifier").setType(StringParam.class).build())
     59                                .append(new ParamBuilder().setId("pos").setName("position").setType(DecimalParam.class).build());
     60        }
    5861
    59         ArrayList<String> actions = new ArrayList<String>();
    60         actions.add("Add");
    61         actions.add("Remove");
    62         actions.add("Modify");
    63         return new FramsClass("ListChange", "ListChange", null)
    64                 .append(new ParamBuilder().setId("type").setName("type").setType(new EnumParam(actions)).build())
    65                 .append(new ParamBuilder().setId("id").setName("identifier").setType(StringParam.class).build())
    66                 .append(new ParamBuilder().setId("pos").setName("position").setType(DecimalParam.class).build());
    67     }
    68 
    69     @Override
    70     public String toString() {
    71         return action + " " + identifier + " " + position;
    72     }
     62        @Override
     63        public String toString() {
     64                return action + " " + identifier + " " + position;
     65        }
    7366}
  • java/main/src/main/java/com/framsticks/core/LocalInstance.java

    r78 r84  
    22
    33import com.framsticks.hosting.InstanceClient;
    4 import com.framsticks.params.AccessInterface;
    5 import com.framsticks.params.Param;
    6 import com.framsticks.util.*;
    7 import com.framsticks.util.Thread;
     4import com.framsticks.util.dispatching.Thread;
     5
     6import org.apache.commons.configuration.Configuration;
    87import org.apache.log4j.Logger;
    98
     
    2120public abstract class LocalInstance extends Instance {
    2221
    23     private static final Logger LOGGER = Logger.getLogger(LocalInstance.class.getName());
     22        private static final Logger log = Logger.getLogger(LocalInstance.class.getName());
    2423
    25     public LocalInstance(Parameters parameters) {
    26         super(parameters);
     24        public LocalInstance() {
    2725
    28         Integer accept = config.getInteger("accept", null);
    29         if (accept != null) {
    30             try {
    31                 acceptSocket = new ServerSocket();
    32                 acceptSocket.setReuseAddress(true);
    33                 acceptThread = new Thread(name + "-accept");
    34                 tryBind(accept);
    35             } catch (IOException e) {
    36                 LOGGER.fatal("failed to create accept socket: " + e);
    37             }
    38         }
    39     }
     26        }
    4027
    41     @Override
    42     protected void run() {
    43         super.run();
    44     }
     28        @Override
     29        public void configure(Configuration config) {
     30                Integer accept = config.getInteger("accept", null);
     31                if (accept != null) {
     32                        try {
     33                                acceptSocket = new ServerSocket();
     34                                acceptSocket.setReuseAddress(true);
     35                                acceptThread = new Thread(name + "-accept");
     36                                tryBind(accept);
     37                        } catch (IOException e) {
     38                                log.fatal("failed to create accept socket: " + e);
     39                        }
     40                }
     41        }
    4542
    46     @Override
    47     protected void configure() throws Exception {
    48         super.configure();
    49     }
     43        protected final Set<InstanceClient> clients = new HashSet<InstanceClient>();
     44        ServerSocket acceptSocket;
     45        Thread acceptThread;
    5046
    51     protected final Set<InstanceClient> clients = new HashSet<InstanceClient>();
    52     ServerSocket acceptSocket;
    53     Thread acceptThread;
     47        protected void acceptNext() {
     48                acceptThread.invokeLater(new Runnable() {
     49                        @Override
     50                        public void run() {
     51                                try {
     52                                        final Socket socket = acceptSocket.accept();
     53                                        assert socket != null;
     54                                        log.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
     55                                        invokeLater(new Runnable() {
     56                                                @Override
     57                                                public void run() {
     58                                                        InstanceClient client = new InstanceClient(LocalInstance.this, socket);
     59                                                        clients.add(client);
     60                                                        log.info("client connected: " + client);
     61                                                }
     62                                        });
     63                                } catch (IOException e) {
     64                                        log.error("failed to accept socket: " + e);
     65                                }
     66                                acceptNext();
     67                        }
     68                });
     69        }
    5470
    55     protected void acceptNext() {
    56         acceptThread.invokeLater(new Runnable() {
    57             @Override
    58             public void run() {
    59                 try {
    60                     final Socket socket = acceptSocket.accept();
    61                     assert socket != null;
    62                     LOGGER.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
    63                     invokeLater(new Runnable() {
    64                         @Override
    65                         public void run() {
    66                             InstanceClient client = new InstanceClient(LocalInstance.this, socket);
    67                             clients.add(client);
    68                             LOGGER.info("client connected: " + client);
    69                         }
    70                     });
    71                 } catch (IOException e) {
    72                     LOGGER.error("failed to accept socket: " + e);
    73                 }
    74                 acceptNext();
    75             }
    76         });
    77     }
    78 
    79     public void tryBind(final Integer accept) {
    80         acceptThread.invokeLater(new Runnable() {
    81             @Override
    82             public void run() {
    83                 try {
    84                     acceptSocket.bind(new InetSocketAddress(accept));
    85                     LOGGER.debug("started accepting on port " + accept);
    86                     acceptNext();
    87                 } catch (IOException e) {
    88                     LOGGER.fatal("failed to accept on port " + accept + ": " + e);
    89                 }
    90                 try {
    91                     java.lang.Thread.sleep(1000);
    92                 } catch (InterruptedException ignored) {
    93                 }
    94                 tryBind(accept);
    95             }
    96         });
    97     }
     71        public void tryBind(final Integer accept) {
     72                acceptThread.invokeLater(new Runnable() {
     73                        @Override
     74                        public void run() {
     75                                try {
     76                                        acceptSocket.bind(new InetSocketAddress(accept));
     77                                        log.debug("started accepting on port " + accept);
     78                                        acceptNext();
     79                                } catch (IOException e) {
     80                                        log.fatal("failed to accept on port " + accept + ": " + e);
     81                                }
     82                                try {
     83                                        java.lang.Thread.sleep(1000);
     84                                } catch (InterruptedException ignored) {
     85                                }
     86                                tryBind(accept);
     87                        }
     88                });
     89        }
    9890
    9991}
  • java/main/src/main/java/com/framsticks/core/Node.java

    r77 r84  
    11package com.framsticks.core;
    22
    3 import com.framsticks.params.types.CompositeParam;
    4 
    5 import java.util.HashMap;
    6 import java.util.Map;
     3import com.framsticks.params.CompositeParam;
    74
    85/**
  • java/main/src/main/java/com/framsticks/core/Path.java

    r77 r84  
    22
    33import com.framsticks.params.AccessInterface;
     4import com.framsticks.params.CompositeParam;
    45import com.framsticks.params.Param;
    5 import com.framsticks.params.types.CompositeParam;
    6 import com.framsticks.util.Dispatching;
    7 import org.apache.log4j.Logger;
    8 
     6import com.framsticks.util.dispatching.Dispatching;
    97import java.util.Iterator;
    108import java.util.LinkedList;
     9import java.util.List;
     10
     11import org.apache.commons.collections.ListUtils;
    1112
    1213/**
     
    1415 */
    1516public class Path {
    16     private final static Logger LOGGER = Logger.getLogger(Path.class.getName());
    17 
    18     final LinkedList<Node> nodes = new LinkedList<Node>();
    19     String textual;
    20     Instance instance;
    21 
    22     protected Object getKnownChild(AccessInterface access, CompositeParam param) {
    23         Object child = access.get(param, Object.class);
    24         if (child == null) {
    25             return null;
    26         }
    27         return (instance.prepareAccess(param) != null) ? child : null;
    28     }
    29 
    30     public Path(Instance instance, String textual) {
    31         assert instance.isActive();
    32         this.instance = instance;
    33         StringBuilder b = new StringBuilder();
    34         nodes.add(instance.root);
    35         Node current = instance.root;
    36         Iterator<String> i = Instance.splitPath(textual);
    37         while (i.hasNext() && current.getObject() != null) {
    38             AccessInterface access = instance.prepareAccess(current.getParam());
    39             if (access == null) {
    40                 break;
    41             }
    42             String e = i.next();
    43             Param p = access.getParam(e);
    44             if (!(p instanceof CompositeParam)) {
    45                 //entries.add(new Entry());
    46                 break;
    47             }
    48             CompositeParam c = (CompositeParam)p;
    49             b.append("/").append(e);
    50             access.select(current.getObject());
    51             current = new Node(c, getKnownChild(access, c));
    52             nodes.add(current);
    53         }
    54         this.textual = (size() == 1) ? "/" : b.toString();
    55     }
    56 
    57     protected Path() {
    58 
    59     }
    60 
    61     public Path appendNode(Node node) {
    62         assert isResolved();
    63         Path result = new Path();
    64         result.textual = textual + ((size() == 1) ? "" : "/") + node.getParam().getId();
    65         result.instance = instance;
    66         result.nodes.addAll(nodes);
    67         result.nodes.add(node);
    68         return result;
    69     }
    70 
    71     public Path appendParam(CompositeParam param) {
    72         assert isResolved();
    73         return appendNode(new Node(param, null));
    74     }
    75 
    76     public Path appendResolution(Object object) {
    77         assert !isResolved();
    78         Path result = new Path();
    79         result.textual = textual;
    80         result.instance = instance;
    81         result.nodes.addAll(nodes);
    82         result.nodes.add(new Node(result.nodes.pollLast().getParam(), object));
    83         return result;
    84     }
    85 
    86     public final Object getTopObject() {
    87         return getTop().getObject();
    88     }
    89 
    90     public final Node getTop() {
    91         return nodes.getLast();
    92     }
    93 
    94     public final Node getUnder() {
    95         assert nodes.size() >= 2;
    96         return nodes.get(nodes.size() - 2);
    97     }
    98 
    99     public final String getTextual() {
    100         return textual;
    101     }
    102 
    103     public String toString() {
    104         return instance + textual + (!isResolved() ? "!" : "");
    105     }
    106 
    107     public final int size() {
    108         assert Dispatching.isThreadSafe();
    109         return nodes.size();
    110     }
    111 
    112     public final boolean isResolved() {
    113         assert Dispatching.isThreadSafe();
    114         return getTop().getObject() != null;
    115     }
    116 
    117     public final boolean isResolved(String textual) {
    118         assert Dispatching.isThreadSafe();
    119         return isTheSame(textual) && isResolved();
    120     }
    121 
    122     public final boolean isTheSame(String textual) {
    123         assert Dispatching.isThreadSafe();
    124         return this.textual.equals(textual);
    125     }
    126 
    127     public final Instance getInstance() {
    128         assert Dispatching.isThreadSafe();
    129         return instance;
    130     }
    131 
    132     public Path findResolution() {
    133         assert instance.isActive();
    134         assert !isResolved();
    135         if (size() == 1) {
     17        // private final static Logger log = Logger.getLogger(Path.class.getName());
     18
     19        final LinkedList<Node> nodes = new LinkedList<Node>();
     20        String textual;
     21        Instance instance;
     22
     23        protected Object getKnownChild(AccessInterface access, CompositeParam param) {
     24                Object child = access.get(param, Object.class);
     25                if (child == null) {
     26                        return null;
     27                }
     28                return (instance.registry.prepareAccess(param) != null) ? child : null;
     29        }
     30
     31        // public Path constructPath(Instance instance, String textual) {
     32        //      assert instance.isActive();
     33
     34        // }
     35
     36        Path(Instance instance, String textual) {
     37                assert instance.isActive();
     38                this.instance = instance;
     39
     40                nodes.add(instance.root);
     41                Node current = instance.root;
     42
     43                StringBuilder b = new StringBuilder();
     44                Iterator<String> i = Instance.splitPath(textual);
     45                while (i.hasNext() && current.getObject() != null) {
     46                        AccessInterface access = instance.registry.prepareAccess(current.getParam());
     47                        if (access == null) {
     48                                break;
     49                        }
     50                        String e = i.next();
     51                        Param p = access.getParam(e);
     52                        if (!(p instanceof CompositeParam)) {
     53                                //entries.add(new Entry());
     54                                break;
     55                        }
     56                        CompositeParam c = (CompositeParam)p;
     57                        b.append("/").append(e);
     58                        access.select(current.getObject());
     59                        current = new Node(c, getKnownChild(access, c));
     60                        nodes.add(current);
     61                }
     62                this.textual = (size() == 1) ? "/" : b.toString();
     63        }
     64
     65        public Path(Instance instance, List<Node> nodes, Node node) {
     66                this.instance = instance;
     67                StringBuilder b = new StringBuilder();
     68                boolean add = false;
     69                for (Node n : nodes) {
     70                        this.nodes.add(n);
     71                        if (add) {
     72                                b.append("/").append(n.getParam().getId());
     73                        }
     74                        add = true;
     75                        if (n == node) {
     76                                break;
     77                        }
     78                }
     79                this.textual = (size() == 1) ? "/" : b.toString();
     80        }
     81
     82        protected Path() {
     83
     84        }
     85
     86        public Path appendNode(Node node) {
     87                assert isResolved();
     88                Path result = new Path();
     89                result.textual = textual + ((size() == 1) ? "" : "/") + node.getParam().getId();
     90                result.instance = instance;
     91                result.nodes.addAll(nodes);
     92                result.nodes.add(node);
     93                return result;
     94        }
     95
     96        public Path appendParam(CompositeParam param) {
     97                assert isResolved();
     98                return appendNode(new Node(param, null));
     99        }
     100
     101        public Path appendResolution(Object object) {
     102                assert !isResolved();
     103                Path result = new Path();
     104                result.textual = textual;
     105                result.instance = instance;
     106                result.nodes.addAll(nodes);
     107                result.nodes.add(new Node(result.nodes.pollLast().getParam(), object));
     108                return result;
     109        }
     110
     111        public final Object getTopObject() {
     112                return getTop().getObject();
     113        }
     114
     115        public final Node getTop() {
     116                return nodes.getLast();
     117        }
     118
     119        public final Node getUnder() {
     120                assert nodes.size() >= 2;
     121                return nodes.get(nodes.size() - 2);
     122        }
     123
     124        public final String getTextual() {
     125                return textual;
     126        }
     127
     128        public String toString() {
     129                return instance + textual + (!isResolved() ? "!" : "");
     130        }
     131
     132        public final int size() {
     133                assert Dispatching.isThreadSafe();
     134                return nodes.size();
     135        }
     136
     137        public final boolean isResolved() {
     138                assert Dispatching.isThreadSafe();
     139                return getTop().getObject() != null;
     140        }
     141
     142        public final boolean isResolved(String textual) {
     143                assert Dispatching.isThreadSafe();
     144                return isTheSame(textual) && isResolved();
     145        }
     146
     147        public final boolean isTheSame(String textual) {
     148                assert Dispatching.isThreadSafe();
     149                return this.textual.equals(textual);
     150        }
     151
     152        public final Instance getInstance() {
     153                assert Dispatching.isThreadSafe();
     154                return instance;
     155        }
     156
     157
     158        /** Attach resolution at end, if available.
     159         *
     160         * @return Modified path, if resolution was available, this otherwise.
     161         */
     162        public Path tryFindResolution() {
     163                assert instance.isActive();
     164                assert !isResolved();
     165                if (size() == 1) {
    136166                        return new Path(instance, "/");//appendResolution(instance.root.object);
    137         }
    138         Object child = getKnownChild(instance.bindAccess(getUnder()), getTop().getParam());
    139         if (child == null) {
    140             return this;
    141         }
    142         return appendResolution(child);
    143     }
    144 
    145     public boolean matches(Path p) {
    146         assert Dispatching.isThreadSafe();
    147         assert instance == p.instance;
    148         Iterator<Node> a = nodes.iterator();
    149         Iterator<Node> b = p.nodes.iterator();
    150         while (a.hasNext() && b.hasNext()) {
    151             Node an = a.next();
    152             Node bn = b.next();
    153             if (an.object != bn.object) {
    154                 return false;
    155             }
    156         }
    157         return a.hasNext() == b.hasNext();
    158     }
    159 
    160     public String getLastElement() {
    161         return getTop().getParam().getId();
    162     }
    163 
    164     public final boolean isOwner(Instance instance) {
    165         return this.instance == instance;
    166     }
     167                }
     168                Object child = getKnownChild(instance.bindAccess(getUnder()), getTop().getParam());
     169                if (child == null) {
     170                        return this;
     171                }
     172                return appendResolution(child);
     173        }
     174
     175        public boolean matches(Path p) {
     176                assert Dispatching.isThreadSafe();
     177                assert instance == p.instance;
     178                Iterator<Node> a = nodes.iterator();
     179                Iterator<Node> b = p.nodes.iterator();
     180                while (a.hasNext() && b.hasNext()) {
     181                        Node an = a.next();
     182                        Node bn = b.next();
     183                        if (an.object != bn.object) {
     184                                return false;
     185                        }
     186                }
     187                return a.hasNext() == b.hasNext();
     188        }
     189
     190        public String getLastElement() {
     191                return getTop().getParam().getId();
     192        }
     193
     194        public final boolean isOwner(Instance instance) {
     195                return this.instance == instance;
     196        }
     197
     198        @SuppressWarnings("unchecked")
     199        public
     200        List<Node> getNodes() {
     201                return ListUtils.unmodifiableList(nodes);
     202        }
    167203}
    168204
  • java/main/src/main/java/com/framsticks/core/Program.java

    r78 r84  
    11package com.framsticks.core;
    22
    3 import com.framsticks.util.Pair;
    4 import com.framsticks.util.Strings;
     3import com.framsticks.util.lang.IterableIterator;
     4import com.framsticks.util.lang.Pair;
     5import com.framsticks.util.lang.Strings;
    56import org.apache.commons.configuration.*;
    67import org.apache.log4j.Logger;
    78import org.apache.log4j.PropertyConfigurator;
    8 //import sun.misc.Signal;
    9 //import sun.misc.SignalHandler;
    109
    1110import java.lang.reflect.Constructor;
     
    1514 * @author Piotr Sniegowski
    1615 */
    17 public class Program extends com.framsticks.util.Thread {
     16public class Program extends com.framsticks.util.dispatching.Thread {
    1817
    19     private final static Logger LOGGER = Logger.getLogger(Program.class.getName());
     18        private final static Logger log = Logger.getLogger(Program.class.getName());
    2019
    21 /*
    22     protected SignalHandler signalHandler = new SignalHandler() {
    23         @Override
    24         public void handle(Signal signal) {
    25             LOGGER.info("caught " + signal);
    26             Runtime.getRuntime().exit(0);
    27         }
    28     };
    29 */
     20        protected Entity entity;
    3021
    31     protected Entity entity;
     22        Configuration config;
    3223
    33     Configuration config;
     24        public Program(String name) {
     25                super(name, java.lang.Thread.currentThread());
     26        }
    3427
     28        public static Entity configureEntity(Configuration config) {
     29                String typeName = config.getString("class");
     30                log.info("configuring instance " + typeName);
     31                try {
     32                        Class<?> type = Class.forName(typeName);
     33                        Constructor<?> constructor = type.getConstructor();
     34                        Entity entity = (Entity) constructor.newInstance();
     35                        return entity;
     36                } catch (Exception e) {
     37                        log.error("failed to instantiate: " + e);
     38                }
     39                return null;
     40        }
    3541
    36     public Program(String name) {
    37         super(name, java.lang.Thread.currentThread());
    38 //        Signal.handle(new Signal("INT"), signalHandler);
    39 //        Signal.handle(new Signal("TERM"), signalHandler);
    40     }
     42        protected static void resolve(Configuration config, String prefix) {
     43                for (String p : new IterableIterator<String>(prefix == null ? config.getKeys() : config.getKeys(prefix))) {
     44                        if (p.endsWith(".mount")) {
     45                                String source = config.getString(p);
     46                                log.info("mounting " + source + " at " + p);
     47                                config.clearProperty(p);
     48                                Configuration mount = config.subset(source);
     49                                for (String mk : new IterableIterator<String>(mount.getKeys())) {
     50                                        config.addProperty(p.substring(0, p.length() - 6) + "." + mk, mount.getProperty(mk));
     51                                }
     52                        }
     53                }
     54        }
    4155
    42     public static Entity configureEntity(Parameters parameters) {
    43         String typeName = parameters.getConfig().getString("class");
    44         LOGGER.info("configuring instance " + typeName);
    45         try {
    46             Class type = Class.forName(typeName);
    47             Constructor constructor = type.getConstructor(Parameters.class);
    48             return (Entity) constructor.newInstance(parameters);
    49         } catch (Exception e) {
    50             LOGGER.error("failed to instantiate: " + e);
    51         }
    52         return null;
    53     }
    54 
    55     protected static void resolve(Configuration config, String prefix) {
    56 
    57         Iterator i = prefix == null ? config.getKeys() : config.getKeys(prefix);
    58         while (i.hasNext()) {
    59             String p = (String) i.next();
    60             if (p.endsWith(".mount")) {
    61                 String source = config.getString(p);
    62                 LOGGER.info("mounting " + source + " at " + p);
    63                 config.clearProperty(p);
    64                 Configuration mount = config.subset(source);
    65                 Iterator mi = mount.getKeys();
    66                 while (mi.hasNext()) {
    67                     String mk = (String) mi.next();
    68                     config.addProperty(p.substring(0, p.length() - 6) + "." + mk, mount.getProperty(mk));
    69                 }
    70             }
    71         }
    72     }
    73 
    74     public void run(String[] args) {
     56        public void run(String[] args) {
    7557
    7658                PropertyConfigurator.configure(getClass().getResource("/configs/log4j.properties"));
    77                 LOGGER.debug("started in " + System.getProperty("user.dir"));
    78         try {
     59                log.debug("started in " + System.getProperty("user.dir"));
     60                try {
    7961                        config = new PropertiesConfiguration(getClass().getResource("/configs/framsticks.properties"));
    8062
    81             for (String a : args) {
    82                 Pair<String, String> p = Strings.splitIntoPair(a, '=', "true");
    83                 config.setProperty(p.first, p.second);
    84             }
     63                        for (String a : args) {
     64                                Pair<String, String> p = Strings.splitIntoPair(a, '=', "true");
     65                                config.setProperty(p.first, p.second);
     66                        }
    8567
    86             resolve(config, null);
     68                        resolve(config, null);
    8769
    88             Iterator i = config.getKeys();
    89             while (i.hasNext()) {
    90                 String p = (String) i.next();
    91                 LOGGER.debug(p + " = " + config.getProperty(p));
    92             }
     70                        Iterator<?> i = config.getKeys();
     71                        while (i.hasNext()) {
     72                                String p = (String) i.next();
     73                                log.debug(p + " = " + config.getProperty(p));
     74                        }
    9375
    94         } catch (ConfigurationException e) {
    95             System.err.print("failed to parse configuration:" + e);
    96             return;
    97         }
     76                } catch (ConfigurationException e) {
     77                        System.err.print("failed to parse configuration:" + e);
     78                        return;
     79                }
     80                Configuration entityConfig = config.subset("com.framsticks.entity");
    9881
    99         entity = configureEntity(new Parameters(config.subset("com.framsticks.entity"), "main", null, new EntityOwner() {
     82                entity = configureEntity(entityConfig);
     83                entity.setOwner(new EntityOwner() {
    10084                        @Override
    10185                        public void onDone() {
    102                                 LOGGER.info("exiting");
     86                                log.info("exiting");
    10387                                Runtime.getRuntime().exit(0);
    10488                        }
    105                 }));
     89                });
     90                entity.setName("main");
    10691                try {
    107                 entity.configurePublic();
     92                        entity.configure(entityConfig);
    10893                } catch (Exception e) {
    109                         LOGGER.fatal("exception caught during configuration: " + e);
     94                        log.fatal("exception caught during configuration: " + e);
    11095                }
    111         LOGGER.info("all entities were configured");
    112         entity.start();
    113     }
     96                log.info("all entities were configured");
     97                entity.start();
     98        }
    11499
    115     public static void main(final String[] args) {
    116         final Program program = new Program("program");
    117         program.invokeLater(new Runnable() {
    118             @Override
    119             public void run() {
    120                 program.run(args);
    121             }
    122         });
    123         program.routine();
    124     }
     100        public static void main(final String[] args) {
     101
     102                final Program program = new Program("program");
     103                program.invokeLater(new Runnable() {
     104                        @Override
     105                        public void run() {
     106                                program.run(args);
     107                        }
     108                });
     109                program.routine();
     110        }
    125111
    126112}
  • java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java

    r78 r84  
    11package com.framsticks.diagnostics;
    22
    3 import com.framsticks.core.Parameters;
     3import org.apache.commons.configuration.Configuration;
     4
    45import com.framsticks.observers.Endpoint;
    56import com.framsticks.observers.Observer;
     
    1011public class Diagnostics extends Observer {
    1112
    12     final Integer dumpsInterval;
    13     final String dumpsPath;
    14     final String dumpsFormat;
     13        Integer dumpsInterval;
     14        String dumpsPath;
     15        String dumpsFormat;
    1516
    1617
    17     public Diagnostics(Parameters parameters) {
    18         super(parameters);
    19         dumpsInterval = config.getInteger("dumps.interval", null);
    20         dumpsPath = config.getString("dumps.path", null);
    21         dumpsFormat = config.getString("dumps.format", null);
    22     }
     18        public Diagnostics() {
     19        }
    2320
    24     @Override
    25     protected void configure() throws Exception {
    26 
    27         super.configure();
    28     }
     21        @Override
     22        public void configure(Configuration config) {
     23                super.configure(config);
     24                dumpsInterval = config.getInteger("dumps.interval", null);
     25                dumpsPath = config.getString("dumps.path", null);
     26                dumpsFormat = config.getString("dumps.format", null);
     27        }
    2928
    3029
    31     @Override
    32     protected Endpoint createEndpoint() {
    33         return new DiagnosticsEndpoint();
    34     }
     30        @Override
     31        protected Endpoint createEndpoint() {
     32                return new DiagnosticsEndpoint();
     33        }
    3534
    3635
  • java/main/src/main/java/com/framsticks/diagnostics/DiagnosticsEndpoint.java

    r77 r84  
    11package com.framsticks.diagnostics;
    22
    3 import com.framsticks.core.Path;
     3import com.framsticks.dumping.PrintWriterSink;
    44import com.framsticks.dumping.SaveStream;
    55import com.framsticks.observers.Endpoint;
    6 import com.framsticks.dumping.PrintStreamSink;
    76import com.framsticks.remote.RecursiveFetcher;
    87import com.framsticks.util.Logging;
     
    1312import java.io.File;
    1413import java.io.IOException;
    15 import java.io.PrintStream;
     14import java.io.PrintWriter;
    1615import java.text.SimpleDateFormat;
    1716import java.util.Date;
     
    2221public class DiagnosticsEndpoint extends Endpoint {
    2322
    24     private final static Logger LOGGER = Logger.getLogger(DiagnosticsEndpoint.class.getName());
     23        private final static Logger log = Logger.getLogger(DiagnosticsEndpoint.class.getName());
    2524
    2625
    27     public DiagnosticsEndpoint() {
    28         super();
    29     }
     26        public DiagnosticsEndpoint() {
     27                super();
     28        }
    3029
    31     @Override
    32     public Diagnostics getObserver() {
    33         return (Diagnostics)observer;
    34     }
     30        @Override
     31        public Diagnostics getObserver() {
     32                return (Diagnostics)observer;
     33        }
    3534
    3635
    37     @Override
    38     protected void configure() {
    39         super.configure();
     36        @Override
     37        public void start() {
     38                super.start();
    4039
    41         if (getObserver().dumpsInterval != null) {
    42             new PeriodicTask(instance, getObserver().dumpsInterval * 1000) {
    43                 @Override
    44                 public void run() {
     40                if (getObserver().dumpsInterval != null) {
     41                        new PeriodicTask(instance, getObserver().dumpsInterval * 1000) {
     42                                @Override
     43                                public void run() {
    4544
    46                     LOGGER.info("starting periodic dump");
    47                     new RecursiveFetcher(instance, new Path(instance, "/"), new StateFunctor() {
    48                         @Override
    49                         public void call(Exception e) {
    50                             if (Logging.log(LOGGER, "recursively fetch", instance, e)) {
    51                                 again();
    52                                 return;
    53                             }
    54                             LOGGER.info("instance resolved, saving");
    55                             try {
    56                                 final String fileName = getObserver().dumpsPath + "/" + instance + "_" + new SimpleDateFormat(getObserver().dumpsFormat).format(new Date()) + ".param";
    57                                 File file = new File(fileName);
    58                                 new SaveStream(new PrintStreamSink(new PrintStream(file)), instance, new Path(instance, "/"), new StateFunctor() {
    59                                     @Override
    60                                     public void call(Exception e) {
    61                                         Logging.log(LOGGER, "periodic dump in " + fileName + " of", DiagnosticsEndpoint.this.instance, e);
    62                                         again();
    63                                     }
    64                                 });
    65                             } catch (IOException ex) {
    66                                 LOGGER.info("failed to initiate dump: " + ex);
    67                                 again();
    68                             }
     45                                        log.info("starting periodic dump");
     46                                        new RecursiveFetcher(instance, instance.getRootPath(), new StateFunctor() {
     47                                                @Override
     48                                                public void call(Exception e) {
     49                                                        if (Logging.log(log, "recursively fetch", instance, e)) {
     50                                                                again();
     51                                                                return;
     52                                                        }
     53                                                        log.info("instance resolved, saving");
     54                                                        try {
     55                                                                final String fileName = getObserver().dumpsPath + "/" + instance + "_" + new SimpleDateFormat(getObserver().dumpsFormat).format(new Date()) + ".param";
     56                                                                File file = new File(fileName);
     57                                                                new SaveStream(new PrintWriterSink(new PrintWriter(file)), instance, instance.getRootPath(), new StateFunctor() {
     58                                                                        @Override
     59                                                                        public void call(Exception e) {
     60                                                                                Logging.log(log, "periodic dump in " + fileName + " of", DiagnosticsEndpoint.this.instance, e);
     61                                                                                again();
     62                                                                        }
     63                                                                });
     64                                                        } catch (IOException ex) {
     65                                                                log.info("failed to initiate dump: " + ex);
     66                                                                again();
     67                                                        }
    6968
    70                         }
    71                     });
     69                                                }
     70                                        });
    7271
    7372
    74                 }
    75             };
    76         }
    77     }
     73                                }
     74                        };
     75                }
     76        }
    7877
    79     /*
    80     @Override
    81     public void onChange(Path path) {
    82         super.onChange(path);    //To change body of overridden methods use File | Settings | File Templates.
    83     }
    84     */
     78        /*
     79        @Override
     80        public void onChange(Path path) {
     81                super.onChange(path);    //To change body of overridden methods use File | Settings | File Templates.
     82        }
     83        */
    8584}
  • java/main/src/main/java/com/framsticks/dumping/FileInstance.java

    r78 r84  
    22
    33import com.framsticks.core.LocalInstance;
    4 import com.framsticks.core.Parameters;
    54import com.framsticks.core.Path;
    6 import com.framsticks.params.FramsClass;
    75import com.framsticks.core.Instance;
    8 import com.framsticks.util.*;
    9 import com.framsticks.util.UnsupportedOperationException;
     6import com.framsticks.util.dispatching.Future;
     7
     8import org.apache.commons.configuration.Configuration;
    109import org.apache.log4j.Logger;
    1110
     
    2019public class FileInstance extends LocalInstance {
    2120
    22     private static final Logger LOGGER = Logger.getLogger(Instance.class.getName());
    23     protected final File file;
     21        private static final Logger log = Logger.getLogger(Instance.class.getName());
     22        protected File file;
    2423
    25     public FileInstance(Parameters parameters) {
    26         super(parameters);
    27         file = new File(config.getString("filename"));
    28     }
     24        public FileInstance() {
     25        }
    2926
    30     @Override
    31     public void run() {
    32         assert isActive();
    33         super.run();
    34         try {
    35             FileReader fileReader = new FileReader(file);
    36             LoadStream stream = new LoadStream(new Path(this, "/"), new BufferedReader(fileReader), this, new Future<Path>() {
    37                 @Override
    38                 public void result(Path result, Exception e) {
    39                     if (e != null) {
    40                         LOGGER.error("failed to load file instance " + FileInstance.this + ": " + e);
    41                         fireRun(e);
    42                         return;
    43                     }
    44                     LOGGER.info("loaded file instance " + FileInstance.this);
    45                     fireRun(null);
    46                 }
    47             });
    48             stream.load();
    49         } catch (IOException e) {
    50             LOGGER.error("io failure: " + e);
    51             fireRun(e);
    52         }
    53     }
     27        @Override
     28        public void configure(Configuration config) {
     29                super.configure(config);
     30                file = new File(config.getString("filename"));
     31        }
    5432
    55     @Override
    56     public String toString() {
    57         return "file@" + file.getName();
    58     }
     33        @Override
     34        public void run() {
     35                assert isActive();
     36                super.run();
     37                try {
     38                        FileReader fileReader = new FileReader(file);
     39                        LoadStream stream = new LoadStream(this.getRootPath(), new BufferedReader(fileReader), this, new Future<Path>() {
     40                                @Override
     41                                public void result(Path result, Exception e) {
     42                                        if (e != null) {
     43                                                log.error("failed to load file instance " + FileInstance.this + ": " + e);
     44                                                fireRun(e);
     45                                                return;
     46                                        }
     47                                        log.info("loaded file instance " + FileInstance.this);
     48                                        fireRun(null);
     49                                }
     50                        });
     51                        stream.load();
     52                } catch (IOException e) {
     53                        log.error("io failure: " + e);
     54                        fireRun(e);
     55                }
     56        }
     57
     58        @Override
     59        public String toString() {
     60                return "file@" + file.getName();
     61        }
    5962
    6063
  • java/main/src/main/java/com/framsticks/dumping/LoadStream.java

    r77 r84  
    66import com.framsticks.core.Instance;
    77import com.framsticks.util.*;
     8import com.framsticks.util.dispatching.Future;
     9import com.framsticks.util.lang.Pair;
     10import com.framsticks.util.lang.Strings;
    811import org.apache.log4j.Logger;
    912
     
    1821public class LoadStream {
    1922
    20     private final static Logger LOGGER = Logger.getLogger(LoadStream.class.getName());
     23        private final static Logger log = Logger.getLogger(LoadStream.class.getName());
    2124
    22     protected final Instance instance;
    23     protected final Path mountPath;
    24     protected final BufferedReader stream;
    25     protected final Future<Path> future;
    26     protected final Stopwatch stopwatch = new Stopwatch();
     25        protected final Instance instance;
     26        protected final Path mountPath;
     27        protected final BufferedReader stream;
     28        protected final Future<Path> future;
     29        protected final Stopwatch stopwatch = new Stopwatch();
    2730
    2831
    29     public LoadStream(Path mountPath, BufferedReader stream, Instance instance, Future<Path> future) {
    30         this.instance = instance;
    31         this.mountPath = mountPath;
    32         this.stream = stream;
    33         this.future = future;
    34     }
     32        public LoadStream(Path mountPath, BufferedReader stream, Instance instance, Future<Path> future) {
     33                this.instance = instance;
     34                this.mountPath = mountPath;
     35                this.stream = stream;
     36                this.future = future;
     37        }
    3538
    36     public void load() {
    37         try {
    38             String line;
    39             Pair<String, String> query = null;
    40             List<File> files = null;
    41             List<String> content = null;
    42             //File file;
    43             while ((line = stream.readLine()) != null) {
    44                 if (query == null) {
    45                     query = Strings.splitIntoPair(line, ' ', "\n");
    46                     files = new LinkedList<File>();
    47                     LOGGER.trace("loading " + line);
    48                     continue;
    49                 }
    50                 if (content == null) {
    51                     if (line.equals("file")) {
    52                         content = new LinkedList<String>();
    53                         continue;
    54                     }
    55                     if (line.equals("ok")) {
    56                         if (query.first.equals("get")) {
    57                             Path path = instance.createIfNeeded(query.second);
    58                             instance.processFetchedValues(path, files);
    59                         } else if (query.first.equals("info")) {
    60                             assert files.size() == 1;
    61                             instance.processFetchedInfo(files.get(0));
    62                         } else {
    63                             assert false;
    64                         }
    65                         query = null;
    66                         files = null;
    67                         continue;
    68                     }
    69                     assert false;
    70                     continue;
    71                 }
    72                 if (line.equals("eof")) {
    73                     files.add(new File(query.second, new ListSource(content)));
    74                     content = null;
    75                     continue;
    76                 }
    77                 content.add(line);
    78             }
    79         } catch (IOException e) {
    80             LOGGER.error("failed to load: " + e);
    81             future.result(null, e);
    82             return;
    83         }
    84         LOGGER.info("loaded in: " + stopwatch);
    85         future.result(new Path(instance, mountPath.getTextual()), null);
    86     }
     39        public void load() {
     40                try {
     41                        String line;
     42                        Pair<String, String> query = null;
     43                        List<File> files = null;
     44                        List<String> content = null;
     45                        //File file;
     46                        while ((line = stream.readLine()) != null) {
     47                                if (query == null) {
     48                                        query = Strings.splitIntoPair(line, ' ', "\n");
     49                                        files = new LinkedList<File>();
     50                                        log.trace("loading " + line);
     51                                        continue;
     52                                }
     53                                if (content == null) {
     54                                        if (line.equals("file")) {
     55                                                content = new LinkedList<String>();
     56                                                continue;
     57                                        }
     58                                        if (line.equals("ok")) {
     59                                                if (query.first.equals("get")) {
     60                                                        Path path = instance.createIfNeeded(query.second);
     61                                                        instance.processFetchedValues(path, files);
     62                                                } else if (query.first.equals("info")) {
     63                                                        assert files.size() == 1;
     64                                                        instance.processFetchedInfo(files.get(0));
     65                                                } else {
     66                                                        assert false;
     67                                                }
     68                                                query = null;
     69                                                files = null;
     70                                                continue;
     71                                        }
     72                                        assert false;
     73                                        continue;
     74                                }
     75                                if (line.equals("eof")) {
     76                                        files.add(new File(query.second, new ListSource(content)));
     77                                        content = null;
     78                                        continue;
     79                                }
     80                                content.add(line);
     81                        }
     82                } catch (IOException e) {
     83                        log.error("failed to load: " + e);
     84                        future.result(null, e);
     85                        return;
     86                }
     87                log.info("loaded in: " + stopwatch);
     88                future.result(instance.getPath(mountPath.getTextual()), null);
     89        }
    8790
    8891
  • java/main/src/main/java/com/framsticks/dumping/SaveStream.java

    r78 r84  
    44import com.framsticks.core.Path;
    55import com.framsticks.params.AccessInterface;
     6import com.framsticks.params.CompositeParam;
    67import com.framsticks.params.FramsClass;
    78import com.framsticks.params.ListAccess;
    8 import com.framsticks.params.Param;
    9 import com.framsticks.params.types.CompositeParam;
    109import com.framsticks.params.SinkInterface;
    1110import com.framsticks.parsers.Savers;
    1211import com.framsticks.core.Instance;
    1312import com.framsticks.util.*;
     13import com.framsticks.util.dispatching.Dispatching;
    1414import org.apache.log4j.Logger;
    1515
    1616import java.util.HashSet;
    1717import java.util.Set;
     18import static com.framsticks.util.lang.Containers.filterInstanceof;
    1819
    1920/**
     
    2223public class SaveStream {
    2324
    24     private final static Logger LOGGER = Logger.getLogger(SaveStream.class.getName());
     25        private final static Logger log = Logger.getLogger(SaveStream.class.getName());
    2526
    26     protected final SinkInterface sink;
    27     protected final Instance instance;
    28     protected final StateFunctor stateFunctor;
    29     protected final Stopwatch stopwatch = new Stopwatch();
    30     protected final Set<FramsClass> storedInfo = new HashSet<FramsClass>();
     27        protected final SinkInterface sink;
     28        protected final Instance instance;
     29        protected final StateFunctor stateFunctor;
     30        protected final Stopwatch stopwatch = new Stopwatch();
     31        protected final Set<FramsClass> storedInfo = new HashSet<FramsClass>();
    3132
    32     private int dispatched = 0;
     33        private int dispatched = 0;
    3334
    34     public SaveStream(SinkInterface sink, Instance instance, Path root, StateFunctor stateFunctor) {
    35         assert Dispatching.isThreadSafe();
    36         this.sink = sink;
    37         this.instance = instance;
    38         this.stateFunctor = stateFunctor;
     35        public SaveStream(SinkInterface sink, Instance instance, Path root, StateFunctor stateFunctor) {
     36                assert Dispatching.isThreadSafe();
     37                this.sink = sink;
     38                this.instance = instance;
     39                this.stateFunctor = stateFunctor;
    3940                dispatchWrite(root);
    40     }
     41        }
    4142
    4243        protected void dispatchWrite(final Path path) {
     
    5051        }
    5152
    52     protected void finished() {
    53         assert instance.isActive();
    54         LOGGER.info("stored in " + stopwatch);
    55         stateFunctor.call(null);
    56     }
     53        protected void finished() {
     54                assert instance.isActive();
     55                log.info("stored in " + stopwatch);
     56                stateFunctor.call(null);
     57        }
    5758
    58     public void write(final Path path) {
    59         assert instance.isActive();
    60         if (!path.isResolved()) {
    61             LOGGER.debug("path " + path + " is not resolved - skipping");
    62         } else {
    63             AccessInterface access = instance.bindAccess(path);
     59        public void write(final Path path) {
     60                assert instance.isActive();
     61                if (!path.isResolved()) {
     62                        log.debug("path " + path + " is not resolved - skipping");
     63                } else {
     64                        AccessInterface access = instance.bindAccess(path);
    6465                        assert access != null;
    65             FramsClass framsClass = access.getFramsClass();
    66             assert framsClass != null;
    67             if (!storedInfo.contains(framsClass)) {
    68                 storedInfo.add(framsClass);
    69                 sink.print("info ").print(path.getTextual()).breakLine();
    70                 sink.print("file").breakLine();
    71                 Savers.saveFramsClass(sink, framsClass);
    72                 sink.print("eof").breakLine();
    73                 sink.print("ok").breakLine();
    74             }
    75             if (!(access instanceof ListAccess)) {
    76                 sink.print("get ").print(path.getTextual()).breakLine();
    77                 sink.print("file").breakLine();
    78                 //stream.print("#" + access.getSelected().getClass().getCanonicalName() + "\n");
    79                 access.save(sink);
    80                 sink.print("eof").breakLine();
    81                 sink.print("ok").breakLine();
    82             }
    83             for (Param p : access.getParams()) {
    84                 if (p instanceof CompositeParam) {
    85                     CompositeParam childParam = (CompositeParam)p;
    86                     final Path childPath = path.appendNode(new Node(childParam, access.get(childParam, Object.class)));
    87                     if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
    88                                                 dispatchWrite(childPath);
    89                     }
    90                 }
    91             }
    92         }
    93         --dispatched;
    94         if (dispatched == 0) {
    95             finished();
    96         }
    97     }
     66                        FramsClass framsClass = access.getFramsClass();
     67                        assert framsClass != null;
     68                        if (!storedInfo.contains(framsClass)) {
     69                                storedInfo.add(framsClass);
     70                                sink.print("info ").print(path.getTextual()).breakLine();
     71                                sink.print("file").breakLine();
     72                                Savers.saveFramsClass(sink, framsClass);
     73                                sink.print("eof").breakLine();
     74                                sink.print("ok").breakLine();
     75                        }
     76                        if (!(access instanceof ListAccess)) {
     77                                sink.print("get ").print(path.getTextual()).breakLine();
     78                                sink.print("file").breakLine();
     79                                //stream.print("#" + access.getSelected().getClass().getCanonicalName() + "\n");
     80                                access.save(sink);
     81                                sink.print("eof").breakLine();
     82                                sink.print("ok").breakLine();
     83                        }
     84                        for (CompositeParam p : filterInstanceof(access.getParams(), CompositeParam.class)) {
     85                                final Path childPath = path.appendNode(new Node(p, access.get(p, Object.class)));
     86                                if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
     87                                        dispatchWrite(childPath);
     88                                }
     89                        }
     90                }
     91                --dispatched;
     92                if (dispatched == 0) {
     93                        finished();
     94                }
     95        }
    9896}
  • java/main/src/main/java/com/framsticks/examples/GenotypeBrowser.java

    r79 r84  
    33import com.framsticks.core.Instance;
    44import com.framsticks.core.Node;
    5 import com.framsticks.core.Parameters;
    6 import com.framsticks.core.Path;
     5import com.framsticks.dumping.PrintWriterSink;
    76import com.framsticks.model.*;
    87import com.framsticks.model.Package;
    98import com.framsticks.params.*;
    10 import com.framsticks.params.types.CompositeParam;
    119import com.framsticks.parsers.F0Parser;
     10import com.framsticks.parsers.F0Writer;
    1211import com.framsticks.parsers.Schema;
     12
     13import org.apache.commons.configuration.Configuration;
    1314import org.apache.log4j.Logger;
    1415
     16import java.io.PrintWriter;
     17import java.io.StringWriter;
    1518import java.util.List;
    1619
     
    2023public class GenotypeBrowser extends Instance {
    2124
    22         private static final Logger LOGGER = Logger.getLogger(Instance.class.getName());
     25        private static final Logger log = Logger
     26                        .getLogger(Instance.class.getName());
    2327        protected Schema schema;
    2428
    25 
    26         public GenotypeBrowser(Parameters parameters) {
    27                 super(parameters);
    28                 LOGGER.info("model builder created");
     29        public GenotypeBrowser() {
     30                log.info("model builder created");
    2931        }
    3032
    3133        @Override
    32         protected void configure() throws Exception {
    33                 super.configure();
    34                 schema = new Schema(Schema.getDefaultDefinitionAsStream());
     34        public void configure(Configuration config) {
     35                super.configure(config);
     36                try {
     37                        schema = new Schema(Schema.getDefaultDefinitionAsStream());
     38                } catch (Exception e) {
     39                        log.error("failed to load schema: " + e);
     40                }
    3541                this.registry = schema.getRegistry();
    3642                Package.register(this.getRegistry());
     
    3844                registry.putInfoIntoCache(new FramsClass("ModelBuilderRoot", "ModelBuilderRoot", null)
    3945                                .append(new ParamBuilder().setType("o Model").setId("model").setName("model").build())
     46                                .append(new ParamBuilder().setType("s 1").setId("genotype").setName("genotype").build())
    4047                );
    4148                root = new Node((CompositeParam)new ParamBuilder().setType("o ModelBuilderRoot").setId(name).setName("Instance").build(), PropertiesAccess.createPropertiesMap());
     
    5158                        Model model = Model.build(objects);
    5259
    53                         AccessInterface rootAccess = bindAccess(new Path(this, "/"));
     60                        AccessInterface rootAccess = bindAccess(this.getRootPath());
    5461
    5562                        rootAccess.set("model", model);
    5663
     64                        StringWriter w = new StringWriter();
     65                        new F0Writer(schema, model, new PrintWriterSink(new PrintWriter(w))).write();
     66                        rootAccess.set("genotype", w.getBuffer().toString());
     67
    5768                } catch (Exception e) {
    58                         LOGGER.error("exception caught: " + e);
     69                        log.error("exception caught: " + e);
    5970                }
    6071                //done();
  • java/main/src/main/java/com/framsticks/gui/Browser.java

    r78 r84  
    44import com.framsticks.observers.Endpoint;
    55import com.framsticks.observers.Observer;
    6 import com.framsticks.util.Dispatcher;
     6import com.framsticks.util.Logging;
     7import com.framsticks.util.dispatching.Dispatcher;
     8import com.framsticks.util.dispatching.Future;
     9
     10import org.apache.commons.configuration.Configuration;
     11import org.apache.commons.lang.ArrayUtils;
    712import org.apache.log4j.Logger;
    813
    914import javax.swing.*;
     15
     16import java.awt.Dimension;
     17import java.util.ArrayList;
    1018import java.util.HashSet;
     19import java.util.List;
    1120import java.util.Set;
    1221
     
    1625public class Browser extends Observer implements Dispatcher {
    1726
    18     private static final Logger LOGGER = Logger.getLogger(Browser.class.getName());
    19 
    20     protected final Set<Frame> frames = new HashSet<Frame>();
    21     protected MainFrame mainFrame;
    22 
    23     public void addFrame(Frame frame) {
    24         frames.add(frame);
    25     }
    26 
    27         public Browser(Parameters parameters) {
    28         super(parameters);
    29         dispatcher = SwingDispatcher.instance;
    30         invokeLater(new Runnable() {
    31             @Override
    32             public void run() {
    33                 assert isActive();
    34 
    35             }
    36         });
     27        private static final Logger log = Logger.getLogger(Browser.class.getName());
     28
     29        protected final Set<Frame> frames = new HashSet<Frame>();
     30        protected MainFrame mainFrame;
     31        public List<PanelProvider> panelProviders = new ArrayList<PanelProvider>();
     32        protected Dimension defaultFrameDimension;
     33
     34        public void addFrame(Frame frame) {
     35                frames.add(frame);
     36        }
     37
     38        public Browser() {
     39                JPopupMenu.setDefaultLightWeightPopupEnabled(false);
     40                addPanelProvider(new StandardPanelProvider());
     41        }
     42
     43        @Override
     44        public void configure(Configuration config) {
     45                super.configure(config);
     46
     47                defaultFrameDimension = new Dimension(config.getInteger("size.width", 1000), config.getInteger("size.height", 500));
     48
     49                for (String name : config.getStringArray("panel_providers")) {
     50                        try {
     51                                Class<?> c = Class.forName(name);
     52                                if (ArrayUtils.indexOf(c.getInterfaces(), PanelProvider.class) == -1) {
     53                                        continue;
     54                                }
     55                                PanelProvider p = (PanelProvider)c.newInstance();
     56                                addPanelProvider(p);
     57                        } catch (Exception e) {
     58                                log.error("failed to load PanelProvider " + name + ": " + e);
     59                        }
     60                }
     61
     62                // for (final String path : config.getStringArray("resolve_paths")) {
     63                //      invokeLater()
     64                //      autoResolvePath(path, new Future<Path>() {
     65                //              @Override
     66                //              public void result(Path p, Exception e) {
     67                //                      Logging.log(log, "auto resolve path", path, e);
     68                //              }
     69                //      });
     70                // }
     71        }
     72
     73        public void addPanelProvider(PanelProvider panelProvider) {
     74                log.debug("added panel provider of type: " + panelProvider.getClass().getCanonicalName());
     75                panelProviders.add(panelProvider);
     76        }
     77
     78        public void autoResolvePath(final String path, final Future<Path> future) {
     79                final Instance i = endpoints.get("localhost").getInstance();
     80                i.invokeLater(new Runnable() {
     81                        @Override
     82                        public void run() {
     83                                i.resolveAndFetch(path, new Future<Path>() {
     84                                        @Override
     85                                        public void result(final Path p, Exception e) {
     86                                                Logging.log(log, "auto resolve path", path, e);
     87                                                if (future != null) {
     88                                                        future.result(p, e);
     89                                                }
     90                                                if (e == null) {
     91                                                        mainFrame.invokeLater(new Runnable() {
     92                                                                @Override
     93                                                                public void run() {
     94                                                                        mainFrame.goTo(p);
     95                                                                }
     96                                                        });
     97                                                }
     98                                        }
     99                                });
     100                        }
     101                });
    37102        }
    38103
    39104        public void clear() {
    40         assert isActive();
    41         for (Frame f : frames) {
    42             f.clear();
    43         }
    44         }
    45 
    46     @Override
    47     protected void configure() throws Exception {
    48         super.configure();
    49     }
    50 
    51 
    52     @Override
    53     public void run() {
    54         super.run();
    55 
    56         try {
    57             UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
    58         } catch (Exception ex) {
    59             LOGGER.warn("failed loading Look&Feel: ", ex);
    60         }
    61         javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
    62 
    63         mainFrame = new MainFrame(Browser.this);
    64         addFrame(mainFrame);
    65 
    66         for (Frame f : frames) {
    67             f.configure();
    68         }
    69 
    70         for (final Endpoint e : getEndpoints().values()) {
    71             e.invokeLater(new Runnable() {
    72                 @Override
    73                 public void run() {
    74                     final Path p = new Path(e.getInstance(), "/");
    75                     invokeLater(new Runnable() {
    76                         @Override
    77                         public void run() {
    78                             mainFrame.addRootPath((BrowserEndpoint) e, p);
    79                         }
    80                     });
    81                 }
    82             });
    83 
    84         }
    85 
    86         for (Frame f : frames) {
    87             f.setVisible(true);
    88         }
    89     }
    90 
    91     public void createTreeNodeForChild(final Path path) {
    92         assert !isActive();
    93         //assert instance.isActive();
     105                assert isActive();
     106                for (Frame f : frames) {
     107                        f.clear();
     108                }
     109        }
     110
     111        @Override
     112        public void run() {
     113                super.run();
     114
     115                assert isActive();
     116
     117                try {
     118                        boolean found = false;
     119                        // for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
     120                        //      log.info("look and feel available: " + info.getName());
     121                        //      if ("Nimbus".equals(info.getName())) {
     122                        //              UIManager.setLookAndFeel(info.getClassName());
     123                        //              found = true;
     124                        //              break;
     125                        //      }
     126                        // }
     127                        if (!found) {
     128                                UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
     129                        }
     130                } catch (Exception ex) {
     131                        log.warn("failed loading Look&Feel: ", ex);
     132                }
     133
     134                javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
     135
     136                mainFrame = new MainFrame(Browser.this);
     137                addFrame(mainFrame);
     138
     139                for (Frame f : frames) {
     140                        f.configure();
     141                }
     142
     143                for (final Endpoint e : getEndpoints().values()) {
     144                        e.invokeLater(new Runnable() {
     145                                @Override
     146                                public void run() {
     147                                        final Path p = e.getInstance().getRootPath();
     148                                        invokeLater(new Runnable() {
     149                                                @Override
     150                                                public void run() {
     151                                                        mainFrame.addRootPath((BrowserEndpoint) e, p);
     152                                                }
     153                                        });
     154                                }
     155                        });
     156                }
     157
     158                for (Frame f : frames) {
     159                        f.setVisible(true);
     160                }
     161
     162                // autoResolvePath("/simulator/genepools/groups/0", null);
     163                // autoResolvePath("/", null);
     164        }
     165
     166        public void createTreeNodeForChild(final Path path) {
     167                assert !isActive();
     168                //assert instance.isActive();
    94169
    95170
    96171/*
    97         final TreeNode parentTreeNode = (TreeNode) child.getParent().getUserObject();
    98         if (parentTreeNode == null) {
    99             Dispatching.invokeDispatch(this, manager, new Runnable() {
    100                 @Override
    101                 public void run() {
    102                     createTreeNodeForChild(child);
    103                 }
    104             });
    105             return;
    106         }
    107         LOGGER.debug(child.getClass().getSimpleName() + " created: " + child);
    108 
    109 
    110         invokeLater(new Runnable() {
    111             @Override
    112             public void run() {
    113                 parentTreeNode.getOrCreateChildTreeNodeFor(child);
    114             }
    115         });
     172                final TreeNode parentTreeNode = (TreeNode) child.getParent().getUserObject();
     173                if (parentTreeNode == null) {
     174                        Dispatching.invokeDispatch(this, manager, new Runnable() {
     175                                @Override
     176                                public void run() {
     177                                        createTreeNodeForChild(child);
     178                                }
     179                        });
     180                        return;
     181                }
     182                log.debug(child.getClass().getSimpleName() + " created: " + child);
     183
     184
     185                invokeLater(new Runnable() {
     186                        @Override
     187                        public void run() {
     188                                parentTreeNode.getOrCreateChildTreeNodeFor(child);
     189                        }
     190                });
    116191*/
    117192        }
    118193
    119194
    120     @Override
    121     protected Endpoint createEndpoint() {
    122         return new BrowserEndpoint();
    123     }
     195        @Override
     196        protected Endpoint createEndpoint() {
     197                return new BrowserEndpoint();
     198        }
     199
     200        @Override
     201        public Dispatcher createDefaultDispatcher() {
     202                return SwingDispatcher.instance;
     203        }
     204
     205        /**
     206         * @return the mainFrame
     207         */
     208        public MainFrame getMainFrame() {
     209                return mainFrame;
     210        }
    124211
    125212}
  • java/main/src/main/java/com/framsticks/gui/BrowserEndpoint.java

    r77 r84  
    99
    1010    public BrowserEndpoint() {
     11       
    1112    }
    1213
  • java/main/src/main/java/com/framsticks/gui/EndpointAtFrame.java

    r77 r84  
    11package com.framsticks.gui;
    22
    3 import java.util.HashMap;
    4 import java.util.Map;
     3import org.apache.log4j.Logger;
     4
     5import com.framsticks.core.Instance;
     6import com.framsticks.core.InstanceListener;
     7import com.framsticks.core.ListChange;
     8import com.framsticks.core.Node;
     9import com.framsticks.core.Path;
     10import com.framsticks.params.CompositeParam;
     11import com.framsticks.params.FramsClass;
     12
     13import java.util.*;
     14
     15import javax.swing.tree.TreePath;
    516
    617/**
    718 * @author Piotr Sniegowski
    819 */
    9 public class EndpointAtFrame {
    10     protected final BrowserEndpoint endpoint;
    11     protected final Frame frame;
    12     protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
     20public class EndpointAtFrame implements InstanceListener {
    1321
    14     public EndpointAtFrame(BrowserEndpoint endpoint, Frame frame) {
    15         this.endpoint = endpoint;
    16         this.frame = frame;
    17     }
     22        private static final Logger log = Logger.getLogger(EndpointAtFrame.class);
    1823
     24        protected final BrowserEndpoint endpoint;
     25        protected final Frame frame;
     26        protected final Instance instance;
     27        protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
     28        protected TreeNode rootTreeNode;
    1929
    20     public BrowserEndpoint getEndpoint() {
    21         return endpoint;
    22     }
     30        public EndpointAtFrame(BrowserEndpoint endpoint, Frame frame) {
     31                this.endpoint = endpoint;
     32                this.frame = frame;
     33                this.instance = endpoint.getInstance();
     34        }
    2335
    24     public Frame getFrame() {
    25         return frame;
    26     }
     36        public BrowserEndpoint getEndpoint() {
     37                return endpoint;
     38        }
    2739
    28     public void registerPanel(Panel panel) {
    29         assert frame.isActive();
    30         knownPanels.put(panel.getClassName(), panel);
    31         frame.cardPanel.add(panel, panel.getFullName());
    32     }
     40        public Frame getFrame() {
     41                return frame;
     42        }
    3343
    34     public Panel findPanel(String className) {
    35         assert frame.isActive();
    36         return (knownPanels.containsKey(className) ? knownPanels.get(className) : null);
    37     }
     44        public void registerPanel(Panel panel) {
     45        }
    3846
    39     public final String getName() {
    40         return endpoint.getName();
    41     }
     47        public Panel findPanel(String accessId) {
     48                assert frame.isActive();
     49                return (knownPanels.containsKey(accessId) ? knownPanels.get(accessId) : null);
     50        }
     51
     52        public final String getName() {
     53                return endpoint.getName();
     54        }
     55
     56        public Panel preparePanel(CompositeParam param, FramsClass framsClass) {
     57                assert frame.isActive();
     58                Panel panel = preparePanelImpl(param, framsClass);
     59                assert panel != null;
     60                String accessId = param.computeAccessId();
     61                panel.uniqueName = accessId + "@" + endpoint.getName();
     62                knownPanels.put(accessId, panel);
     63                frame.cardPanel.add(panel, panel.uniqueName);
     64                log.debug("prepared panel for " + panel);
     65                return panel;
     66        }
     67
     68        protected Panel preparePanelImpl(CompositeParam param, FramsClass framsClass) {
     69                assert frame.isActive();
     70                List<Panel> panels = new ArrayList<Panel>();
     71
     72                Panel.Parameters parameters = new Panel.Parameters(this, param,
     73                                framsClass);
     74                for (PanelProvider pp : frame.browser.panelProviders) {
     75                        Panel p = pp.providePanel(parameters);
     76                        if (p != null) {
     77                                panels.add(p);
     78                        }
     79                }
     80
     81                if (panels.isEmpty()) {
     82                        return new EmptyPanel(parameters);
     83                }
     84                if (panels.size() == 1) {
     85                        return panels.get(0);
     86                }
     87                return new MultiPanel(parameters, panels);
     88
     89        }
     90
     91        @Override
     92        public void onListChange(Path path, ListChange change) {
     93
     94        }
     95
     96        public TreePath getTreePath(Path path, boolean create) {
     97                assert frame.isActive();
     98                TreeNode t = rootTreeNode;
     99                TreePath result = new TreePath(frame.rootNode).pathByAddingChild(rootTreeNode);
     100                List<Node> nodes = path.getNodes();
     101                Iterator<Node> i = nodes.iterator();
     102                i.next();
     103                // Node first = i.next();
     104
     105                // if (!t.path.isResolved()) {
     106                //      t.path = new Path(path.getInstance(), nodes, first);
     107                // }
     108                while (i.hasNext()) {
     109                        Node n = i.next();
     110                        TreeNode r = null;
     111                        for (TreeNode c : t.childrenIterable()) {
     112                                if (c.paramId.equals(n.getParam().getId())) {
     113                                        r = c;
     114                                        break;
     115                                }
     116                        }
     117                        if (r == null) {
     118                                log.debug("missing " + n.getParam().getId() + " in " + t);
     119                                if (!create) {
     120                                        return result;
     121                                }
     122                                Path p = new Path(path.getInstance(), nodes, n);
     123                                log.debug("forced resolution: creating treenode for " + p);
     124                                TreeNode childNode = new TreeNode(EndpointAtFrame.this, p);
     125
     126                                frame.addNode(childNode, t);
     127                                // frame.treeModel.reload();
     128                                // t.add(childNode);
     129                                // frame.treeModel.nodeStructureChanged(t);
     130
     131                                r = childNode;
     132                        } else {
     133                                // if (!r.path.isResolved()) {
     134                                //      r.path = new Path(path.getInstance(), nodes, n);
     135                                // }
     136                        }
     137                        result = result.pathByAddingChild(r);
     138                        t = r;
     139                }
     140                return result;
     141        }
     142
     143        @Override
     144        public void onFetch(final Path path) {
     145                assert instance.isActive();
     146                log.trace("fetched " + path);
     147
     148                frame.invokeLater(new Runnable() {
     149                        @Override
     150                        public void run() {
     151
     152                                TreePath treePath = getTreePath(path, true);
     153                                assert treePath.getPathCount() == path.size() + 1;
     154
     155                                final TreeNode result = (TreeNode) treePath.getLastPathComponent();
     156                                // log.trace("found " + result + " == " + path);
     157                                instance.invokeLater(new Runnable() {
     158                                        @Override
     159                                        public void run() {
     160                                                result.reactForFetchResult(path, null);
     161                                        }
     162                                });
     163                        }
     164                });
     165        }
     166
     167        @Override
     168        public void onRun(Exception e) {
     169
     170        }
     171
     172        @Override
     173        public void onStop(Exception e) {
     174
     175        }
    42176}
  • java/main/src/main/java/com/framsticks/gui/Frame.java

    r78 r84  
    11package com.framsticks.gui;
    22
    3 import com.framsticks.core.Node;
     3import com.framsticks.core.Instance;
    44import com.framsticks.core.Path;
    55import com.framsticks.gui.view.*;
    66import com.framsticks.gui.view.TreeCellRenderer;
    7 import com.framsticks.util.Dispatcher;
     7import com.framsticks.util.dispatching.Dispatcher;
     8import com.framsticks.util.swing.KeyboardModifier;
    89import org.apache.log4j.Logger;
    910
    1011import javax.swing.*;
     12import javax.swing.event.TreeModelEvent;
     13import javax.swing.event.TreeModelListener;
    1114import javax.swing.event.TreeSelectionEvent;
    1215import javax.swing.event.TreeSelectionListener;
    1316import javax.swing.tree.*;
     17
    1418import java.awt.*;
    1519import java.awt.datatransfer.StringSelection;
    16 import java.awt.event.ActionEvent;
    17 import java.awt.event.MouseAdapter;
    18 import java.awt.event.MouseEvent;
     20import java.awt.event.*;
    1921import java.util.HashMap;
    2022import java.util.Map;
     
    2325 * @author Piotr Sniegowski
    2426 */
     27@SuppressWarnings("serial")
    2528public class Frame extends JFrame implements Dispatcher {
    2629
    27     private static final Logger LOGGER = Logger.getLogger(Frame.class.getName());
    28 
    29     protected final Browser browser;
    30 
    31     protected final Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
    32 
    33 
    34     final protected CardLayout cardPanelLayout = new CardLayout();
    35     protected final JPanel cardPanel = new JPanel();
    36 
    37     protected JScrollPane treeScrollPane;
    38     protected JTree tree;
    39     protected DefaultTreeModel treeModel;
    40     protected javax.swing.tree.MutableTreeNode rootNode;
    41     //final Instance instance;
    42     protected JPanel treePanel;
    43     protected  JPopupMenu treePopupMenu;
    44     protected JMenuItem treePopupMenuHeader;
    45 
    46     TreeNode currentlyPoppedTreeNode;
    47     protected JLabel statusBar;
    48     protected JPanel mainPanel;
    49     protected JPanel leftPanel;
    50     protected JPanel normalWorkPanel;
    51     protected CardLayout mainPanelLayout;
    52 
    53     protected final Map<BrowserEndpoint, EndpointAtFrame> endpoints = new HashMap<BrowserEndpoint, EndpointAtFrame>();
    54 
    55     public Frame(String title, Browser browser) {
     30        private static final Logger log = Logger.getLogger(Frame.class.getName());
     31
     32        protected final Browser browser;
     33
     34        protected final Dimension screenDimension = Toolkit.getDefaultToolkit()
     35                        .getScreenSize();
     36
     37        final protected CardLayout cardPanelLayout = new CardLayout();
     38        protected final JPanel cardPanel = new JPanel();
     39
     40        protected JScrollPane treeScrollPane;
     41        protected JTree tree;
     42        protected DefaultTreeModel treeModel;
     43        protected javax.swing.tree.MutableTreeNode rootNode;
     44        //final Instance instance;
     45        protected JPanel treePanel;
     46        protected JPopupMenu treePopupMenu;
     47        protected JMenuItem treePopupMenuHeader;
     48
     49        TreeNode currentlyPoppedTreeNode;
     50        protected JLabel statusBar;
     51        protected JPanel mainPanel;
     52        protected JPanel leftPanel;
     53        protected JPanel normalWorkPanel;
     54        protected CardLayout mainPanelLayout;
     55
     56        protected JMenuBar menuBar;
     57        protected JMenu fileMenu;
     58        protected JMenu editMenu;
     59        protected JMenu viewMenu;
     60        protected JMenu windowMenu;
     61        protected JMenu helpMenu;
     62
     63        protected final Map<BrowserEndpoint, EndpointAtFrame> endpoints = new HashMap<BrowserEndpoint, EndpointAtFrame>();
     64        protected final Map<Instance, EndpointAtFrame> endpointsByInstance = new HashMap<Instance, EndpointAtFrame>();
     65
     66        public Frame(String title, Browser browser) {
    5667                super(title);
    57         this.browser = browser;
    58     }
    59 
    60     public void configure() {
    61 
    62         Container contentPane = this.getContentPane();
    63         contentPane.setLayout(new BorderLayout());
    64 
    65         treePopupMenu = new JPopupMenu("title");
    66         treePopupMenu.setName("popup");
    67         treePopupMenuHeader = new JMenuItem();
    68         treePopupMenuHeader.setForeground(Color.BLUE);
    69         treePopupMenu.add(treePopupMenuHeader);
    70         treePopupMenu.addSeparator();
    71         //TODO: add to favourites
    72         //TODO: remove from favourites
    73         //TODO: open in new window as root
    74         //TODO: refresh
    75         //TODO: open in console
    76 
    77         treePopupMenu.add(new JMenuItem("Refresh"));
    78         treePopupMenu.add(new JMenuItem("Open in new frame as root"));
    79                 addNodeActionToTreePopupMenu("Copy path to clipboard", new NodeAction() {
    80                         @Override
    81                         public void actionPerformed(TreeNode treeNode) {
    82                                 Path path = treeNode.getInstancePath();
    83                                 StringSelection selection = new StringSelection(path.toString());
    84                                 getToolkit().getSystemClipboard().setContents(selection, selection);
    85                         }
    86                 });
    87         //this.add(createMenuItem("Add to favourites", null));
    88         //this.add(createMenuItem("Remove from favourites", null));
    89 
    90         treePanel = new JPanel();
    91         treePanel.setLayout(new BorderLayout());
    92 
    93         treeModel = new DefaultTreeModel(null);
    94 
    95         tree = new JTree(treeModel);
    96         tree.setRootVisible(false);
    97         ToolTipManager.sharedInstance().registerComponent(tree);
    98 
    99         tree.addTreeSelectionListener(new TreeSelectionListener() {
    100             @Override
    101             public void valueChanged(TreeSelectionEvent e) {
    102                 chooseTreeNode(e.getNewLeadSelectionPath());
    103             }
    104         });
    105 
    106         tree.setExpandsSelectedPaths(true);
    107         tree.setEditable(false);
    108         tree.setDoubleBuffered(true);
    109         tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    110         tree.setShowsRootHandles(true);
    111         tree.setRowHeight(26);
    112         tree.setDoubleBuffered(true);
    113         tree.addMouseListener(new MouseAdapter() {
    114             @Override
    115             public void mousePressed(MouseEvent e) {
    116                 assert isActive();
    117                 showPopup(e);
    118             }
    119 
    120             @Override
    121             public void mouseReleased(MouseEvent e) {
    122                 assert isActive();
    123                 showPopup(e);
    124             }
    125         });
    126         tree.setCellRenderer(new TreeCellRenderer());
    127 
    128         treeScrollPane = new JScrollPane(tree);
    129         treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
    130 
    131         treePanel.add(treeScrollPane);
    132 
    133         rootNode = new DefaultMutableTreeNode();
    134         treeModel.setRoot(rootNode);
    135 
    136         normalWorkPanel = new JPanel();
    137         normalWorkPanel.setLayout(new BorderLayout());
    138 
    139         mainPanel = new JPanel();
    140         mainPanelLayout = new CardLayout();
    141         mainPanel.setLayout(mainPanelLayout);
    142         mainPanel.add(normalWorkPanel, "browser");
    143 
    144         contentPane.add(createMenu(), BorderLayout.NORTH);
    145         contentPane.add(mainPanel, BorderLayout.CENTER);
    146         contentPane.add(statusBar, BorderLayout.SOUTH);
    147 
    148         leftPanel = new JPanel();
    149         leftPanel.setLayout(new BorderLayout());
    150         JPanel leftTopPanel = createLeftTopPanel();
    151         if (leftTopPanel != null) {
    152             leftPanel.add(leftTopPanel, BorderLayout.PAGE_START);
    153         }
    154         leftPanel.add(treePanel, BorderLayout.CENTER);
    155         leftPanel.setBackground(Color.WHITE);
    156         leftPanel.setForeground(Color.WHITE);
    157 
    158         JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, cardPanel);
    159         split.setPreferredSize(new Dimension(this.browser.getConfig().getInteger("size.width", 1000), this.browser.getConfig().getInteger("size.height", 500)));
    160         split.setMaximumSize(screenDimension);
    161         split.setOneTouchExpandable(true);
    162         split.setDividerLocation(250);
    163         split.setDividerSize(5);
    164 
    165         normalWorkPanel.add(split);
    166 
    167         //this.setVisible(true);
    168         mainPanelLayout.show(mainPanel, "browser");
    169 
    170         cardPanel.setLayout(cardPanelLayout);
     68                /** this is done to remove the current value label from above the slider,
     69                 * because it cannot put to work properly with floating-point value sliders,
     70                 * nor it can be removed in normal way through JSlider methods  */
     71                UIManager.put("Slider.paintValue", false);
     72                this.browser = browser;
     73                log.debug("creating " + this);
     74        }
     75
     76        public void configure() {
     77
     78                Container contentPane = this.getContentPane();
     79                contentPane.setLayout(new BorderLayout());
     80
     81                treePopupMenu = new JPopupMenu("title");
     82                treePopupMenu.setName("popup");
     83                treePopupMenuHeader = new JMenuItem();
     84                treePopupMenuHeader.setForeground(Color.BLUE);
     85                treePopupMenu.add(treePopupMenuHeader);
     86                treePopupMenu.addSeparator();
     87                //TODO: add to favourites
     88                //TODO: remove from favourites
     89                //TODO: open in new window as root
     90                //TODO: refresh
     91                //TODO: open in console
     92
     93                treePopupMenu.add(new JMenuItem("Refresh"));
     94                treePopupMenu.add(new JMenuItem("Open in new frame as root"));
     95                addNodeActionToTreePopupMenu("Copy path to clipboard",
     96                                new NodeAction() {
     97                                        @Override
     98                                        public void actionPerformed(TreeNode treeNode) {
     99                                                Path path = treeNode.getInstancePath();
     100                                                StringSelection selection = new StringSelection(path
     101                                                                .toString());
     102                                                getToolkit().getSystemClipboard().setContents(
     103                                                                selection, selection);
     104                                        }
     105                                });
     106                //this.add(createMenuItem("Add to favourites", null));
     107                //this.add(createMenuItem("Remove from favourites", null));
     108
     109                treePanel = new JPanel();
     110                treePanel.setLayout(new BorderLayout());
     111
     112                treeModel = new DefaultTreeModel(null);
     113                treeModel.addTreeModelListener(new TreeModelListener() {
     114
     115                        @Override
     116                        public void treeNodesChanged(TreeModelEvent arg0) {
     117                                log.trace("treeNodesChanged: " + arg0);
     118                        }
     119
     120                        @Override
     121                        public void treeNodesInserted(TreeModelEvent arg0) {
     122                                // log.trace("treeNodesInserted: " + arg0);
     123                        }
     124
     125                        @Override
     126                        public void treeNodesRemoved(TreeModelEvent arg0) {
     127                                log.trace("treeNodesRemoved: " + arg0);
     128                        }
     129
     130                        @Override
     131                        public void treeStructureChanged(TreeModelEvent arg0) {
     132                                log.trace("treeStructureChanged: " + arg0);
     133                        }
     134                });
     135
     136                tree = new JTree(treeModel);
     137                tree.setName("tree");
     138                tree.setRootVisible(false);
     139                tree.setExpandsSelectedPaths(true);
     140                tree.setSelectionModel(new DefaultTreeSelectionModel());
     141                ToolTipManager.sharedInstance().registerComponent(tree);
     142
     143                tree.addTreeSelectionListener(new TreeSelectionListener() {
     144                        @Override
     145                        public void valueChanged(TreeSelectionEvent e) {
     146                                chooseTreeNode(e.getNewLeadSelectionPath());
     147                        }
     148                });
     149
     150                tree.setExpandsSelectedPaths(true);
     151                tree.setEditable(false);
     152                tree.setDoubleBuffered(true);
     153                tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
     154                tree.setShowsRootHandles(true);
     155                tree.setRowHeight(26);
     156                tree.setDoubleBuffered(true);
     157                tree.addMouseListener(new MouseAdapter() {
     158                        @Override
     159                        public void mousePressed(MouseEvent e) {
     160                                assert isActive();
     161                                showPopup(e);
     162                        }
     163
     164                        @Override
     165                        public void mouseReleased(MouseEvent e) {
     166                                assert isActive();
     167                                showPopup(e);
     168                        }
     169                });
     170
     171                new KeyboardModifier(tree, JComponent.WHEN_FOCUSED)
     172                        .join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0))
     173                        .join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0))
     174                        .join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0))
     175                        .join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0))
     176                        ;
     177
     178                tree.setCellRenderer(new TreeCellRenderer());
     179
     180                treeScrollPane = new JScrollPane(tree);
     181                treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
     182
     183                treePanel.add(treeScrollPane);
     184
     185                rootNode = new DefaultMutableTreeNode();
     186                rootNode.setUserObject("root");
     187                treeModel.setRoot(rootNode);
     188
     189                normalWorkPanel = new JPanel();
     190                normalWorkPanel.setLayout(new BorderLayout());
     191                normalWorkPanel.setName("browser");
     192
     193                mainPanel = new JPanel();
     194                mainPanel.setName("main");
     195                mainPanelLayout = new CardLayout();
     196                mainPanel.setLayout(mainPanelLayout);
     197                mainPanel.add(normalWorkPanel, "browser");
     198
     199                menuBar = new JMenuBar();
     200
     201                fileMenu = menuBar.add(new JMenu("File"));
     202                editMenu = menuBar.add(new JMenu("Edit"));
     203                viewMenu = menuBar.add(new JMenu("View"));
     204                windowMenu = menuBar.add(new JMenu("Window"));
     205                helpMenu = menuBar.add(new JMenu("Help"));
     206
     207                contentPane.add(menuBar, BorderLayout.NORTH);
     208                contentPane.add(mainPanel, BorderLayout.CENTER);
     209                contentPane.add(statusBar, BorderLayout.SOUTH);
     210
     211                leftPanel = new JPanel();
     212                leftPanel.setLayout(new BorderLayout());
     213                //leftPanel.add(new ViewerTest(), BorderLayout.PAGE_START);
     214//        JPanel leftTopPanel = createLeftTopPanel();
     215//        if (leftTopPanel != null) {
     216//            leftPanel.add(leftTopPanel, BorderLayout.PAGE_START);
     217//        }
     218                leftPanel.add(treePanel, BorderLayout.CENTER);
     219                leftPanel.setBackground(Color.WHITE);
     220                leftPanel.setForeground(Color.WHITE);
     221
     222                cardPanel.setName("card");
     223                JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, cardPanel);
     224                split.setPreferredSize(browser.defaultFrameDimension);
     225                split.setMaximumSize(screenDimension);
     226                split.setOneTouchExpandable(true);
     227                split.setDividerLocation(250);
     228                split.setDividerSize(5);
     229                split.setName("split");
     230
     231