http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjEntityRelationshipPanel.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjEntityRelationshipPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjEntityRelationshipPanel.java index dffd96d..f417989 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjEntityRelationshipPanel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjEntityRelationshipPanel.java @@ -18,15 +18,10 @@ ****************************************************************/ package org.apache.cayenne.modeler.editor; -import org.apache.cayenne.map.Attribute; import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.map.DbEntity; -import org.apache.cayenne.map.DbRelationship; import org.apache.cayenne.map.DeleteRule; -import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.map.ObjRelationship; -import org.apache.cayenne.map.Relationship; import org.apache.cayenne.map.event.EntityEvent; import org.apache.cayenne.map.event.ObjEntityListener; import org.apache.cayenne.map.event.ObjRelationshipListener; @@ -45,19 +40,18 @@ import org.apache.cayenne.modeler.event.TablePopupHandler; import org.apache.cayenne.modeler.pref.TableColumnPreferences; import org.apache.cayenne.modeler.util.CayenneTable; import org.apache.cayenne.modeler.util.CellRenderers; -import org.apache.cayenne.modeler.util.EntityTreeFilter; -import org.apache.cayenne.modeler.util.EntityTreeModel; +import org.apache.cayenne.modeler.util.DbRelationshipPathComboBoxEditor; +import org.apache.cayenne.modeler.util.JTableCollectionTypeComboBoxEditor; +import org.apache.cayenne.modeler.util.JTableCollectionTypeComboBoxRenderer; +import org.apache.cayenne.modeler.util.JTableMapKeyComboBoxEditor; +import org.apache.cayenne.modeler.util.JTableMapKeyComboBoxRenderer; import org.apache.cayenne.modeler.util.ModelerUtil; import org.apache.cayenne.modeler.util.PanelFactory; import org.apache.cayenne.modeler.util.UIUtil; -import org.apache.cayenne.modeler.util.combo.AutoCompletion; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import javax.swing.AbstractCellEditor; import javax.swing.DefaultCellEditor; -import javax.swing.DefaultComboBoxModel; import javax.swing.Icon; import javax.swing.JComboBox; import javax.swing.JLabel; @@ -71,22 +65,14 @@ import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; -import javax.swing.text.JTextComponent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.regex.Pattern; /** * Displays ObjRelationships for the edited ObjEntity. @@ -96,20 +82,15 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl private static Log logObj = LogFactory.getLog(ObjEntityRelationshipPanel.class); - private static final Object[] deleteRules = new Object[]{ + private static final Object[] DELETE_RULES = new Object[]{ DeleteRule.deleteRuleName(DeleteRule.NO_ACTION), DeleteRule.deleteRuleName(DeleteRule.NULLIFY), DeleteRule.deleteRuleName(DeleteRule.CASCADE), DeleteRule.deleteRuleName(DeleteRule.DENY), }; - /* static final String COLLECTION_TYPE_MAP = "java.util.Map"; - static final String COLLECTION_TYPE_SET = "java.util.Set"; - static final String COLLECTION_TYPE_COLLECTION = "java.util.Collection"; - static final String DEFAULT_COLLECTION_TYPE = "java.util.List";*/ - - protected ProjectController mediator; - protected CayenneTable table; + private ProjectController mediator; + private CayenneTable table; private TableColumnPreferences tablePreferences; private ActionListener resolver; private ObjEntityAttributeRelationshipTab parentPanel; @@ -119,7 +100,7 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl * By now popup menu item is made similar to toolbar button. (i.e. all functionality * is here) This should be probably refactored as Action. */ - protected JMenuItem resolveMenu; + private JMenuItem resolveMenu; public ObjEntityRelationshipPanel(ProjectController mediator, ObjEntityAttributeRelationshipTab parentPanel) { this.mediator = mediator; @@ -129,21 +110,20 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl initController(); } + public CayenneTable getTable() { + return table; + } + + public void setTable(CayenneTable table) { + this.table = table; + } + private void init() { this.setLayout(new BorderLayout()); ActionManager actionManager = Application.getInstance().getActionManager(); - table = new CayenneTable(){ - @Override - public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { - Component component = super.prepareRenderer(renderer, row, column); - int rendererWidth = component.getPreferredSize().width; - TableColumn tableColumn = getColumnModel().getColumn(column); - tableColumn.setPreferredWidth(Math.max(rendererWidth + getIntercellSpacing().width, tableColumn.getPreferredWidth())); - return component; - } - }; + table = new CayenneTable(); table.setDefaultRenderer(String.class, new StringRenderer()); table.setDefaultRenderer(ObjEntity.class, new EntityRenderer()); tablePreferences = new TableColumnPreferences( @@ -318,8 +298,6 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl JComboBox combo = (JComboBox) editor.getComponent(); combo.setRenderer(CellRenderers.entityListRendererWithIcons(entity.getDataMap())); - //combo.setModel(new DefaultComboBoxModel(createObjEntityComboModel())); - //combo.setEnabled(false); ObjRelationshipTableModel model = (ObjRelationshipTableModel) table.getModel(); model.fireTableDataChanged(); @@ -336,11 +314,7 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl public void tableChanged(TableModelEvent e) { if (table.getSelectedRow() >= 0) { ObjRelationship rel = model.getRelationship(table.getSelectedRow()); - if (((ObjEntity) rel.getSourceEntity()).getDbEntity() != null) { - enabledResolve = true; - } else - enabledResolve = false; - + enabledResolve = rel.getSourceEntity().getDbEntity() != null; resolveMenu.setEnabled(enabledResolve); } } @@ -350,21 +324,12 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl table.setRowHeight(25); table.setRowMargin(3); - TableColumn col = table.getColumnModel().getColumn( - ObjRelationshipTableModel.REL_TARGET_PATH); - JComboBox targetCombo = Application.getWidgetFactory().createComboBox( - createObjEntityComboModel(), - false); - AutoCompletion.enable(targetCombo); - - targetCombo.setRenderer(CellRenderers.entityListRendererWithIcons(entity - .getDataMap())); - targetCombo.setSelectedIndex(-1); - col.setCellEditor(new JTableTargetComboBoxEditor()); + TableColumn col = table.getColumnModel().getColumn(ObjRelationshipTableModel.REL_TARGET_PATH); + col.setCellEditor(new DbRelationshipPathComboBoxEditor()); col = table.getColumnModel().getColumn(ObjRelationshipTableModel.REL_DELETE_RULE); JComboBox deleteRulesCombo = Application.getWidgetFactory().createComboBox( - deleteRules, + DELETE_RULES, false); deleteRulesCombo.setEditable(false); deleteRulesCombo.setSelectedIndex(0); // Default to the first value @@ -377,6 +342,7 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl col.setCellRenderer(new JTableCollectionTypeComboBoxRenderer()); col = table.getColumnModel().getColumn(ObjRelationshipTableModel.REL_MAP_KEY); + col.setCellEditor(new JTableMapKeyComboBoxEditor()); col.setCellRenderer(new JTableMapKeyComboBoxRenderer()); @@ -465,9 +431,10 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl if (!e.getValueIsAdjusting() && !((ListSelectionModel) e.getSource()).isSelectionEmpty()) { - parentPanel.getAttributePanel().table.getSelectionModel().clearSelection(); - if (parentPanel.getAttributePanel().table.getCellEditor() != null) - parentPanel.getAttributePanel().table.getCellEditor().stopCellEditing(); + parentPanel.getAttributePanel().getTable().getSelectionModel().clearSelection(); + if (parentPanel.getAttributePanel().getTable().getCellEditor() != null) { + parentPanel.getAttributePanel().getTable().getCellEditor().stopCellEditing(); + } Application.getInstance().getActionManager().getAction(RemoveAttributeRelationshipAction.class).setCurrentSelectedPanel(parentPanel.getRelationshipPanel()); Application.getInstance().getActionManager().getAction(CutAttributeRelationshipAction.class).setCurrentSelectedPanel(parentPanel.getRelationshipPanel()); Application.getInstance().getActionManager().getAction(CopyAttributeRelationshipAction.class).setCurrentSelectedPanel(parentPanel.getRelationshipPanel()); @@ -511,485 +478,4 @@ public class ObjEntityRelationshipPanel extends JPanel implements ObjEntityDispl return resolver; } - private final static class JTableCollectionTypeComboBoxEditor extends AbstractCellEditor implements TableCellEditor{ - - static final String COLLECTION_TYPE_MAP = "java.util.Map"; - static final String COLLECTION_TYPE_SET = "java.util.Set"; - static final String COLLECTION_TYPE_COLLECTION = "java.util.Collection"; - static final String DEFAULT_COLLECTION_TYPE = "java.util.List"; - - private ObjRelationshipTableModel model; - private int row; - private int column; - - public JTableCollectionTypeComboBoxEditor() { - } - - @Override - public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, final int column) { - this.model = (ObjRelationshipTableModel) table.getModel(); - this.row = row; - this.column = column; - - final JComboBox collectionTypeCombo = Application.getWidgetFactory().createComboBox( - new Object[]{ - COLLECTION_TYPE_MAP, - COLLECTION_TYPE_SET, - COLLECTION_TYPE_COLLECTION, - DEFAULT_COLLECTION_TYPE - }, - false); - if(model.getRelationship(row).isToMany()){ - collectionTypeCombo.setEnabled(true); - collectionTypeCombo.setSelectedItem( model.getRelationship(row).getCollectionType()); - }else{ - JLabel labelIfToOneRelationship = new JLabel(); - labelIfToOneRelationship.setEnabled(false); - //collectionTypeCombo.setEnabled(false); - //collectionTypeCombo.setSelectedItem( model.getRelationship(row).getCollectionType()); - return labelIfToOneRelationship; - } - collectionTypeCombo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Object selected = collectionTypeCombo.getSelectedItem(); - model.setUpdatedValueAt(selected,row,column); - table.repaint(); - } - }); - return collectionTypeCombo; - } - - @Override - public Object getCellEditorValue() { - return model.getValueAt(row,column); - } - } - - private final static class JTableCollectionTypeComboBoxRenderer implements TableCellRenderer { - - private ObjRelationshipTableModel model; - - public JTableCollectionTypeComboBoxRenderer() { - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - this.model = (ObjRelationshipTableModel) table.getModel(); - JLabel labelIfToOneRelationship = new JLabel(); - labelIfToOneRelationship.setEnabled(false); - JLabel labelIfToManyRelationship = new JLabel((String) value); - labelIfToManyRelationship.setEnabled(true); - labelIfToManyRelationship.setFont(new Font("Verdana", Font.PLAIN , 12)); - if (value == null) - return labelIfToOneRelationship; - - if (model.getRelationship(row).isToMany()) { - return labelIfToManyRelationship; - }else{ - return labelIfToOneRelationship; - } - - } - } - - private final static class JTableMapKeyComboBoxEditor extends AbstractCellEditor implements TableCellEditor { - - static final String DEFAULT_MAP_KEY = "ID (default)"; - static final String COLLECTION_TYPE_MAP = "java.util.Map"; - - private List<String> mapKeys = new ArrayList<>() ; - private ObjRelationshipTableModel model; - private int row; - private int column; - - private JTableMapKeyComboBoxEditor() { - } - - private void initMapKeys() { - mapKeys.clear(); - mapKeys.add(DEFAULT_MAP_KEY); - /** - * Object target can be null when selected target DbEntity has no - * ObjEntities - */ - ObjEntity objectTarget = model.getRelationship(row).getTargetEntity(); - if (objectTarget == null) { - return ; - } - for (ObjAttribute attribute : objectTarget.getAttributes()) { - mapKeys.add(attribute.getName()); - } - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, final int row, final int column) { - this.model = (ObjRelationshipTableModel) table.getModel(); - this.row = row; - this.column = column; - initMapKeys(); - final JComboBox mapKeysComboBox = Application.getWidgetFactory().createComboBox( - mapKeys, - false); - if ((model.getRelationship(row).getCollectionType() == null) - ||(!model.getRelationship(row).getCollectionType().equals(COLLECTION_TYPE_MAP))){ - JComboBox jComboBox = new JComboBox(); - jComboBox.setFocusable(false); - jComboBox.setEnabled(false); - return jComboBox; - }else{ - mapKeysComboBox.setFocusable(true); - mapKeysComboBox.setEnabled(true); - } - mapKeysComboBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Object selected = mapKeysComboBox.getSelectedItem(); - model.setUpdatedValueAt(selected,row,column); - } - }); - mapKeysComboBox.setSelectedItem(model.getRelationship(row).getMapKey()); - return mapKeysComboBox; - } - - @Override - public Object getCellEditorValue() { - return model.getValueAt(row,column); - } - } - - private final static class JTableMapKeyComboBoxRenderer implements TableCellRenderer{ - - static final String DEFAULT_MAP_KEY = "ID (default)"; - static final String COLLECTION_TYPE_MAP = "java.util.Map"; - - private ObjRelationshipTableModel model; - - public JTableMapKeyComboBoxRenderer() { - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - this.model = (ObjRelationshipTableModel) table.getModel(); - if ( (model.getRelationship(row).getCollectionType() == null) - ||(!model.getRelationship(row).getCollectionType().equals(COLLECTION_TYPE_MAP))){ - JComboBox jComboBox = new JComboBox(); - jComboBox.setFocusable(false); - jComboBox.setEnabled(false); - return jComboBox; - } - if (model.getRelationship(row).getMapKey() == null){ - model.getRelationship(row).setMapKey(DEFAULT_MAP_KEY); - } - JLabel jLabel = new JLabel(model.getRelationship(row).getMapKey()); - jLabel.setFont(new Font("Verdana", Font.PLAIN , 12)); - return jLabel; - } - } - - private static final class JTableTargetComboBoxEditor extends AbstractCellEditor implements TableCellEditor, ActionListener { - - private ObjRelationshipTableModel model; - private int row; - private int column; - private JComboBox dbRelationshipPathCombo; - private EntityTreeModel treeModel; - private int previousEmbededLevel = 0; - private static int enterPressedCount = 0; - - public JTableTargetComboBoxEditor() { - } - - @Override - public Object getCellEditorValue() { - return model.getValueAt(row,column); - } - - @Override - public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, int column) { - this.model = (ObjRelationshipTableModel) table.getModel(); - this.row = row; - this.column = column; - treeModel = createTreeModelForComboBoxBrowser(row); - if (treeModel == null) - return new JLabel("You need select table to this ObjectEntity"); - initializeCombo(model , row); - - String dbRelationshipPath = ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).getText(); - previousEmbededLevel = dbRelationshipPath.split(Pattern.quote(".")).length; - - dbRelationshipPathCombo.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() { - private void enterPressed(){ - String dbRelationshipPath = ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).getText(); - Object currentNode = getCurrentNode(dbRelationshipPath); - String[] pathStrings = dbRelationshipPath.split(Pattern.quote(".")); - String lastStringInPath = pathStrings[pathStrings.length - 1]; - - if (lastStringInPath.equals(ModelerUtil.getObjectName(currentNode))) { - if (enterPressedCount == 1) { - //it is second time enter pressed.. so we will save input data - enterPressedCount = 0; - if (currentNode instanceof DbRelationship) { - - if (table.getCellEditor() != null) { - - table.getCellEditor().stopCellEditing(); - model.getRelationship(row).setDbRelationshipPath(dbRelationshipPath); - - //we need object target to save it in model - DbEntity lastEntity = ((DbRelationship) currentNode).getTargetEntity(); - Collection<ObjEntity> objEntities = ((DbRelationship) currentNode).getTargetEntity(). - getDataMap().getMappedEntities(lastEntity); - ObjEntity objectTarget = objEntities.size() == 0 ? null : objEntities.iterator().next(); - model.getRelationship(row).setTargetEntityName(objectTarget); - } - } - table.repaint(); - } else { - enterPressedCount = 1; - } - } - } - - @Override - public void keyReleased(KeyEvent event) { - if (event.getKeyCode() == KeyEvent.VK_ENTER) { - enterPressed(); - return; - } - parseDbRelationshipString(event.getKeyChar()); - } - }); - return dbRelationshipPathCombo; - } - - private void initializeCombo(ObjRelationshipTableModel model , int row){ - String dbRelationshipPath = model.getRelationship(row).getDbRelationshipPath(); - Object currentNode; - if (dbRelationshipPath == null){ - //case if it is new attribute or for some reason dbRelationshipPath is null - currentNode = getCurrentNode(dbRelationshipPath); - dbRelationshipPath = ""; - - }else{ - //case if dbRelationshipPath isn't null and we must change it to find auto completion list - String[] pathStrings = dbRelationshipPath.split(Pattern.quote(".")); - String lastStringInPath = pathStrings[pathStrings.length - 1]; - dbRelationshipPath = dbRelationshipPath.replaceAll(lastStringInPath + "$", ""); - currentNode = getCurrentNode(dbRelationshipPath); - } - List<String> nodeChildren = getChildren(currentNode , dbRelationshipPath); - dbRelationshipPathCombo = Application.getWidgetFactory().createComboBox( - nodeChildren, - false); - AutoCompletion.enable(dbRelationshipPathCombo, false, true); - dbRelationshipPathCombo.setEditable(true); - ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).setText(model.getRelationship(row).getDbRelationshipPath()); - dbRelationshipPathCombo.setSelectedItem(model.getRelationship(row).getDbRelationshipPath()); - dbRelationshipPathCombo.addActionListener(this); - return; - } - - /* - * chech if potential child is child for father - * @param father - * @param potentialChild - * @return - */ - /*private boolean isChild(Object father , Object potentialChild){ - List<Object> fatherChildren = new ArrayList<>(); - for(int j = 0 ; j < treeModel.getChildCount(father) ; j++){ - Object child = treeModel.getChild(father, j); - fatherChildren.add(child); - } - return fatherChildren.contains(potentialChild); - }*/ - - private void parseDbRelationshipString(char lastEnteredCharacter){ - String dbRelationshipPath = ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).getText(); - - enterPressedCount = 0; - - if (dbRelationshipPath.equals("")){ - List<String> currentNodeChildren = new ArrayList<>(); - currentNodeChildren.add(""); - currentNodeChildren.addAll(getChildren(getCurrentNode(dbRelationshipPath),"")); - dbRelationshipPathCombo.setModel(new DefaultComboBoxModel(currentNodeChildren.toArray())); - dbRelationshipPathCombo.showPopup(); - dbRelationshipPathCombo.setPopupVisible(true); - return; - } - - if (lastEnteredCharacter == '.') { - processDotEntered(); - previousEmbededLevel = StringUtils.countMatches(dbRelationshipPath,"."); - return; - } - - int currentEmbededLevel = StringUtils.countMatches(dbRelationshipPath,"."); - if (previousEmbededLevel != currentEmbededLevel){ - previousEmbededLevel = currentEmbededLevel; - List<String> currentNodeChildren = new ArrayList<>(); - String[] pathStrings = dbRelationshipPath.split(Pattern.quote(".")); - String lastStringInPath = pathStrings[pathStrings.length - 1]; - String saveDbRelationshipPath = dbRelationshipPath; - dbRelationshipPath = dbRelationshipPath.replaceAll(lastStringInPath + "$", ""); - currentNodeChildren.add(""); - currentNodeChildren.addAll(getChildren(getCurrentNode(dbRelationshipPath), dbRelationshipPath)); - dbRelationshipPathCombo.setModel(new DefaultComboBoxModel(currentNodeChildren.toArray())); - ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).setText(saveDbRelationshipPath); - - dbRelationshipPathCombo.showPopup(); - dbRelationshipPathCombo.setPopupVisible(true); - return; - } - } - - private void processDotEntered(){ - String dbAttributePath = ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).getText(); - if (dbAttributePath.equals(".")){ - List<String> currentNodeChildren = new ArrayList<>(); - currentNodeChildren.add(""); - currentNodeChildren.addAll(getChildren(getCurrentNode(""),"")); - dbRelationshipPathCombo.setModel(new DefaultComboBoxModel(currentNodeChildren.toArray())); - dbRelationshipPathCombo.showPopup(); - dbRelationshipPathCombo.setPopupVisible(true); - return; - }else { - char secondFromEndCharacter = dbAttributePath.charAt(dbAttributePath.length()-2); - if(secondFromEndCharacter == '.') { - // two dots entered one by one , we replace it by one dot - ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).setText(dbAttributePath.substring(0,dbAttributePath.length()-1)); - return; - }else{ - String[] pathStrings = dbAttributePath.split(Pattern.quote(".")); - String lastStringInPath = pathStrings[pathStrings.length - 1]; - - //we will check if lastStringInPath is correct name of DbAttribute or DbRelationship - //for appropriate previous node in path. if it is not we won't add entered dot to dbAttributePath - String dbAttributePathForPreviousNode; - if (pathStrings.length == 1){ - dbAttributePathForPreviousNode = null; - }else { - dbAttributePathForPreviousNode = dbAttributePath.replace("."+lastStringInPath,""); - } - List<String> potentialVariantsToChoose = getChildren(getCurrentNode(dbAttributePathForPreviousNode),""); - if (potentialVariantsToChoose.contains(lastStringInPath)){ - List<String> currentNodeChildren = new ArrayList<>(); - currentNodeChildren.add(dbAttributePath + ""); - currentNodeChildren.addAll(getChildren(getCurrentNode(dbAttributePath), dbAttributePath)); - dbRelationshipPathCombo.setModel(new DefaultComboBoxModel(currentNodeChildren.toArray())); - dbRelationshipPathCombo.showPopup(); - dbRelationshipPathCombo.setPopupVisible(true); - }else{ - ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).setText(dbAttributePath.substring(0,dbAttributePath.length()-1)); - } - } - } - previousEmbededLevel = StringUtils.countMatches(dbAttributePath,"."); - return; - } - - /** - * find current node by dbRelationshipPath - * @param dbRelationshipPath - * @return last node in dbRelationshipPath which matches DbRelationship - */ - private final Object getCurrentNode(String dbRelationshipPath) { - try { - //case for new relationship - if(dbRelationshipPath == null){ - return treeModel.getRoot(); - } - String[] pathStrings = dbRelationshipPath.split(Pattern.quote(".")); - Object root = treeModel.getRoot(); - for (int i = 0 ; i < pathStrings.length ; i ++) { - String rootChildText = pathStrings[i]; - for (int j = 0; j < treeModel.getChildCount(root); j++) { - Object child = treeModel.getChild(root, j); - if (child instanceof DbRelationship) { - String relationshipName = ModelerUtil.getObjectName(child); - if (relationshipName.equals(rootChildText)) { - root = child; - break; - } - } - } - } - return root; - }catch (Exception e){ - return treeModel.getRoot(); - } - } - - /** - * @param node for which we will find children - * @param dbRelationshipPath string which will be added to each child to make right autocomplete - * @return list with children , which will be used to autocomplete - */ - private final List<String> getChildren(Object node , String dbRelationshipPath){ - List<String> currentNodeChildren = new ArrayList<>(); - for(int j = 0 ; j < treeModel.getChildCount(node) ; j++){ - Object child = treeModel.getChild(node, j); - String relationshipName = ModelerUtil.getObjectName(child); - currentNodeChildren.add(dbRelationshipPath + relationshipName); - } - return currentNodeChildren; - } - - /** - * @param relationshipIndexInTable index of attribute for which now we will create cell editor - * @return treeModel for nessesary for us attribute - */ - private EntityTreeModel createTreeModelForComboBoxBrowser(int relationshipIndexInTable){ - if (model.getRelationship(relationshipIndexInTable). - getSourceEntity().getDbEntity() == null) - return null; - EntityTreeModel treeModel = new EntityTreeModel(model.getRelationship(relationshipIndexInTable). - getSourceEntity().getDbEntity()); - treeModel.setFilter(new EntityTreeFilter() { - - public boolean attributeMatch(Object node, Attribute attr) { - // attrs not allowed here - return false; - } - - public boolean relationshipMatch(Object node, Relationship rel) { - if (!(node instanceof Relationship)) { - return true; - } - - /** - * We do not allow A->B->A chains, where relationships are - * to-one - */ - DbRelationship prev = (DbRelationship) node; - return !(!rel.isToMany() && prev.getReverseRelationship() == rel); - } - - }); - return treeModel; - } - - @Override - public void actionPerformed(ActionEvent e) { - model.getRelationship(row).setMapKey(null); - - //for some reason dbRelationshipPathCombo don't load selected item text, so we made it by hand - if (dbRelationshipPathCombo.getSelectedIndex() != (-1)){ - ((JTextComponent) (dbRelationshipPathCombo). - getEditor().getEditorComponent()).setText(dbRelationshipPathCombo.getSelectedItem().toString()); - } - - - } - } } \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjRelationshipTableModel.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjRelationshipTableModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjRelationshipTableModel.java index 91592f6..eab255b 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjRelationshipTableModel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjRelationshipTableModel.java @@ -37,18 +37,17 @@ import java.util.Comparator; public class ObjRelationshipTableModel extends CayenneTableModel { // Columns - static final int REL_NAME = 0; - static final int REL_TARGET = 1; - static final int REL_TARGET_PATH = 2; - static final int REL_COLLECTION_TYPE = 3; - static final int REL_MAP_KEY = 4; - static final int REL_SEMANTICS = 5; - static final int REL_DELETE_RULE = 6; - static final int REL_LOCKING = 7; - - static final int COLUMN_COUNT = 8; - - protected ObjEntity entity; + public static final int REL_NAME = 0; + public static final int REL_TARGET = 1; + public static final int REL_TARGET_PATH = 2; + public static final int REL_COLLECTION_TYPE = 3; + public static final int REL_MAP_KEY = 4; + public static final int REL_SEMANTICS = 5; + public static final int REL_DELETE_RULE = 6; + public static final int REL_LOCKING = 7; + public static final int COLUMN_COUNT = 8; + + private ObjEntity entity; public ObjRelationshipTableModel(ObjEntity entity, ProjectController mediator, Object eventSource) { @@ -99,7 +98,6 @@ public class ObjRelationshipTableModel extends CayenneTableModel { return "Map key"; case REL_TARGET_PATH: return "DbRelationshipPath"; - default: return null; } @@ -127,52 +125,35 @@ public class ObjRelationshipTableModel extends CayenneTableModel { if (column == REL_NAME) { return relationship.getName(); - } - else if (column == REL_TARGET) { + } else if (column == REL_TARGET) { return relationship.getTargetEntity(); - } - else if (column == REL_LOCKING) { + } else if (column == REL_LOCKING) { return relationship.isUsedForLocking() ? Boolean.TRUE : Boolean.FALSE; - } - else if (column == REL_SEMANTICS) { + } else if (column == REL_SEMANTICS) { return getSemantics(relationship); - } - else if (column == REL_DELETE_RULE) { + } else if (column == REL_DELETE_RULE) { return DeleteRule.deleteRuleName(relationship.getDeleteRule()); } else if (column == REL_COLLECTION_TYPE) { - if (!relationship.isToMany()) + if (!relationship.isToMany()) { return null; + } return relationship.getCollectionType(); - } else if (column == REL_MAP_KEY){ + } else if (column == REL_MAP_KEY) { return relationship.getMapKey(); - } else if (column == REL_TARGET_PATH){ + } else if (column == REL_TARGET_PATH) { return relationship.getDbRelationshipPath(); - } - else { + } else { return null; } } - private String getSemantics(ObjRelationship relationship) { - String semantics = relationship.isToMany() ? "to many" : "to one"; + private static String getSemantics(ObjRelationship relationship) { + StringBuilder semantics = new StringBuilder(20); + semantics.append(relationship.isToMany() ? "to many" : "to one"); if (relationship.isReadOnly()) { - semantics += ", read-only"; - } - - if (relationship.isToMany()) { - String collection = "list"; - if (relationship.getCollectionType() != null) { - int dot = relationship.getCollectionType().lastIndexOf('.'); - collection = relationship - .getCollectionType() - .substring(dot + 1) - .toLowerCase(); - } - - semantics += ", " + collection; + semantics.append(", read-only"); } - - return semantics; + return semantics.toString(); } @Override @@ -185,19 +166,18 @@ public class ObjRelationshipTableModel extends CayenneTableModel { event.setOldName(relationship.getName()); ProjectUtil.setRelationshipName(entity, relationship, text); fireTableCellUpdated(row, column); - } - else if (column == REL_TARGET) { + } else if (column == REL_TARGET) { ObjEntity target = (ObjEntity) value; relationship.setTargetEntityName(target); - + /** * Clear existing relationships, otherwise addDbRelationship() might fail */ relationship.clearDbRelationships(); - + // now try to connect DbEntities if we can do it in one step if (target != null) { - DbEntity srcDB = ((ObjEntity) relationship.getSourceEntity()) + DbEntity srcDB = relationship.getSourceEntity() .getDbEntity(); DbEntity targetDB = target.getDbEntity(); if (srcDB != null && targetDB != null) { @@ -209,24 +189,20 @@ public class ObjRelationshipTableModel extends CayenneTableModel { } fireTableRowsUpdated(row, row); - } - else if (column == REL_DELETE_RULE) { + } else if (column == REL_DELETE_RULE) { relationship.setDeleteRule(DeleteRule.deleteRuleForName((String) value)); fireTableCellUpdated(row, column); - } - else if (column == REL_LOCKING) { + } else if (column == REL_LOCKING) { relationship.setUsedForLocking((value instanceof Boolean) && ((Boolean) value).booleanValue()); fireTableCellUpdated(row, column); - } - else if (column == REL_COLLECTION_TYPE){ + } else if (column == REL_COLLECTION_TYPE) { relationship.setCollectionType((String) value); fireTableCellUpdated(row, column); - }else if (column == REL_MAP_KEY){ + } else if (column == REL_MAP_KEY) { relationship.setMapKey((String) value); fireTableCellUpdated(row, column); - } - else if (column == REL_TARGET_PATH){ + } else if (column == REL_TARGET_PATH) { relationship.setDbRelationshipPath((String) value); fireTableCellUpdated(row, column); } @@ -235,8 +211,9 @@ public class ObjRelationshipTableModel extends CayenneTableModel { } public void removeRow(int row) { - if (row < 0) + if (row < 0) { return; + } Relationship rel = getRelationship(row); RelationshipEvent e; e = new RelationshipEvent(eventSource, rel, entity, RelationshipEvent.REMOVE); @@ -296,55 +273,60 @@ public class ObjRelationshipTableModel extends CayenneTableModel { case REL_MAP_KEY: case REL_DELETE_RULE: case REL_TARGET_PATH: - Collections.sort(objectList, new Comparator<ObjRelationship>() { - - public int compare(ObjRelationship o1, ObjRelationship o2) { - if ((o1 == null && o2 == null) || o1 == o2) { - return 0; - } - else if (o1 == null && o2 != null) { - return -1; - } - else if (o1 != null && o2 == null) { - return 1; - } - - String valueToCompare1 = ""; - String valueToCompare2 = ""; - switch(sortCol){ - case REL_COLLECTION_TYPE: - valueToCompare1 = o1.getCollectionType(); - valueToCompare2 = o2.getCollectionType(); - break; - case REL_MAP_KEY: - valueToCompare1 = o1.getMapKey(); - valueToCompare2 = o2.getMapKey(); - break; - case REL_SEMANTICS: - valueToCompare1 = getSemantics(o1); - valueToCompare2 = getSemantics(o2); - break; - case REL_DELETE_RULE: - valueToCompare1 = DeleteRule.deleteRuleName(o1.getDeleteRule()); - valueToCompare2 = DeleteRule.deleteRuleName(o2.getDeleteRule()); - break; - case REL_TARGET_PATH: - valueToCompare1 = o1.getDbRelationshipPath(); - valueToCompare2 = o2.getDbRelationshipPath(); - break; - } - return (valueToCompare1 == null) ? -1 : (valueToCompare2 == null) - ? 1 - : valueToCompare1.compareTo(valueToCompare2); - } - - }); + Collections.sort(objectList, new ObjRelationshipTableComparator(sortCol)); if (!isAscent) { Collections.reverse(objectList); } break; + default: + break; + } + } + + private static class ObjRelationshipTableComparator implements Comparator<ObjRelationship>{ + private int sortCol; + + public ObjRelationshipTableComparator(int sortCol) { + this.sortCol = sortCol; + } + + public int compare(ObjRelationship o1, ObjRelationship o2) { + if ((o1 == null && o2 == null) || o1 == o2) { + return 0; + } + else if (o1 == null && o2 != null) { + return -1; + } + else if (o1 != null && o2 == null) { + return 1; + } + + switch(sortCol){ + case REL_COLLECTION_TYPE: + return compareColumnsData(o1.getCollectionType(), o2.getCollectionType()); + case REL_MAP_KEY: + return compareColumnsData(o1.getMapKey(), o2.getMapKey()); + case REL_SEMANTICS: + return compareColumnsData(getSemantics(o1), getSemantics(o2)); + case REL_DELETE_RULE: + return compareColumnsData(DeleteRule.deleteRuleName(o1.getDeleteRule()), + DeleteRule.deleteRuleName(o2.getDeleteRule())); + case REL_TARGET_PATH: + return compareColumnsData(o1.getDbRelationshipPath(), o2.getDbRelationshipPath()); + default: + return compareColumnsData("", ""); + } } + } + private static int compareColumnsData(String value1, String value2) { + if (value1 == null) { + return -1; + } else if (value2 == null) { + return 1; + } else { + return value1.compareTo(value2); + } } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbAttributePathComboBoxEditor.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbAttributePathComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbAttributePathComboBoxEditor.java new file mode 100644 index 0000000..14cb155 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbAttributePathComboBoxEditor.java @@ -0,0 +1,208 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.map.DbAttribute; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.Entity; +import org.apache.cayenne.map.ObjAttribute; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.modeler.editor.ObjAttributeTableModel; +import org.apache.cayenne.util.CayenneMapEntry; +import org.apache.commons.lang.StringUtils; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JTable; +import javax.swing.text.JTextComponent; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; + +public class DbAttributePathComboBoxEditor extends PathChooserComboBoxCellEditor { + + private static final int DB_ATTRIBUTE_PATH_COLUMN = 3; + + private ObjAttributeTableModel model; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + this.model = (ObjAttributeTableModel) table.getModel(); + this.row = row; + treeModel = createTreeModelForComboBox(row); + if (treeModel == null) { + return new JLabel("You should select table for this ObjectEntity"); + } + initializeCombo(model, row, table); + + String dbAttributePath = ((JTextComponent) (comboBoxPathChooser).getEditor().getEditorComponent()).getText(); + previousEmbeddedLevel = StringUtils.countMatches(dbAttributePath, "."); + return comboBoxPathChooser; + } + + @Override + public Object getCellEditorValue() { + return model.getValueAt(row, DB_ATTRIBUTE_PATH_COLUMN); + } + + @Override + protected void initializeCombo(CayenneTableModel model, int row, final JTable table) { + super.initializeCombo(model, row, table); + ((JTextComponent) (comboBoxPathChooser). + getEditor().getEditorComponent()). + setText(((ObjAttributeTableModel) model).getAttribute(row).getValue().getDbAttributePath()); + comboBoxPathChooser.setRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Object currentNode = getCurrentNode((String) value); + JLabel jLabel = new JLabel(); + jLabel.setFont(new Font("Verdana", Font.PLAIN, 13)); + if (isSelected) { + jLabel.setOpaque(true); + jLabel.setBackground(new Color(0xB4B4B4)); + } + if (currentNode instanceof DbRelationship) { + if (((String) value).charAt(((String) value).length() - 1) != '.') { + jLabel.setText(ModelerUtil.getObjectName(value) + " ->"); + } + return jLabel; + } + jLabel.setText(ModelerUtil.getObjectName(value)); + return jLabel; + } + }); + } + + + @Override + protected Object getCurrentNodeToInitializeCombo(CayenneTableModel model, int row) { + return getCurrentNode(getPathToInitializeCombo(model, row)); + } + + @Override + protected String getPathToInitializeCombo(CayenneTableModel model, int row) { + String pathString = ((ObjAttributeTableModel) model).getAttribute(row).getValue().getDbAttributePath(); + if (pathString == null) { + return ""; + } + String[] pathStrings = pathString.split(Pattern.quote(".")); + String lastStringInPath = pathStrings[pathStrings.length - 1]; + return pathString.replaceAll(lastStringInPath + '$', ""); + } + + @Override + protected void enterPressed(JTable table){ + String dbAttributePath =((JTextComponent) comboBoxPathChooser. + getEditor().getEditorComponent()).getText(); + Object currentNode = getCurrentNode(dbAttributePath); + + String[] pathStrings = dbAttributePath.split(Pattern.quote(".")); + String lastStringInPath = pathStrings[pathStrings.length - 1]; + if (ModelerUtil.getObjectName(currentNode).equals(lastStringInPath) && + currentNode instanceof DbAttribute) { + // in this case choose is made.. we save data + + if (table.getCellEditor() != null) { + table.getCellEditor().stopCellEditing(); + model.getAttribute(row).setDbAttributePath(dbAttributePath); + model.setUpdatedValueAt(dbAttributePath, row, DB_ATTRIBUTE_PATH_COLUMN); + } + }else if (ModelerUtil.getObjectName(currentNode).equals(lastStringInPath) && + currentNode instanceof DbRelationship) { + // in this case we add dot to pathString (if it is missing) and show variants for currentNode + + if (dbAttributePath.charAt(dbAttributePath.length()-1) != '.') { + dbAttributePath = dbAttributePath + '.'; + previousEmbeddedLevel = StringUtils.countMatches(dbAttributePath,"."); + ((JTextComponent) (comboBoxPathChooser). + getEditor().getEditorComponent()).setText(dbAttributePath); + } + List<String> currentNodeChildren = new ArrayList<>(); + currentNodeChildren.add(dbAttributePath); + currentNodeChildren.addAll(getChildren(getCurrentNode(dbAttributePath), dbAttributePath)); + comboBoxPathChooser.setModel(new DefaultComboBoxModel(currentNodeChildren.toArray())); + comboBoxPathChooser.showPopup(); + comboBoxPathChooser.setPopupVisible(true); + } + } + + @Override + protected EntityTreeModel createTreeModelForComboBox(int attributeIndexInTable) { + ObjAttribute attribute = model.getAttribute(attributeIndexInTable).getValue(); + Entity firstEntity = null; + if (attribute.getDbAttribute() == null) { + + if (attribute.getParent() instanceof ObjEntity) { + DbEntity dbEnt = ((ObjEntity) attribute.getParent()).getDbEntity(); + + if (dbEnt != null) { + Collection<DbAttribute> attributes = dbEnt.getAttributes(); + Collection<DbRelationship> rel = dbEnt.getRelationships(); + + if (!attributes.isEmpty()) { + Iterator<DbAttribute> iterator = attributes.iterator(); + firstEntity = iterator.next().getEntity(); + } else if (!rel.isEmpty()) { + Iterator<DbRelationship> iterator = rel.iterator(); + firstEntity = iterator.next().getSourceEntity(); + } + } + } + } else { + firstEntity = getFirstEntity(attribute); + } + + if (firstEntity != null) { + EntityTreeModel treeModel = new EntityTreeModel(firstEntity); + treeModel.setFilter(new EntityTreeAttributeRelationshipFilter()); + return treeModel; + } + return null; + } + + private Entity getFirstEntity(ObjAttribute attribute) { + Iterator<CayenneMapEntry> it = attribute.getDbPathIterator(); + Entity firstEnt = attribute.getDbAttribute().getEntity(); + boolean setEnt = false; + + while (it.hasNext()) { + Object ob = it.next(); + if (ob instanceof DbRelationship) { + if (!setEnt) { + firstEnt = ((DbRelationship) ob).getSourceEntity(); + setEnt = true; + } + } else if (ob instanceof DbAttribute) { + if (!setEnt) { + firstEnt = ((DbAttribute) ob).getEntity(); + } + } + } + return firstEnt; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbRelationshipPathComboBoxEditor.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbRelationshipPathComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbRelationshipPathComboBoxEditor.java new file mode 100644 index 0000000..9aac322 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/DbRelationshipPathComboBoxEditor.java @@ -0,0 +1,150 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.modeler.editor.ObjRelationshipTableModel; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.text.JTextComponent; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collection; +import java.util.regex.Pattern; + +public class DbRelationshipPathComboBoxEditor extends PathChooserComboBoxCellEditor implements ActionListener { + + private static final int REL_TARGET_PATH_COLUMN = 2; + private static int enterPressedCount = 0; + + private ObjRelationshipTableModel model; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + this.model = (ObjRelationshipTableModel) table.getModel(); + this.row = row; + treeModel = createTreeModelForComboBox(row); + if (treeModel == null) { + return new JLabel("You should select table for this ObjectEntity"); + } + initializeCombo(model, row, table); + + String dbRelationshipPath = ((JTextComponent) (comboBoxPathChooser). + getEditor().getEditorComponent()).getText(); + previousEmbeddedLevel = dbRelationshipPath.split(Pattern.quote(".")).length; + return comboBoxPathChooser; + } + + @Override + public Object getCellEditorValue() { + return model.getValueAt(row, REL_TARGET_PATH_COLUMN); + } + + @Override + protected void initializeCombo(CayenneTableModel model, int row, final JTable table) { + super.initializeCombo(model, row, table); + ((JTextComponent) (comboBoxPathChooser). + getEditor().getEditorComponent()). + setText(((ObjRelationshipTableModel) model).getRelationship(row).getDbRelationshipPath()); + + enterPressedCount = 0; + comboBoxPathChooser.addActionListener(this); + } + + @Override + protected void enterPressed(JTable table) { + String dbRelationshipPath = ((JTextComponent) (comboBoxPathChooser). + getEditor().getEditorComponent()).getText(); + Object currentNode = getCurrentNode(dbRelationshipPath); + String[] pathStrings = dbRelationshipPath.split(Pattern.quote(".")); + String lastStringInPath = pathStrings[pathStrings.length - 1]; + if (lastStringInPath.equals(ModelerUtil.getObjectName(currentNode)) + && currentNode instanceof DbRelationship) { + if (enterPressedCount == 1) { + //it is second time enter pressed.. so we will save input data + enterPressedCount = 0; + if (table.getCellEditor() != null) { + + table.getCellEditor().stopCellEditing(); + model.getRelationship(row).setDbRelationshipPath(dbRelationshipPath); + + //we need object target to save it in model + DbEntity lastEntity = ((DbRelationship) currentNode).getTargetEntity(); + Collection<ObjEntity> objEntities = ((DbRelationship) currentNode).getTargetEntity(). + getDataMap().getMappedEntities(lastEntity); + ObjEntity objectTarget = objEntities.isEmpty() ? null : objEntities.iterator().next(); + model.getRelationship(row).setTargetEntityName(objectTarget); + } + table.repaint(); + } else { + enterPressedCount = 1; + } + } + } + + @Override + protected void parsePathString(char lastEnteredCharacter) { + super.parsePathString(lastEnteredCharacter); + enterPressedCount = 0; + } + + @Override + protected EntityTreeModel createTreeModelForComboBox(int relationshipIndexInTable) { + if (model.getRelationship(relationshipIndexInTable). + getSourceEntity().getDbEntity() == null) { + return null; + } + EntityTreeModel treeModel = new EntityTreeModel(model.getRelationship(relationshipIndexInTable). + getSourceEntity().getDbEntity()); + treeModel.setFilter(new EntityTreeRelationshipFilter()); + return treeModel; + } + + @Override + protected Object getCurrentNodeToInitializeCombo(CayenneTableModel model, int row) { + return getCurrentNode(getPathToInitializeCombo(model, row)); + } + + @Override + protected String getPathToInitializeCombo(CayenneTableModel model, int row) { + String pathString = ((ObjRelationshipTableModel) model).getRelationship(row).getDbRelationshipPath(); + if (pathString == null) { + return ""; + } + String[] pathStrings = pathString.split(Pattern.quote(".")); + String lastStringInPath = pathStrings[pathStrings.length - 1]; + return pathString.replaceAll(lastStringInPath + '$', ""); + } + + @Override + public void actionPerformed(ActionEvent e) { + model.getRelationship(row).setMapKey(null); + + //for some reason dbRelationshipPathCombo don't load selected item text, so we made it by hand + if (comboBoxPathChooser.getSelectedIndex() != (-1)) { + ((JTextComponent) (comboBoxPathChooser). + getEditor().getEditorComponent()).setText(comboBoxPathChooser.getSelectedItem().toString()); + } + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeAttributeRelationshipFilter.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeAttributeRelationshipFilter.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeAttributeRelationshipFilter.java new file mode 100644 index 0000000..12d9900 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeAttributeRelationshipFilter.java @@ -0,0 +1,47 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.map.Attribute; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.Relationship; + +public class EntityTreeAttributeRelationshipFilter implements EntityTreeFilter { + + public boolean attributeMatch(Object node, Attribute attr) { + if (!(node instanceof Attribute)) { + return true; + } + return false; + } + + public boolean relationshipMatch(Object node, Relationship rel) { + if (!(node instanceof Relationship)) { + return true; + } + + /** + * We do not allow A->B->A chains, where relationships + * are to-one + */ + DbRelationship prev = (DbRelationship) node; + return !(!rel.isToMany() && prev.getReverseRelationship() == rel); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeFilter.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeFilter.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeFilter.java index 2b2b065..eaebb7c 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeFilter.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeFilter.java @@ -29,10 +29,10 @@ public interface EntityTreeFilter { /** * Checks if attribute should appear in the tree */ - public boolean attributeMatch(Object node, Attribute attr); + boolean attributeMatch(Object node, Attribute attr); /** * Checks if relationship should appear in the tree */ - public boolean relationshipMatch(Object node, Relationship rel); + boolean relationshipMatch(Object node, Relationship rel); } http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeRelationshipFilter.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeRelationshipFilter.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeRelationshipFilter.java new file mode 100644 index 0000000..06cc25b --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeRelationshipFilter.java @@ -0,0 +1,45 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.map.Attribute; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.Relationship; + +public class EntityTreeRelationshipFilter implements EntityTreeFilter { + + public boolean attributeMatch(Object node, Attribute attr) { + // attrs not allowed here + return false; + } + + public boolean relationshipMatch(Object node, Relationship rel) { + if (!(node instanceof Relationship)) { + return true; + } + + /** + * We do not allow A->B->A chains, where relationships are + * to-one + */ + DbRelationship prev = (DbRelationship) node; + return !(!rel.isToMany() && prev.getReverseRelationship() == rel); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxEditor.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxEditor.java new file mode 100644 index 0000000..f43b095 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxEditor.java @@ -0,0 +1,84 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.modeler.Application; +import org.apache.cayenne.modeler.editor.ObjRelationshipTableModel; + +import javax.swing.AbstractCellEditor; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class JTableCollectionTypeComboBoxEditor extends AbstractCellEditor implements TableCellEditor { + + private static final String COLLECTION_TYPE_MAP = "java.util.Map"; + private static final String COLLECTION_TYPE_SET = "java.util.Set"; + private static final String COLLECTION_TYPE_COLLECTION = "java.util.Collection"; + private static final String DEFAULT_COLLECTION_TYPE = "java.util.List"; + private static final int REL_COLLECTION_TYPE_COLUMN = 3; + + private ObjRelationshipTableModel model; + private int row; + + public JTableCollectionTypeComboBoxEditor() { + } + + @Override + public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, final int column) { + this.model = (ObjRelationshipTableModel) table.getModel(); + this.row = row; + + final JComboBox collectionTypeCombo = Application.getWidgetFactory().createComboBox( + new Object[]{ + COLLECTION_TYPE_MAP, + COLLECTION_TYPE_SET, + COLLECTION_TYPE_COLLECTION, + DEFAULT_COLLECTION_TYPE + }, + false); + if (model.getRelationship(row).isToMany()) { + collectionTypeCombo.setEnabled(true); + collectionTypeCombo.setSelectedItem(model.getRelationship(row).getCollectionType()); + } else { + JLabel labelIfToOneRelationship = new JLabel(); + labelIfToOneRelationship.setEnabled(false); + return labelIfToOneRelationship; + } + collectionTypeCombo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Object selected = collectionTypeCombo.getSelectedItem(); + model.setUpdatedValueAt(selected, row, REL_COLLECTION_TYPE_COLUMN); + table.repaint(); + } + }); + return collectionTypeCombo; + } + + @Override + public Object getCellEditorValue() { + return model.getValueAt(row, REL_COLLECTION_TYPE_COLUMN); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxRenderer.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxRenderer.java new file mode 100644 index 0000000..8c5d497 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableCollectionTypeComboBoxRenderer.java @@ -0,0 +1,55 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.modeler.editor.ObjRelationshipTableModel; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.awt.Font; + +public class JTableCollectionTypeComboBoxRenderer implements TableCellRenderer { + + private ObjRelationshipTableModel model; + + public JTableCollectionTypeComboBoxRenderer() { + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + this.model = (ObjRelationshipTableModel) table.getModel(); + JLabel labelIfToOneRelationship = new JLabel(); + labelIfToOneRelationship.setEnabled(false); + JLabel labelIfToManyRelationship = new JLabel((String) value); + labelIfToManyRelationship.setEnabled(true); + labelIfToManyRelationship.setFont(new Font("Verdana", Font.PLAIN, 12)); + if (value == null) { + return labelIfToOneRelationship; + } + if (model.getRelationship(row).isToMany()) { + return labelIfToManyRelationship; + } else { + return labelIfToOneRelationship; + } + + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxEditor.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxEditor.java new file mode 100644 index 0000000..3e1178a --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxEditor.java @@ -0,0 +1,99 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.map.ObjAttribute; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.modeler.Application; +import org.apache.cayenne.modeler.editor.ObjRelationshipTableModel; + +import javax.swing.AbstractCellEditor; +import javax.swing.JComboBox; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +public class JTableMapKeyComboBoxEditor extends AbstractCellEditor implements TableCellEditor { + + private static final String DEFAULT_MAP_KEY = "ID (default)"; + private static final String COLLECTION_TYPE_MAP = "java.util.Map"; + private static final int REL_MAP_KEY_COLUMN = 4; + + private List<String> mapKeys = new ArrayList<>(); + private ObjRelationshipTableModel model; + private int row; + + public JTableMapKeyComboBoxEditor() { + } + + private void initMapKeys() { + mapKeys.clear(); + mapKeys.add(DEFAULT_MAP_KEY); + /** + * Object target can be null when selected target DbEntity has no + * ObjEntities + */ + ObjEntity objectTarget = model.getRelationship(row).getTargetEntity(); + if (objectTarget == null) { + return; + } + for (ObjAttribute attribute : objectTarget.getAttributes()) { + mapKeys.add(attribute.getName()); + } + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, final int row, final int column) { + this.model = (ObjRelationshipTableModel) table.getModel(); + this.row = row; + initMapKeys(); + final JComboBox mapKeysComboBox = Application.getWidgetFactory().createComboBox( + mapKeys, + false); + if ((model.getRelationship(row).getCollectionType() == null) + || (!model.getRelationship(row).getCollectionType().equals(COLLECTION_TYPE_MAP))) { + JComboBox jComboBox = new JComboBox(); + jComboBox.setFocusable(false); + jComboBox.setEnabled(false); + return jComboBox; + } else { + mapKeysComboBox.setFocusable(true); + mapKeysComboBox.setEnabled(true); + } + mapKeysComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Object selected = mapKeysComboBox.getSelectedItem(); + model.setUpdatedValueAt(selected, row, REL_MAP_KEY_COLUMN); + } + }); + mapKeysComboBox.setSelectedItem(model.getRelationship(row).getMapKey()); + return mapKeysComboBox; + } + + @Override + public Object getCellEditorValue() { + return model.getValueAt(row, REL_MAP_KEY_COLUMN); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cayenne/blob/b444b1df/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxRenderer.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxRenderer.java new file mode 100644 index 0000000..6f359a1 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/JTableMapKeyComboBoxRenderer.java @@ -0,0 +1,58 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.util; + +import org.apache.cayenne.modeler.editor.ObjRelationshipTableModel; + +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.awt.Font; + +public class JTableMapKeyComboBoxRenderer implements TableCellRenderer { + + private static final String DEFAULT_MAP_KEY = "ID (default)"; + private static final String COLLECTION_TYPE_MAP = "java.util.Map"; + + private ObjRelationshipTableModel model; + + public JTableMapKeyComboBoxRenderer() { + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + this.model = (ObjRelationshipTableModel) table.getModel(); + if ((model.getRelationship(row).getCollectionType() == null) + || (!model.getRelationship(row).getCollectionType().equals(COLLECTION_TYPE_MAP))) { + JComboBox jComboBox = new JComboBox(); + jComboBox.setFocusable(false); + jComboBox.setEnabled(false); + return jComboBox; + } + if (model.getRelationship(row).getMapKey() == null) { + model.getRelationship(row).setMapKey(DEFAULT_MAP_KEY); + } + JLabel jLabel = new JLabel(model.getRelationship(row).getMapKey()); + jLabel.setFont(new Font("Verdana", Font.PLAIN, 12)); + return jLabel; + } + } \ No newline at end of file