Package net.bnubot.bot.gui

Source Code of net.bnubot.bot.gui.DatabaseEditor$getValueDelegate

/**
* This file is distributed under the GPL
* $Id: DatabaseEditor.java 1907 2014-02-12 09:04:56Z scotta $
*/

package net.bnubot.bot.gui;

import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import net.bnubot.bot.gui.components.ConfigFlagChecks;
import net.bnubot.bot.gui.components.ConfigTextField;
import net.bnubot.db.CustomDataObject;
import net.bnubot.db.conf.DatabaseContext;
import net.bnubot.logging.Out;
import net.bnubot.util.TimeFormatter;
import net.bnubot.util.UnloggedException;

import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
import org.apache.cayenne.query.SelectQuery;

/**
* @author scotta
* @param <T> The {@link CustomDataObject} type
* @param <S> The sortable field type of the {@link CustomDataObject}
*/
public class DatabaseEditor<T extends CustomDataObject<S>, S extends Comparable<? super S>> {
  private final ObjectContext context;
  private final String editorType;

  private final Map<String, T> dataMap = new HashMap<String, T>();
  private T currentRow = null;
  private final Map<ObjAttribute, getValueDelegate> data = new HashMap<ObjAttribute, getValueDelegate>();
  private final Map<ObjRelationship, getValueDelegate> dataRel = new HashMap<ObjRelationship, getValueDelegate>();
  private final JDialog jf = new JDialog();
  private final JPanel jp = new JPanel(new GridBagLayout());
  private final DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
  private final JList<String> jl = new JList<String>(model);

  private interface getValueDelegate {
    public Object getValue();
  }

  @SuppressWarnings("unchecked")
  public DatabaseEditor(Class<T> clazz) throws Exception {
    context = DatabaseContext.getContext();
    if(context == null)
      throw new UnloggedException("No database is initialized");
    List<T> dataRows = context.performQuery(new SelectQuery(clazz));
    Collections.sort(dataRows);

    editorType = clazz.getSimpleName();
    jf.setTitle(editorType + " Editor");
    Box box = new Box(BoxLayout.X_AXIS);
    box.add(new JScrollPane(jl));

    Box box2 = new Box(BoxLayout.Y_AXIS);
    box2.add(jp);

    Box box3 = new Box(BoxLayout.X_AXIS);

    JButton btnSave = new JButton("Save");
    btnSave.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        saveData();
        loadData();
      }});
    box3.add(btnSave);
    JButton btnRevert = new JButton("Revert");
    btnRevert.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        loadData();
      }});
    box3.add(btnRevert);
    JButton btnDelete = new JButton("Delete");
    btnDelete.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        int option = JOptionPane.showConfirmDialog(
            jf,
            "Are you sure you want to delete this row?",
            "Delete row?",
            JOptionPane.YES_NO_OPTION,
            JOptionPane.QUESTION_MESSAGE);
        if(option != JOptionPane.YES_OPTION)
          return;

        try {
          String disp = getDisplayString(currentRow);
          dataMap.remove(disp);

          context.deleteObject(currentRow);
          currentRow.updateRow();

          currentRow = null;
          model.removeElement(disp);
          jp.removeAll();
          jp.repaint();
          data.clear();
          dataRel.clear();
        } catch(Exception ex) {
          Out.popupException(ex, jf);
        }
      }});
    box3.add(btnDelete);

    box2.add(box3);

    box.add(box2);

    for(T row : dataRows) {
      String disp = getDisplayString(row);
      model.addElement(disp);
      dataMap.put(disp, row);
    }

    jl.addListSelectionListener(new ListSelectionListener() {
      @Override
      public void valueChanged(ListSelectionEvent e) {
        if(changesMade()) {
          int option = JOptionPane.showConfirmDialog(
              jf,
              "You have made changes to the " + editorType + " " + currentRow.toString() + ". Do you want to save them?",
              "Save changes?",
              JOptionPane.YES_NO_OPTION,
              JOptionPane.QUESTION_MESSAGE);
          if(option == JOptionPane.YES_OPTION)
            saveData();
        }
        context.rollbackChanges();
        loadData();
      }});

    jf.add(box);
    jf.pack();
    jf.setVisible(true);
    jf.setModal(true);
  }

  private String getDisplayString(T row) {
    if(row == null)
      return "NULL";
    return row.toString();
  }

  private void loadData() {
    jp.removeAll();
    data.clear();
    dataRel.clear();
    int y = 0;

    currentRow = dataMap.get(jl.getSelectedValue());
    if(currentRow == null)
      return;

    ObjEntity objEntity = currentRow.getObjEntity();
    for (ObjAttribute attr : objEntity.getAttributes()) {
      DbAttribute dbAttribute = attr.getDbAttribute();
      if(dbAttribute.isGenerated() || dbAttribute.isForeignKey())
        continue;
      addField(jp, y++, attr, currentRow);
    }
    for (ObjRelationship rel : objEntity.getRelationships()) {
      if(rel.isToMany())
        continue;
      addField(jp, y++, rel, currentRow);
    }

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridy = y++;
    gbc.weighty = 1;
    jp.add(Box.createVerticalGlue(), gbc);

    jf.pack();
  }

  @SuppressWarnings("unchecked")
  public void addField(Container jp, int y, ObjRelationship rel, CustomDataObject<?> row) {
    final Class<?> fieldType = ((ObjEntity)rel.getTargetEntity()).getJavaClass();
    final String propName = rel.getName();

    boolean isNullable = true;
    for(DbRelationship dbr : rel.getDbRelationships())
      for(DbAttribute dba : dbr.getSourceAttributes()) {
        if(dba.isMandatory()) {
          isNullable = false;
          break;
        }
      }

    final T value = (T)row.readProperty(propName);

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridy = y;
    gbc.gridx = 0;
    gbc.fill = GridBagConstraints.BOTH;
    jp.add(new JLabel(propName), gbc);

    final JCheckBox bNull;
    gbc.gridx++;
    if(isNullable) {
      bNull = new JCheckBox("NULL", value == null);
      jp.add(bNull, gbc);
    } else {
      bNull = null;
      jp.add(new JLabel(), gbc);
    }

    final HashMap<String, T> theseOptions = new HashMap<String, T>();
    List<T> relTargets = context.performQuery(new SelectQuery(fieldType));
    Collections.sort(relTargets);
    DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
    for(T v : relTargets) {
      String s = getDisplayString(v);
      model.addElement(s);
      theseOptions.put(s, v);
    }
    final JComboBox<String> valueComponent = new JComboBox<String>(model);
    valueComponent.setSelectedItem((value == null) ? null : getDisplayString(value));

    gbc.gridx++;
    gbc.weightx = 1;
    jp.add(valueComponent, gbc);

    dataRel.put(rel, new getValueDelegate() {
      @Override
      public Object getValue() {
        if((bNull != null) && bNull.isSelected())
          return null;
        String key = (String)valueComponent.getSelectedItem();
        return theseOptions.get(key);
      }});
  }

  public void addField(Container jp, int y, ObjAttribute attr, CustomDataObject<?> row) {
    final Class<?> fieldType = attr.getJavaClass();
    final String propName = attr.getName();
    final Object value = row.readProperty(propName);
    final boolean isNullable = !attr.getDbAttribute().isMandatory();

    final String v =
      (value == null) ? null :
      (value instanceof Date) ? TimeFormatter.formatDateTime((Date)value) :
      value.toString();

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridy = y;
    gbc.gridx = 0;
    gbc.fill = GridBagConstraints.BOTH;
    jp.add(new JLabel(propName), gbc);

    final JCheckBox bNull;
    gbc.gridx++;
    if(isNullable) {
      bNull = new JCheckBox("NULL", value == null);
      jp.add(bNull, gbc);
    } else {
      bNull = null;
      jp.add(new JLabel(), gbc);
    }

    final Component valueComponent;
    if(fieldType.equals(Boolean.class)) {
      valueComponent = new JCheckBox((String)null, ((Boolean)value).booleanValue());
    } else if(fieldType.equals(int.class) && attr.getName().equals("flagSpoof")) {
      int flags = 0;
      if(value != null)
        flags = ((Integer)value).intValue();
      valueComponent = new ConfigFlagChecks(flags);
    } else {
      valueComponent = new ConfigTextField(v);
    }
    gbc.gridx++;
    jp.add(valueComponent, gbc);

    data.put(attr, new getValueDelegate() {
      @Override
      public Object getValue() {
        // If it's nullable, and it's null, return null
        if(isNullable && bNull.isSelected())
          return null;

        // If it's a boolean, return a Boolean
        if(valueComponent instanceof JCheckBox)
          return new Boolean(((JCheckBox)valueComponent).isSelected());

        // If it's a flag set, return an Integer
        if(valueComponent instanceof ConfigFlagChecks)
          return ((ConfigFlagChecks)valueComponent).getFlags();

        String value = ((ConfigTextField)valueComponent).getText();
        if(fieldType.equals(String.class))
          return value;
        if(fieldType.equals(Integer.class) || fieldType.equals(int.class))
          return Integer.valueOf(value);
        if(fieldType.equals(Boolean.class) || fieldType.equals(boolean.class))
          return new Boolean(value);
        if(fieldType.equals(Date.class))
          try {
            return new Date(TimeFormatter.parseDateTime(value));
          } catch (ParseException e) {
            throw new RuntimeException(e);
          }

        throw new IllegalStateException("Unknown fieldType " + fieldType.getSimpleName());
      }});
  }

  private void saveData() {
    try {
      for(ObjAttribute attr : data.keySet()) {
        String key = attr.getName();
        Object value = data.get(attr).getValue();
        currentRow.writeProperty(key, value);
      }
      for(ObjRelationship rel : dataRel.keySet()) {
        String key = rel.getName();
        Object value = dataRel.get(rel).getValue();
        currentRow.writeProperty(key, value);
      }
      currentRow.updateRow();
    } catch(Exception ex) {
      Out.popupException(ex, jf);
    }
  }

  private boolean changesMade() {
    if(currentRow == null)
      return false;

    ObjEntity objEntity = currentRow.getObjEntity();
    for (ObjAttribute attr : objEntity.getAttributes()) {
      DbAttribute dbAttribute = attr.getDbAttribute();
      if(dbAttribute.isGenerated() || dbAttribute.isForeignKey())
        continue;

      final Object value_frm = data.get(attr).getValue();
      final Object value_db = currentRow.readProperty(attr.getName());

      if(!equal(value_frm, value_db))
        return true;
    }
    for (ObjRelationship rel : objEntity.getRelationships()) {
      if(rel.isToMany())
        continue;

      final Object value_frm = dataRel.get(rel).getValue();
      final Object value_db = currentRow.readProperty(rel.getName());

      if(!equal(value_frm, value_db))
        return true;
    }

    return false;
  }

  private boolean equal(Object value_frm, Object value_db) {
    if(value_frm == value_db)
      return true;
    if(value_frm == null)
      return false;
    if((value_frm instanceof Date)
    && (value_db instanceof Date)) {
      Date d1 = (Date)value_frm;
      Date d2 = (Date)value_db;
      // Don't compare miliseconds
      return (d1.getTime()/1000) == (d2.getTime()/1000);
    }

    return value_frm.equals(value_db);
  }
}
TOP

Related Classes of net.bnubot.bot.gui.DatabaseEditor$getValueDelegate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.