@Override
  protected void mergeChilds(Device prev, Device device, Preferences deviceNode)
      throws BackingStoreException {
    HL7DeviceExtension prevHL7Ext = prev.getDeviceExtension(HL7DeviceExtension.class);
    HL7DeviceExtension hl7Ext = device.getDeviceExtension(HL7DeviceExtension.class);

    if (hl7Ext == null) {
      if (prevHL7Ext != null) deviceNode.node("hl7Application").removeNode();
      return;
    }

    Preferences appsNode = deviceNode.node("hl7Application");
    if (prevHL7Ext != null)
      for (String appName : prevHL7Ext.getHL7ApplicationNames()) {
        if (!hl7Ext.containsHL7Application(appName)) appsNode.node(appName).removeNode();
      }

    List<Connection> devConns = device.listConnections();
    for (HL7Application app : hl7Ext.getHL7Applications()) {
      String appName = app.getApplicationName();
      Preferences appNode = appsNode.node(appName);
      if (prevHL7Ext == null || !prevHL7Ext.containsHL7Application(appName)) {
        storeTo(app, appNode, devConns);
      } else {
        storeDiffs(appNode, prevHL7Ext.getHL7Application(appName), app);
      }
    }
  }
 public Device createHL7Device(
     String name,
     Issuer issuer,
     Code institutionCode,
     String appName,
     String host,
     int port,
     int tlsPort)
     throws Exception {
   Device device = new Device(name);
   HL7DeviceExtension hl7Device = new HL7DeviceExtension();
   device.addDeviceExtension(hl7Device);
   init(device, issuer, institutionCode);
   HL7Application hl7app = new HL7Application(appName);
   hl7Device.addHL7Application(hl7app);
   Connection hl7 = new Connection("hl7", host, port);
   hl7.setProtocol(Connection.Protocol.HL7);
   device.addConnection(hl7);
   hl7app.addConnection(hl7);
   Connection hl7TLS = new Connection("hl7-tls", host, tlsPort);
   hl7TLS.setProtocol(Connection.Protocol.HL7);
   hl7TLS.setTlsCipherSuites(
       Connection.TLS_RSA_WITH_AES_128_CBC_SHA, Connection.TLS_RSA_WITH_3DES_EDE_CBC_SHA);
   device.addConnection(hl7TLS);
   hl7app.addConnection(hl7TLS);
   return device;
 }
  private void loadFrom(HL7Application hl7app, Preferences prefs) {
    hl7app.setAcceptedSendingApplications(
        PreferencesUtils.stringArray(prefs, "hl7AcceptedSendingApplication"));
    hl7app.setAcceptedMessageTypes(PreferencesUtils.stringArray(prefs, "hl7AcceptedMessageType"));
    hl7app.setHL7DefaultCharacterSet(prefs.get("hl7DefaultCharacterSet", null));
    hl7app.setInstalled(PreferencesUtils.booleanValue(prefs.get("dicomInstalled", null)));

    for (PreferencesHL7ConfigurationExtension ext : extensions) ext.loadFrom(hl7app, prefs);
  }
  private void storeTo(HL7Application hl7App, Preferences prefs, List<Connection> devConns) {
    PreferencesUtils.storeNotEmpty(
        prefs, "hl7AcceptedSendingApplication", hl7App.getAcceptedSendingApplications());
    PreferencesUtils.storeNotEmpty(
        prefs, "hl7AcceptedMessageType", hl7App.getAcceptedMessageTypes());
    PreferencesUtils.storeNotNull(
        prefs, "hl7DefaultCharacterSet", hl7App.getHL7DefaultCharacterSet());
    PreferencesUtils.storeNotNull(prefs, "dicomInstalled", hl7App.getInstalled());
    PreferencesUtils.storeConnRefs(prefs, hl7App.getConnections(), devConns);

    for (PreferencesHL7ConfigurationExtension ext : extensions) ext.storeTo(hl7App, prefs);
  }
  @Override
  protected void storeChilds(Device device, Preferences deviceNode) {
    HL7DeviceExtension hl7Ext = device.getDeviceExtension(HL7DeviceExtension.class);
    if (hl7Ext == null) return;

    List<Connection> devConns = device.listConnections();
    Preferences parent = deviceNode.node("hl7Application");
    for (HL7Application hl7App : hl7Ext.getHL7Applications()) {
      Preferences appNode = parent.node(hl7App.getApplicationName());
      storeTo(hl7App, appNode, devConns);
    }
  }
  @Override
  protected void loadChilds(Device device, Preferences deviceNode)
      throws BackingStoreException, ConfigurationException {
    if (!deviceNode.nodeExists("hl7Application")) return;

    HL7DeviceExtension hl7Ext = new HL7DeviceExtension();
    device.addDeviceExtension(hl7Ext);
    List<Connection> devConns = device.listConnections();
    Preferences appsNode = deviceNode.node("hl7Application");
    for (String appName : appsNode.childrenNames()) {
      Preferences appNode = appsNode.node(appName);
      HL7Application hl7app = newHL7Application(appNode);
      loadFrom(hl7app, appNode);
      int n = appNode.getInt("dicomNetworkConnectionReference.#", 0);
      for (int i = 0; i < n; i++) {
        hl7app.addConnection(
            devConns.get(appNode.getInt("dicomNetworkConnectionReference." + (i + 1), 0) - 1));
      }
      hl7Ext.addHL7Application(hl7app);
    }
  }
  private static void addHL7DeviceExtension(Device device, boolean sampleConfig) {
    HL7DeviceExtension ext = new HL7DeviceExtension();
    device.addDeviceExtension(ext);

    HL7Application hl7App = new HL7Application("*");
    ArchiveHL7ApplicationExtension hl7AppExt = new ArchiveHL7ApplicationExtension();
    hl7App.addHL7ApplicationExtension(hl7AppExt);
    hl7App.setAcceptedMessageTypes(HL7_MESSAGE_TYPES);
    hl7App.setHL7DefaultCharacterSet("8859/1");
    ext.addHL7Application(hl7App);

    Connection hl7 = new Connection("hl7", "localhost", 2575);
    hl7.setBindAddress("0.0.0.0");
    hl7.setClientBindAddress("0.0.0.0");
    hl7.setProtocol(Connection.Protocol.HL7);
    device.addConnection(hl7);
    hl7App.addConnection(hl7);

    if (sampleConfig) {
      Connection hl7TLS = new Connection("hl7-tls", "localhost", 12575);
      hl7TLS.setBindAddress("0.0.0.0");
      hl7TLS.setClientBindAddress("0.0.0.0");
      hl7TLS.setProtocol(Connection.Protocol.HL7);
      hl7TLS.setTlsCipherSuites(
          Connection.TLS_RSA_WITH_AES_128_CBC_SHA, Connection.TLS_RSA_WITH_3DES_EDE_CBC_SHA);
      device.addConnection(hl7TLS);
      hl7App.addConnection(hl7TLS);
    }
  }
  private void storeDiffs(Preferences prefs, HL7Application a, HL7Application b) {
    PreferencesUtils.storeDiffConnRefs(
        prefs,
        a.getConnections(),
        a.getDevice().listConnections(),
        b.getConnections(),
        b.getDevice().listConnections());
    PreferencesUtils.storeDiff(
        prefs,
        "hl7AcceptedSendingApplication",
        a.getAcceptedSendingApplications(),
        b.getAcceptedSendingApplications());
    PreferencesUtils.storeDiff(
        prefs, "hl7AcceptedMessageType", a.getAcceptedMessageTypes(), b.getAcceptedMessageTypes());
    PreferencesUtils.storeDiff(
        prefs,
        "hl7DefaultCharacterSet",
        a.getHL7DefaultCharacterSet(),
        b.getHL7DefaultCharacterSet());
    PreferencesUtils.storeDiff(prefs, "dicomInstalled", a.getInstalled(), b.getInstalled());

    for (PreferencesHL7ConfigurationExtension ext : extensions) ext.storeDiffs(a, b, prefs);
  }