Example #1
0
  /**
   * Checks if the two entries represent the same publication.
   *
   * @param one BibEntry
   * @param two BibEntry
   * @return boolean
   */
  public static boolean isDuplicate(BibEntry one, BibEntry two, BibDatabaseMode bibDatabaseMode) {

    // First check if they are of the same type - a necessary condition:
    if (!one.getType().equals(two.getType())) {
      return false;
    }
    EntryType type = EntryTypes.getTypeOrDefault(one.getType(), bibDatabaseMode);

    // The check if they have the same required fields:
    java.util.List<String> var = type.getRequiredFieldsFlat();
    String[] fields = var.toArray(new String[var.size()]);
    double[] req;
    if (fields == null) {
      req = new double[] {0., 0.};
    } else {
      req = DuplicateCheck.compareFieldSet(fields, one, two);
    }

    if (Math.abs(req[0] - DuplicateCheck.duplicateThreshold) > DuplicateCheck.DOUBT_RANGE) {
      // Far from the threshold value, so we base our decision on the req. fields only
      return req[0] >= DuplicateCheck.duplicateThreshold;
    }
    // Close to the threshold value, so we take a look at the optional fields, if any:
    java.util.List<String> optionalFields = type.getOptionalFields();
    fields = optionalFields.toArray(new String[optionalFields.size()]);
    if (fields != null) {
      double[] opt = DuplicateCheck.compareFieldSet(fields, one, two);
      double totValue =
          ((DuplicateCheck.REQUIRED_WEIGHT * req[0] * req[1]) + (opt[0] * opt[1]))
              / ((req[1] * DuplicateCheck.REQUIRED_WEIGHT) + opt[1]);
      return totValue >= DuplicateCheck.duplicateThreshold;
    }
    return req[0] >= DuplicateCheck.duplicateThreshold;
  }
Example #2
0
  private Optional<BibEntry> createNewEntry() {
    // Find out what type is desired
    EntryTypeDialog etd = new EntryTypeDialog(frame);
    // We want to center the dialog, to make it look nicer.
    etd.setLocationRelativeTo(frame);
    etd.setVisible(true);
    EntryType type = etd.getChoice();

    if (type != null) { // Only if the dialog was not canceled.
      String id = IdGenerator.next();
      final BibEntry bibEntry = new BibEntry(id, type.getName());
      try {
        panel.getDatabase().insertEntry(bibEntry);

        // Set owner/timestamp if options are enabled:
        List<BibEntry> list = new ArrayList<>();
        list.add(bibEntry);
        UpdateField.setAutomaticFields(list, true, true, Globals.prefs.getUpdateFieldPreferences());

        // Create an UndoableInsertEntry object.
        panel
            .getUndoManager()
            .addEdit(new UndoableInsertEntry(panel.getDatabase(), bibEntry, panel));
        panel.output(
            Localization.lang("Added new")
                + " '"
                + type.getName().toLowerCase()
                + "' "
                + Localization.lang("entry")
                + ".");

        // We are going to select the new entry. Before that, make sure that we are in
        // show-entry mode. If we aren't already in that mode, enter the WILL_SHOW_EDITOR
        // mode which makes sure the selection will trigger display of the entry editor
        // and adjustment of the splitter.
        if (panel.getMode() != BasePanelMode.SHOWING_EDITOR) {
          panel.setMode(BasePanelMode.WILL_SHOW_EDITOR);
        }

        SwingUtilities.invokeLater(() -> panel.showEntry(bibEntry));

        // The database just changed.
        panel.markBaseChanged();

        return Optional.of(bibEntry);
      } catch (KeyCollisionException ex) {
        LOGGER.info("Key collision occurred", ex);
      }
    }
    return Optional.empty();
  }
  private JTextField addEntryType(Container c, EntryType type, int y) {

    JLabel lab = new JLabel(type.getName());
    con.gridx = 0;
    con.gridy = y;
    con.fill = GridBagConstraints.BOTH;
    con.weightx = 0;
    con.weighty = 0;
    con.anchor = GridBagConstraints.WEST;
    con.insets = new Insets(0, 5, 0, 5);
    gbl.setConstraints(lab, con);
    c.add(lab);

    JTextField tf = new JTextField();
    tf.setColumns(15);
    con.gridx = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 1;
    con.weighty = 0;
    con.anchor = GridBagConstraints.CENTER;
    con.insets = new Insets(0, 5, 0, 5);
    gbl.setConstraints(tf, con);
    c.add(tf);

    JButton but = new JButton(Localization.lang("Default"));
    con.gridx = 2;
    con.fill = GridBagConstraints.BOTH;
    con.weightx = 0;
    con.weighty = 0;
    con.anchor = GridBagConstraints.CENTER;
    con.insets = new Insets(0, 5, 0, 5);
    gbl.setConstraints(but, con);
    but.setActionCommand(type.getName().toLowerCase());
    but.addActionListener(
        e -> {
          JTextField tField = textFields.get(e.getActionCommand());
          tField.setText("");
        });
    c.add(but);

    return tf;
  }
  private void buildGUI() {
    JPanel pan = new JPanel();
    JScrollPane sp = new JScrollPane(pan);
    sp.setPreferredSize(new Dimension(100, 100));
    sp.setBorder(BorderFactory.createEmptyBorder());
    pan.setLayout(gbl);
    setLayout(gbl);
    // The header - can be removed
    JLabel lblEntryType = new JLabel(Localization.lang("Entry type"));
    Font f = new Font("plain", Font.BOLD, 12);
    lblEntryType.setFont(f);
    con.gridx = 0;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.VERTICAL;
    con.anchor = GridBagConstraints.WEST;
    con.insets = new Insets(5, 5, 10, 0);
    gbl.setConstraints(lblEntryType, con);
    pan.add(lblEntryType);

    JLabel lblKeyPattern = new JLabel(Localization.lang("Key pattern"));
    lblKeyPattern.setFont(f);
    con.gridx = 1;
    con.gridy = 0;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.anchor = GridBagConstraints.WEST;
    con.insets = new Insets(5, 5, 10, 5);
    gbl.setConstraints(lblKeyPattern, con);
    pan.add(lblKeyPattern);

    con.gridy = 1;
    con.gridx = 0;
    JLabel lab = new JLabel(Localization.lang("Default pattern"));
    gbl.setConstraints(lab, con);
    pan.add(lab);
    con.gridx = 1;
    gbl.setConstraints(defaultPat, con);
    pan.add(defaultPat);
    con.insets = new Insets(5, 5, 10, 5);
    JButton btnDefault = new JButton(Localization.lang("Default"));
    btnDefault.addActionListener(
        e ->
            defaultPat.setText(
                (String) Globals.prefs.defaults.get(JabRefPreferences.DEFAULT_BIBTEX_KEY_PATTERN)));
    con.gridx = 2;
    int y = 2;
    gbl.setConstraints(btnDefault, con);
    pan.add(btnDefault);

    BibDatabaseMode mode;
    // check mode of currently used DB
    if (panel != null) {
      mode = panel.getBibDatabaseContext().getMode();
    } else {
      // use preferences value if no DB is open
      mode = Globals.prefs.getDefaultBibDatabaseMode();
    }

    for (EntryType type : EntryTypes.getAllValues(mode)) {
      textFields.put(type.getName().toLowerCase(), addEntryType(pan, type, y));
      y++;
    }

    con.fill = GridBagConstraints.BOTH;
    con.gridx = 0;
    con.gridy = 1;
    con.gridwidth = 3;
    con.weightx = 1;
    con.weighty = 1;
    gbl.setConstraints(sp, con);
    add(sp);

    // A help button
    con.gridwidth = 1;
    con.gridx = 1;
    con.gridy = 2;
    con.fill = GridBagConstraints.HORIZONTAL;
    //
    con.weightx = 0;
    con.weighty = 0;
    con.anchor = GridBagConstraints.SOUTHEAST;
    con.insets = new Insets(0, 5, 0, 5);
    JButton hlb = new JButton(IconTheme.JabRefIcon.HELP.getSmallIcon());
    hlb.setToolTipText(Localization.lang("Help on key patterns"));
    gbl.setConstraints(hlb, con);
    add(hlb);
    hlb.addActionListener(help);

    // And finally a button to reset everything
    JButton btnDefaultAll = new JButton(Localization.lang("Reset all"));
    con.gridx = 2;
    con.gridy = 2;

    con.weightx = 1;
    con.weighty = 0;
    con.anchor = GridBagConstraints.SOUTHEAST;
    con.insets = new Insets(20, 5, 0, 5);
    gbl.setConstraints(btnDefaultAll, con);
    btnDefaultAll.addActionListener(
        e -> {
          // reset all fields
          for (JTextField field : textFields.values()) {
            field.setText("");
          }

          // also reset the default pattern
          defaultPat.setText(
              (String) Globals.prefs.defaults.get(JabRefPreferences.DEFAULT_BIBTEX_KEY_PATTERN));
        });
    add(btnDefaultAll);
  }
Example #5
0
  /** Main function for building the merge entry JPanel */
  private void initialize() {

    joint = new TreeSet<>(one.getFieldNames());
    joint.addAll(two.getFieldNames());

    // Remove field starting with __
    TreeSet<String> toberemoved = new TreeSet<>();
    for (String field : joint) {
      if (field.startsWith("__")) {
        toberemoved.add(field);
      }
    }

    for (String field : toberemoved) {
      joint.remove(field);
    }

    // Create storage arrays
    rb = new JRadioButton[3][joint.size() + 1];
    ButtonGroup[] rbg = new ButtonGroup[joint.size() + 1];
    identical = new Boolean[joint.size() + 1];
    jointStrings = new String[joint.size()];

    // Create main layout
    String colSpecMain =
        "left:pref, 5px, center:3cm:grow, 5px, center:pref, 3px, center:pref, 3px, center:pref, 5px, center:3cm:grow";
    String colSpecMerge =
        "left:pref, 5px, fill:3cm:grow, 5px, center:pref, 3px, center:pref, 3px, center:pref, 5px, fill:3cm:grow";
    String rowSpec = "pref, pref, 10px, fill:5cm:grow, 10px, pref, 10px, fill:3cm:grow";
    StringBuilder rowBuilder = new StringBuilder("");
    for (int i = 0; i < joint.size(); i++) {
      rowBuilder.append("pref, ");
    }
    rowBuilder.append("pref");

    FormLayout mainLayout = new FormLayout(colSpecMain, rowSpec);
    FormLayout mergeLayout = new FormLayout(colSpecMerge, rowBuilder.toString());
    mainPanel.setLayout(mainLayout);
    mergePanel.setLayout(mergeLayout);

    JLabel label = new JLabel(Localization.lang("Use"));
    Font font = label.getFont();
    label.setFont(font.deriveFont(font.getStyle() | Font.BOLD));

    mainPanel.add(label, cc.xyw(4, 1, 7, "center, bottom"));

    // Set headings
    JLabel headingLabels[] = new JLabel[6];
    for (int i = 0; i < 6; i++) {
      headingLabels[i] = new JLabel(columnHeadings[i]);
      font = headingLabels[i].getFont();
      headingLabels[i].setFont(font.deriveFont(font.getStyle() | Font.BOLD));
      mainPanel.add(headingLabels[i], cc.xy(1 + (i * 2), 2));
    }

    mainPanel.add(new JSeparator(), cc.xyw(1, 3, 11));

    // Start with entry type
    EntryType type1 = one.getType();
    EntryType type2 = two.getType();

    mergedEntry.setType(type1);
    label = new JLabel(Localization.lang("Entry type"));
    font = label.getFont();
    label.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
    mergePanel.add(label, cc.xy(1, 1));

    JTextArea type1ta = new JTextArea(type1.getName());
    type1ta.setEditable(false);
    mergePanel.add(type1ta, cc.xy(3, 1));
    if (type1.compareTo(type2) != 0) {
      identical[0] = false;
      rbg[0] = new ButtonGroup();
      for (int k = 0; k < 3; k += 2) {
        rb[k][0] = new JRadioButton();
        rbg[0].add(rb[k][0]);
        mergePanel.add(rb[k][0], cc.xy(5 + (k * 2), 1));
        rb[k][0].addChangeListener(
            new ChangeListener() {

              @Override
              public void stateChanged(ChangeEvent e) {
                updateAll();
              }
            });
      }
      rb[0][0].setSelected(true);
    } else {
      identical[0] = true;
    }
    JTextArea type2ta = new JTextArea(type2.getName());
    type2ta.setEditable(false);
    mergePanel.add(type2ta, cc.xy(11, 1));

    // For all fields in joint add a row and possibly radio buttons
    int row = 2;
    int maxLabelWidth = -1;
    int tmpLabelWidth = 0;
    for (String field : joint) {
      jointStrings[row - 2] = field;
      label = new JLabel(CaseChangers.UPPER_FIRST.format(field));
      font = label.getFont();
      label.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
      mergePanel.add(label, cc.xy(1, row));
      String string1 = one.getField(field);
      String string2 = two.getField(field);
      identical[row - 1] = false;
      if ((string1 != null) && (string2 != null)) {
        if (string1.equals(string2)) {
          identical[row - 1] = true;
        }
      }

      tmpLabelWidth = label.getPreferredSize().width;
      if (tmpLabelWidth > maxLabelWidth) {
        maxLabelWidth = tmpLabelWidth;
      }

      if ("abstract".equals(field) || "review".equals(field)) {
        // Treat the abstract and review fields special
        JTextArea tf = new JTextArea();
        tf.setLineWrap(true);
        tf.setEditable(false);
        JScrollPane jsptf = new JScrollPane(tf);

        mergeLayout.setRowSpec(row, RowSpec.decode("center:2cm:grow"));
        mergePanel.add(jsptf, cc.xy(3, row, "f, f"));
        tf.setText(string1);
        tf.setCaretPosition(0);

      } else {
        JTextArea tf = new JTextArea(string1);
        mergePanel.add(tf, cc.xy(3, row));
        tf.setCaretPosition(0);
        tf.setEditable(false);
      }

      // Add radio buttons if the two entries do not have identical fields
      if (!identical[row - 1]) {
        rbg[row - 1] = new ButtonGroup();
        for (int k = 0; k < 3; k++) {
          rb[k][row - 1] = new JRadioButton();
          rbg[row - 1].add(rb[k][row - 1]);
          mergePanel.add(rb[k][row - 1], cc.xy(5 + (k * 2), row));
          rb[k][row - 1].addChangeListener(
              new ChangeListener() {

                @Override
                public void stateChanged(ChangeEvent e) {
                  updateAll();
                }
              });
        }
        if (string1 != null) {
          mergedEntry.setField(field, string1);
          rb[0][row - 1].setSelected(true);
          if (string2 == null) {
            rb[2][row - 1].setEnabled(false);
          }
        } else {
          rb[0][row - 1].setEnabled(false);
          mergedEntry.setField(field, string2);
          rb[2][row - 1].setSelected(true);
        }
      } else {
        mergedEntry.setField(field, string1);
      }
      if ("abstract".equals(field) || "review".equals(field)) {
        // Again, treat abstract and review special
        JTextArea tf = new JTextArea();
        tf.setLineWrap(true);
        tf.setEditable(false);
        JScrollPane jsptf = new JScrollPane(tf);

        mergePanel.add(jsptf, cc.xy(11, row, "f, f"));
        tf.setText(string2);
        tf.setCaretPosition(0);

      } else {
        JTextArea tf = new JTextArea(string2);
        mergePanel.add(tf, cc.xy(11, row));
        tf.setCaretPosition(0);
        tf.setEditable(false);
      }

      row++;
    }

    JScrollPane scrollPane =
        new JScrollPane(
            mergePanel,
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setBorder(BorderFactory.createEmptyBorder());
    mainPanel.add(scrollPane, cc.xyw(1, 4, 11));
    mainPanel.add(new JSeparator(), cc.xyw(1, 5, 11));

    // Synchronize column widths
    String rbAlign[] = {"right", "center", "left"};
    mainLayout.setColumnSpec(1, ColumnSpec.decode(Integer.toString(maxLabelWidth) + "px"));
    Integer maxRBWidth = -1;
    Integer tmpRBWidth;
    for (int k = 0; k < 3; k++) {
      tmpRBWidth = headingLabels[k + 2].getPreferredSize().width;
      if (tmpRBWidth > maxRBWidth) {
        maxRBWidth = tmpRBWidth;
      }
    }
    for (int k = 0; k < 3; k++) {
      mergeLayout.setColumnSpec(
          5 + (k * 2), ColumnSpec.decode(rbAlign[k] + ":" + maxRBWidth + "px"));
    }

    // Setup a PreviewPanel and a Bibtex source box for the merged entry
    label = new JLabel(Localization.lang("Merged entry"));
    font = label.getFont();
    label.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
    mainPanel.add(label, cc.xyw(1, 6, 6));

    String layoutString = Globals.prefs.get(JabRefPreferences.PREVIEW_0);
    pp = new PreviewPanel(null, mergedEntry, null, new MetaData(), layoutString);
    // JScrollPane jsppp = new JScrollPane(pp, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
    // JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    mainPanel.add(pp, cc.xyw(1, 8, 6));

    label = new JLabel(Localization.lang("Merged BibTeX source code"));
    font = label.getFont();
    label.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
    mainPanel.add(label, cc.xyw(8, 6, 4));

    jta = new JTextArea();
    jta.setLineWrap(true);
    JScrollPane jspta = new JScrollPane(jta);
    mainPanel.add(jspta, cc.xyw(8, 8, 4));
    jta.setEditable(false);
    StringWriter sw = new StringWriter();
    try {
      new BibtexEntryWriter(new LatexFieldFormatter(), false).write(mergedEntry, sw);
    } catch (IOException ex) {
      LOGGER.error("Error in entry" + ": " + ex.getMessage(), ex);
    }
    jta.setText(sw.getBuffer().toString());
    jta.setCaretPosition(0);

    // Add some margin around the layout
    mainLayout.appendRow(RowSpec.decode("10px"));
    mainLayout.appendColumn(ColumnSpec.decode("10px"));
    mainLayout.insertRow(1, RowSpec.decode("10px"));
    mainLayout.insertColumn(1, ColumnSpec.decode("10px"));

    if (mainPanel.getHeight() > DIM.height) {
      mainPanel.setSize(new Dimension(mergePanel.getWidth(), DIM.height));
    }
    if (mainPanel.getWidth() > DIM.width) {
      mainPanel.setSize(new Dimension(DIM.width, mergePanel.getHeight()));
    }

    // Everything done, allow any action to actually update the merged entry
    doneBuilding = true;

    // Show what we've got
    mainPanel.setVisible(true);
    javax.swing.SwingUtilities.invokeLater(
        new Runnable() {
          @Override
          public void run() {
            scrollPane.getVerticalScrollBar().setValue(0);
          }
        });
  }
 public ChangeTypeAction(EntryType type, BasePanel bp) {
   super(type.getName());
   this.type = type.getName();
   panel = bp;
 }