## Appendix A. How to adapt an existing "`.xxe`" configuration file to XXEW

Like XXE, the desktop app, `xxeserver` scans the `XXEW_install_dir/addon/` and, if `xxeserver` option `-userprefs` has been specified, `XXE_user_preferences_dir/addon/` add-ons directories during its startup and load configurations from there.
Unlike XXE, `xxeserver` automatically skips certain configuration elements (`<binding>` s other than keyboard bindings, `<attributeVisibility>` , `<elementVisibility>` , `<documentSetFactory>` ), certain configuration files ("MathML support", "XMLmind XML Editor Configuration Pack", etc) and certain add-on categories ("spell checker dictionaries", "spell checker plug-ins", "XSL-FO processor plug-ins", etc) because these are either not useful in the context of XXEW or because these are not yet supported by XXEW. Moreover, XXE features are not enabled in `xxeserver`. For example, the `ConvertDocument` feature is not enabled, therefore `<xxe-client>` has no "Convert Document" submenu.

| ##### Restriction There is currently no way to force a running `xxeserver` to reload one or all of its configurations.

Therefore you can very easily make XXEW reuse existing configurations created for XXE or if you want to create a configuration for XXEW, simply follow the instructions which apply to XXE .
There is one big restriction though: interactive commands, that is, commands written in Java™ displaying Java dialog boxes, won't work in XXEW.

| ##### Note What happens in `<xxe-client>` if the user invokes a interactive Java command which has not yet been “ported” to JavaScript™? Not much. If the command is found in a menu or toolbar, the corresponding menu item/toolbar button will generally be disabled and the user will not be able to invoke the command. At worse, if the user manages to invoke the command, the command will do nothing at all.

Fortunately there is a simple way to mark parts of a configuration file as being specific to XXEW or, on the contrary, as being specific to XXE. This way some configuration elements are used only when the file is loaded by `xxeserver` and other configuration elements are used only when the file is loaded by the desktop app.

### Conditional processing of configuration files

It's strongly recommended to use the following processing-instructions to mark parts of a configuration file as being specific to XXEW or, on the contrary, as being specific to XXE:

    <?if TEST?>
    ...configuration elements...
    <?else?>
    ...configuration elements...
    <?endif?>

- `TEST` is `XXE_CLIENT` for configuration elements which are specific to XXEW and `!XXE_CLIENT` for configuration elements which are specific to XXE.
- The `<?else?>` directive is optional.

Use this facility to mark

- interactive command declarations,
- macro command definitions invoking interactive commands,
- menu items, toolbar buttons, bindings invoking interactive commands,
- and more generally any functionality which is not useful in the context of XXEW

as being specific to XXE.
DocBook examples (excerpts from `XXEW_install_dir/addon/config/docbook/docbook.xxe`):

    <?if !XXE_CLIENT?>
    ...
    <command name="docb.editImageMap">
      <class>com.xmlmind.xmleditext.docbook.EditImageMap</class>
    </command>
    <?endif?>

    <command name="{docb}setLinkEnd">
      <macro>
        <sequence>
          <test context="$implicitElement" expression="is-editable()" />

          <set variable="selectedElement" context="$implicitElement"
               expression="(ancestor-or-self::*[@%0])[last()]" />

          <?if XXE_CLIENT?>
          <command name="stop"
                   parameter="xxeClientExecuteCommand editAttributes %0" />
          <?else?>
          <command name="putAttribute" parameter="%0" />
          <?endif?>
        </sequence>
      </macro>
    </command>

    <menu label="_DocBook">
      <?if !XXE_CLIENT?>
      <item label="Upgrade to DocBook _version 5..."
            command="docb.toV5"/>
      <separator/>
      <item label="_Set up olinks..."
            command="docb.olinkedDocuments"/>
      <separator/>
      <?endif?>
      ...
    </menu>

### Adapting an interactive macro to XXEW

In some cases, a menu command or a macro command ending with an interactive command can be easily ported to XXEW by the means of the `stop` command.
The `stop` command is specific to XXEW and does not exist in XXE. It's a very simple command which stops the execution of the macro and returns to its invoker a `STOPPED` status and its parameter as the result of the command.
In the above `{docb}setLinkEnd` macro, "`putAttribute attribute_name`", which is an interactive Java command, has been replaced by "`stop xxeClientExecuteCommand editAttributes attribute_name`".
By convention, when `<xxe-client>` invokes a remote command (here it's `{docb}setLinkEnd`) and this command stops and returns a result which starts with "`xxeClientExecuteCommand`", then `<xxe-client>` invokes the command specified in this result.
In above example, `editAttributes` is an interactive command written in JavaScript which is the XXEW equivalent of interactive Java command `editAttributes` .
Other DocBook example:

    <command name="{docb}linkMenuItems2">
      <menu>
        <?if !XXE_CLIENT?>
        <item label="Follow Link"
              command="start" parameter="helper(defaultViewer) '%*'" />
        <?else?>
        <item label="Follow Link" command="stop"
              parameter="xxeClientExecuteCommand openExternalLink %*" />
        <?endif?>
        <item label="Set Link Target..."
              command="{docb}setLinkEnd" parameter="url" />
      </menu>
    </command>

### “Porting” an interactive Java command to XXEW

Reading the following section should give you an idea on how difficult it is to “port” an interactive Java command to XXEW. It's by no mean a detailed, step by step, tutorial.
Let's use DocBook command `LinkCallouts` as an example. This interactive Java command, found in the DocBook menu , links a sequence of `<callout>` elements to the corresponding sequence of `<co>` or `<area>` elements (and, of course, also the other way round).
First of all, the server-side, interactive Java command must be made “portable” to XXEW. This is the case of `LinkCallouts` because:

- The command may be used interactively as well as non-interactively.
  When passed an ID prefix as its parameter, `LinkCallouts` does its work and modify the document being edited without having to display its Java dialog box.

  #### Figure A-1. The Java dialog box displayed by command `LinkCallouts` when used interactively

- The command can be executed on computers having no display (typically when the command is invoked by `xxeserver`(1)).
  `LinkCallouts` tests whether it can display its Java dialog box. When displaying a dialog box is needed and this is not possible, instead of just failing, `LinkCallouts` returns a `STOPPED` status and the result of the command contains all the information needed to populate the dialog box it would have displayed.

      Component dialogParent = docView.getDialogParent();
      ...
      if (dialogParent == null) {
          // Cannot prompt user.
          return CommandResult.stopped (stoppedValue(
              prefix, discardExistingXRefs, lockDiscardExistingXRefs));
      } else {
          // Prompt user for an ID prefix.
          PrefixDialog dialog = new PrefixDialog(dialogParent);
          Object[] result = dialog.getPrefix(prefix, discardExistingXRefs,
                                             lockDiscardExistingXRefs);
          if (result == null) {
              return CommandResult.CANCELED;
          }
          ...

The second effort consists in implementing a client-side, interactive JavaScript command, displaying a dialog box written in HTML+CSS+JavaScript, having the same registered command name as its Java counterpart.
This client-side command is implemented by JavaScript class `LinkCalloutsCmd` and it is declared to `<xxe-client>` as being `docb.linkCallouts` (for use by DocBook 4 documents) and `db5.linkCallouts` (for use by DocBook 5+ documents). Excerpts from `XXEW_install_dir/web/webapp/xxeclient/docbook.js`:

    class LinkCalloutsCmd extends XXE.InteractiveRemoteCommand {
        constructor(commandName) {
            super(commandName);
        }

        resumeExecution(mode, docView, params,
                        stoppedCommandInfo, resolve, reject) {
            // stoppedCommandInfo syntax is:
            // 'discard'|'keep' [ '!' ] [ ';' prefix ]

        ...
    }

    for (let n of [ "docb.linkCallouts", "db5.linkCallouts" ]) {
        XXE.ALL_LOCAL_COMMANDS[n] = new LinkCalloutsCmd(n);
    }

Like all `XXE.InteractiveRemoteCommand` s, `LinkCalloutsCmd` functions as follows:

1. It invokes the remote, that is, server-side, Java, command having the same name (e.g. `docb.linkCallouts`, implemented by Java class `LinkCallouts`) without any parameter.
2. After receiving the result of the remote command (in method `resumeExecution()`), normally a `STOPPED` status and a result value containing all the information needed to populate a dialog box (an ID prefix, if any, and other settings in the case of `docb.linkCallouts`), `LinkCalloutsCmd` displays its HTML+CSS+JavaScript dialog box.

   #### Figure A-2. The HTML+CSS+JavaScript dialog box displayed by command `LinkCalloutsCmd`

3. Unless the user cancels this dialog box, `LinkCalloutsCmd` invokes one more time remote command `docb.linkCallouts`, but this time with a parameter containing the ID prefix and the other settings specified by the user in the dialog box.
4. Remote command `docb.linkCallouts` having all needed information to do its job, modifies the document accordingly and returns an `DONE` result, which is returned as is as the result of `LinkCalloutsCmd`.

### Related information

‣ Part I, Chapter 2. How it works

(1) | `xxeserver` is designed to run on computers having no display hence `xxeserver` is started with `-Djava.awt.headless=true`.