Esempio n. 1
0
 /**
  * Return filename from a "title" string, ala selection in matchingComboBox.
  *
  * @param title The title for the entry.
  * @return The filename for the RosterEntry matching title, or null if no such RosterEntry exists.
  */
 public String fileFromTitle(String title) {
   RosterEntry r = entryFromTitle(title);
   if (r != null) {
     return r.getFileName();
   }
   return null;
 }
Esempio n. 2
0
  /** Rebuild the Roster index and store it. */
  public void reindex() {
    Roster roster = new Roster();
    for (String fileName : Roster.getAllFileNames()) {
      // Read file
      try {
        Element loco =
            (new LocoFile())
                .rootFromName(LocoFile.getFileLocation() + fileName)
                .getChild("locomotive");
        if (loco != null) {
          RosterEntry re = new RosterEntry(loco);
          re.setFileName(fileName);
          roster.addEntry(re);
        }
      } catch (JDOMException | IOException ex) {
        log.error("Exception while loading loco XML file: {} execption: {}", fileName, ex);
      }
    }

    this.makeBackupFile(this.getRosterIndexPath());
    try {
      roster.writeFile(this.getRosterIndexPath());
    } catch (IOException ex) {
      log.error("Exception while writing the new roster file, may not be complete: {}", ex);
    }
    this.reloadRosterFile();
    log.info("Roster rebuilt, stored in {}", this.getRosterIndexPath());
  }
Esempio n. 3
0
  public void actionPerformed(ActionEvent e) {
    // obtain a HardcopyWriter to do this
    Roster r = Roster.instance();
    String title = "DecoderPro Roster";
    String rosterGroup = r.getDefaultRosterGroup();
    // rosterGroup may legitimately be null
    // but getProperty returns null if the property cannot be found, so
    // we test that the property exists before attempting to get its value
    if (Beans.hasProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP)) {
      rosterGroup = (String) Beans.getProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP);
    }
    if (rosterGroup == null) {
      title = title + " All Entries";
    } else {
      title = title + " Group " + rosterGroup + " Entires";
    }
    HardcopyWriter writer = null;
    try {
      writer = new HardcopyWriter(mFrame, title, 10, .5, .5, .5, .5, isPreview);
    } catch (HardcopyWriter.PrintCanceledException ex) {
      log.debug("Print cancelled");
      return;
    }

    // add the image
    ImageIcon icon =
        new ImageIcon(FileUtil.findURL("resources/decoderpro.gif", FileUtil.Location.INSTALLED));
    // we use an ImageIcon because it's guaranteed to have been loaded when ctor is complete
    writer.write(icon.getImage(), new JLabel(icon));
    // Add a number of blank lines, so that the roster entry starts below the decoderpro logo
    int height = icon.getImage().getHeight(null);
    int blanks = (height - writer.getLineAscent()) / writer.getLineHeight();

    try {
      for (int i = 0; i < blanks; i++) {
        String s = "\n";
        writer.write(s, 0, s.length());
      }
    } catch (IOException ex) {
      log.warn("error during printing: " + ex);
    }

    // Loop through the Roster, printing as needed
    List<RosterEntry> l = r.matchingList(null, null, null, null, null, null, null); // take all
    log.debug("Roster list size: " + l.size());
    for (RosterEntry re : l) {
      if (rosterGroup != null) {
        if (re.getAttribute(Roster.getRosterGroupProperty(rosterGroup)) != null
            && re.getAttribute(Roster.getRosterGroupProperty(rosterGroup)).equals("yes")) {
          re.printEntry(writer);
        }
      } else {
        re.printEntry(writer);
      }
    }

    // and force completion of the printing
    writer.close();
  }
Esempio n. 4
0
 /**
  * Return RosterEntry from a "id" string.
  *
  * @param id The id for the RosterEntry.
  * @return The matching RosterEntry or null
  */
 public RosterEntry getEntryForId(String id) {
   for (RosterEntry re : _list) {
     if (re.getId().equals(id)) {
       return re;
     }
   }
   return null;
 }
Esempio n. 5
0
 /**
  * Return RosterEntry from a "title" string, ala selection in matchingComboBox.
  *
  * @param title The title for the RosterEntry.
  * @return The matching RosterEntry or null
  */
 public RosterEntry entryFromTitle(String title) {
   for (RosterEntry re : _list) {
     if (re.titleString().equals(title)) {
       return re;
     }
   }
   return null;
 }
Esempio n. 6
0
 public Set<String> getAllAttributeKeys() {
   // slow but effective algorithm
   Set<String> result = new TreeSet<>();
   java.util.Iterator<RosterEntry> i = _list.iterator();
   while (i.hasNext()) {
     RosterEntry r = i.next();
     result.addAll(r.getAttributes());
   }
   return result;
 }
Esempio n. 7
0
 public List<RosterEntry> getEntriesWithAttributeKey(String key) {
   // slow but effective algorithm
   ArrayList<RosterEntry> result = new ArrayList<>();
   java.util.Iterator<RosterEntry> i = _list.iterator();
   while (i.hasNext()) {
     RosterEntry r = i.next();
     if (r.getAttribute(key) != null) {
       result.add(r);
     }
   }
   return result;
 }
Esempio n. 8
0
 /**
  * Remove a RosterEntry object from the in-memory Roster. This does not delete the file for the
  * RosterEntry!
  *
  * @param e Entry to remove
  */
 public void removeEntry(RosterEntry e) {
   log.debug("Remove entry {}", e);
   _list.remove(e);
   e.removePropertyChangeListener(this);
   setDirty(true);
   firePropertyChange(REMOVE, e, null);
 }
Esempio n. 9
0
 /**
  * Add a RosterEntry object to the in-memory Roster.
  *
  * @param e Entry to add
  */
 public void addEntry(RosterEntry e) {
   if (log.isDebugEnabled()) {
     log.debug("Add entry " + e);
   }
   int i = _list.size() - 1; // Last valid index
   while (i >= 0) {
     if (e.getId().compareToIgnoreCase(_list.get(i).getId()) > 0) {
       break; // I can never remember whether I want break or continue here
     }
     i--;
   }
   _list.add(i + 1, e);
   e.addPropertyChangeListener(this);
   this.addRosterGroups(e.getGroups(this));
   setDirty(true);
   firePropertyChange(ADD, null, e);
 }
Esempio n. 10
0
 public int getGroupIndex(String group, RosterEntry re) {
   List<RosterEntry> l = matchingList(null, null, null, null, null, null, null);
   int num = 0;
   for (RosterEntry r : l) {
     if (group != null) {
       if ((r.getAttribute(getRosterGroupProperty(group)) != null)
           && r.getAttribute(getRosterGroupProperty(group)).equals("yes")) { // NOI18N
         if (r == re) {
           return num;
         }
         num++;
       }
     } else {
       if (re == r) {
         return num;
       }
       num++;
     }
   }
   return -1;
 }
Esempio n. 11
0
 /**
  * Get the Nth RosterEntry in the group
  *
  * @param group The group being queried.
  * @param i The index within the group of the requested entry.
  * @return The specified entry in the group or null if i is larger than the group, or the group
  *     does not exist.
  */
 public RosterEntry getGroupEntry(String group, int i) {
   List<RosterEntry> l = matchingList(null, null, null, null, null, null, null);
   int num = 0;
   for (RosterEntry r : l) {
     if (group != null) {
       if ((r.getAttribute(getRosterGroupProperty(group)) != null)
           && r.getAttribute(getRosterGroupProperty(group)).equals("yes")) { // NOI18N
         if (num == i) {
           return r;
         }
         num++;
       }
     } else {
       if (num == i) {
         return r;
       }
       num++;
     }
   }
   return null;
 }
Esempio n. 12
0
  /**
   * Check if an entry is consistent with specific properties.
   *
   * <p>A null String argument always matches. Strings are used for convenience in GUI building.
   *
   * @param r the roster entry being checked
   * @param roadName road name of entry or null for any road name
   * @param roadNumber road number of entry of null for any number
   * @param dccAddress address of entry or null for any address
   * @param mfg manufacturer of entry or null for any manufacturer
   * @param decoderModel decoder model of entry or null for any model
   * @param decoderFamily decoder family of entry or null for any family
   * @param id id of entry or null for any id
   * @param group group entry is member of or null for any group
   * @return True if the entry matches
   */
  public boolean checkEntry(
      RosterEntry r,
      String roadName,
      String roadNumber,
      String dccAddress,
      String mfg,
      String decoderModel,
      String decoderFamily,
      String id,
      String group) {

    if (id != null && !id.equals(r.getId())) {
      return false;
    }
    if (roadName != null && !roadName.equals(r.getRoadName())) {
      return false;
    }
    if (roadNumber != null && !roadNumber.equals(r.getRoadNumber())) {
      return false;
    }
    if (dccAddress != null && !dccAddress.equals(r.getDccAddress())) {
      return false;
    }
    if (mfg != null && !mfg.equals(r.getMfg())) {
      return false;
    }
    if (decoderModel != null && !decoderModel.equals(r.getDecoderModel())) {
      return false;
    }
    if (decoderFamily != null && !decoderFamily.equals(r.getDecoderFamily())) {
      return false;
    }
    if (group != null
        && !Roster.ALLENTRIES.equals(group)
        && (r.getAttribute(Roster.getRosterGroupProperty(group)) == null
            || !r.getAttribute(Roster.getRosterGroupProperty(group)).equals("yes"))) { // NOI18N
      return false;
    }
    return true;
  }
  @Override
  public void actionPerformed(ActionEvent event) {

    Roster roster = Roster.instance();
    String rosterGroup = Roster.instance().getDefaultRosterGroup();
    RosterEntry[] entries;
    // rosterGroup may legitimately be null
    // but getProperty returns null if the property cannot be found, so
    // we test that the property exists before attempting to get its value
    if (Beans.hasProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP)) {
      rosterGroup = (String) Beans.getProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP);
      log.debug("selectedRosterGroup was {}", rosterGroup);
    }
    if (Beans.hasProperty(wi, "selectedRosterEntries")) {
      entries = (RosterEntry[]) Beans.getProperty(wi, "selectedRosterEntries");
      if (entries != null) {
        log.debug("selectedRosterEntries found {} entries", entries.length);
      } else {
        log.debug("selectedRosterEntries left entries null");
      }
    } else {
      entries = selectRosterEntry(rosterGroup);
      if (entries != null) {
        log.debug("selectRosterEntry(rosterGroup) found {} entries", entries.length);
      } else {
        log.debug("selectRosterEntry(rosterGroup) left entries null");
      }
    }
    if (entries == null) {
      return;
    }
    // get parent object if there is one
    // Component parent = null;
    // if ( event.getSource() instanceof Component) parent = (Component)event.getSource();

    // find the file for the selected entry
    for (RosterEntry re : entries) {
      String filename = roster.fileFromTitle(re.titleString());
      String fullFilename = LocoFile.getFileLocation() + filename;
      log.debug("resolves to [{}], [{}]", filename, fullFilename);

      // prompt for one last chance
      log.debug("rosterGroup now {}", rosterGroup);
      if (rosterGroup == null) {
        if (!userOK(re.titleString(), filename, fullFilename)) {
          return;
        }
        // delete it from roster
        roster.removeEntry(re);
      } else {
        String group = Roster.getRosterGroupProperty(rosterGroup);
        log.debug("removing {} group from entry", group);
        re.deleteAttribute(group);
        re.updateFile();
      }
      Roster.writeRosterFile();

      // backup the file & delete it
      if (rosterGroup == null) {
        try {
          // ensure preferences will be found
          FileUtil.createDirectory(LocoFile.getFileLocation());

          // move original file to backup
          LocoFile df = new LocoFile(); // need a dummy object to do this operation in next line
          df.makeBackupFile(LocoFile.getFileLocation() + filename);

        } catch (Exception ex) {
          log.error("error during locomotive file output: " + ex);
        }
      }
    }
  }
 public Builder player(Map<String, String> values) {
   this.players.add(RosterEntry.of(values));
   return this;
 }
Esempio n. 15
0
  /**
   * Read the contents of a roster XML file into this object.
   *
   * <p>Note that this does not clear any existing entries.
   *
   * @param name filename of roster file
   */
  void readFile(String name) throws org.jdom2.JDOMException, java.io.IOException {
    // roster exists?
    if (!(new File(name)).exists()) {
      log.debug(
          "no roster file found; this is normal if you haven't put decoders in your roster yet");
      return;
    }

    // find root
    Element root = rootFromName(name);
    if (root == null) {
      log.error("Roster file exists, but could not be read; roster not available");
      return;
    }
    // if (log.isDebugEnabled()) XmlFile.dumpElement(root);

    // decode type, invoke proper processing routine if a decoder file
    if (root.getChild("roster") != null) { // NOI18N
      List<Element> l = root.getChild("roster").getChildren("locomotive"); // NOI18N
      if (log.isDebugEnabled()) {
        log.debug("readFile sees " + l.size() + " children");
      }
      l.stream()
          .forEach(
              (e) -> {
                addEntry(new RosterEntry(e));
              });

      // Scan the object to check the Comment and Decoder Comment fields for
      // any <?p?> processor directives and change them to back \n characters
      for (int i = 0; i < numEntries(); i++) {
        // Get a RosterEntry object for this index
        RosterEntry r = _list.get(i);

        // Extract the Comment field and create a new string for output
        String tempComment = r.getComment();
        String xmlComment = "";

        // transfer tempComment to xmlComment one character at a time, except
        // when <?p?> is found.  In that case, insert a \n and skip over those
        // characters in tempComment.
        for (int k = 0; k < tempComment.length(); k++) {
          if (tempComment.startsWith("<?p?>", k)) { // NOI18N
            xmlComment = xmlComment + "\n"; // NOI18N
            k = k + 4;
          } else {
            xmlComment = xmlComment + tempComment.substring(k, k + 1);
          }
        }
        r.setComment(xmlComment);

        // Now do the same thing for the decoderComment field
        String tempDecoderComment = r.getDecoderComment();
        String xmlDecoderComment = "";

        for (int k = 0; k < tempDecoderComment.length(); k++) {
          if (tempDecoderComment.startsWith("<?p?>", k)) { // NOI18N
            xmlDecoderComment = xmlDecoderComment + "\n"; // NOI18N
            k = k + 4;
          } else {
            xmlDecoderComment = xmlDecoderComment + tempDecoderComment.substring(k, k + 1);
          }
        }

        r.setDecoderComment(xmlDecoderComment);
      }
    } else {
      log.error("Unrecognized roster file contents in file: " + name);
    }
    if (root.getChild("rosterGroup") != null) { // NOI18N
      List<Element> groups = root.getChild("rosterGroup").getChildren("group"); // NOI18N
      groups
          .stream()
          .forEach(
              (group) -> {
                addRosterGroup(group.getText());
              });
    }
  }
Esempio n. 16
0
  /**
   * Write the entire roster to a file object. This does not do backup; that has to be done
   * separately. See writeRosterFile() for a public function that finds the default location, does a
   * backup and then calls this.
   *
   * @param file an op
   */
  void writeFile(File file) throws java.io.IOException {
    // create root element
    Element root = new Element("roster-config"); // NOI18N
    root.setAttribute(
        "noNamespaceSchemaLocation", // NOI18N
        "http://jmri.org/xml/schema/roster" + schemaVersion + ".xsd", // NOI18N
        org.jdom2.Namespace.getNamespace(
            "xsi", // NOI18N
            "http://www.w3.org/2001/XMLSchema-instance")); // NOI18N
    Document doc = newDocument(root);

    // add XSLT processing instruction
    // <?xml-stylesheet type="text/xsl" href="XSLT/roster.xsl"?>
    java.util.Map<String, String> m = new java.util.HashMap<>();
    m.put("type", "text/xsl"); // NOI18N
    m.put("href", xsltLocation + "roster2array.xsl"); // NOI18N
    ProcessingInstruction p = new ProcessingInstruction("xml-stylesheet", m); // NOI18N
    doc.addContent(0, p);

    String newLocoString = SymbolicProgBundle.getMessage("LabelNewDecoder");

    // Check the Comment and Decoder Comment fields for line breaks and
    // convert them to a processor directive for storage in XML
    // Note: this is also done in the LocoFile.java class to do
    // the same thing in the indidvidual locomotive roster files
    // Note: these changes have to be undone after writing the file
    // since the memory version of the roster is being changed to the
    // file version for writing
    for (int i = 0; i < numEntries(); i++) {

      // Extract the RosterEntry at this index and inspect the Comment and
      // Decoder Comment fields to change any \n characters to <?p?> processor
      // directives so they can be stored in the xml file and converted
      // back when the file is read.
      RosterEntry r = _list.get(i);
      if (!r.getId().equals(newLocoString)) {
        String tempComment = r.getComment();
        String xmlComment = "";

        // transfer tempComment to xmlComment one character at a time, except
        // when \n is found.  In that case, insert <?p?>
        for (int k = 0; k < tempComment.length(); k++) {
          if (tempComment.startsWith("\n", k)) { // NOI18N
            xmlComment = xmlComment + "<?p?>"; // NOI18N
          } else {
            xmlComment = xmlComment + tempComment.substring(k, k + 1);
          }
        }
        r.setComment(xmlComment);

        // Now do the same thing for the decoderComment field
        String tempDecoderComment = r.getDecoderComment();
        String xmlDecoderComment = "";

        for (int k = 0; k < tempDecoderComment.length(); k++) {
          if (tempDecoderComment.startsWith("\n", k)) { // NOI18N
            xmlDecoderComment = xmlDecoderComment + "<?p?>"; // NOI18N
          } else {
            xmlDecoderComment = xmlDecoderComment + tempDecoderComment.substring(k, k + 1);
          }
        }
        r.setDecoderComment(xmlDecoderComment);
      } else {
        log.debug("skip unsaved roster entry with default name " + r.getId());
      }
    }
    // All Comments and Decoder Comment line feeds have been changed to processor directives

    // add top-level elements
    Element values = new Element("roster"); // NOI18N
    root.addContent(values);
    // add entries
    for (int i = 0; i < numEntries(); i++) {
      if (!_list.get(i).getId().equals(newLocoString)) {
        values.addContent(_list.get(i).store());
      } else {
        log.debug("skip unsaved roster entry with default name " + _list.get(i).getId());
      }
    }

    if (!this.rosterGroups.isEmpty()) {
      Element rosterGroup = new Element("rosterGroup"); // NOI18N
      rosterGroups
          .keySet()
          .stream()
          .forEach(
              (name) -> {
                Element group = new Element("group"); // NOI18N
                if (!name.equals(Roster.ALLENTRIES)) {
                  group.addContent(name);
                  rosterGroup.addContent(group);
                }
              });
      root.addContent(rosterGroup);
    }

    writeXML(file, doc);

    // Now that the roster has been rewritten in file form we need to
    // restore the RosterEntry object to its normal \n state for the
    // Comment and Decoder comment fields, otherwise it can cause problems in
    // other parts of the program (e.g. in copying a roster)
    for (int i = 0; i < numEntries(); i++) {
      RosterEntry r = _list.get(i);
      if (!r.getId().equals(newLocoString)) {
        String xmlComment = r.getComment();
        String tempComment = "";

        for (int k = 0; k < xmlComment.length(); k++) {
          if (xmlComment.startsWith("<?p?>", k)) { // NOI18N
            tempComment = tempComment + "\n"; // NOI18N
            k = k + 4;
          } else {
            tempComment = tempComment + xmlComment.substring(k, k + 1);
          }
        }
        r.setComment(tempComment);

        String xmlDecoderComment = r.getDecoderComment();
        String tempDecoderComment = ""; // NOI18N

        for (int k = 0; k < xmlDecoderComment.length(); k++) {
          if (xmlDecoderComment.startsWith("<?p?>", k)) { // NOI18N
            tempDecoderComment = tempDecoderComment + "\n"; // NOI18N
            k = k + 4;
          } else {
            tempDecoderComment = tempDecoderComment + xmlDecoderComment.substring(k, k + 1);
          }
        }
        r.setDecoderComment(tempDecoderComment);
      } else {
        log.debug("skip unsaved roster entry with default name " + r.getId());
      }
    }

    // done - roster now stored, so can't be dirty
    setDirty(false);
    firePropertyChange(SAVED, false, true);
  }