content: /*****************************************************************
   *   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
   *
   *    https://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.editor;
  
  import org.apache.cayenne.configuration.event.QueryEvent;
  import org.apache.cayenne.map.Attribute;
  import org.apache.cayenne.map.Entity;
  import org.apache.cayenne.map.Relationship;
  import org.apache.cayenne.modeler.Application;
  import org.apache.cayenne.modeler.ProjectController;
  import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEdit;
  import org.apache.cayenne.modeler.util.CayenneAction;
  import org.apache.cayenne.modeler.util.EntityTreeFilter;
  import org.apache.cayenne.modeler.util.EntityTreeModel;
  import org.apache.cayenne.modeler.util.ModelerUtil;
  import org.apache.cayenne.swing.components.image.FilteredIconFactory;
  
  import javax.swing.BorderFactory;
  import javax.swing.DefaultCellEditor;
  import javax.swing.Icon;
  import javax.swing.JButton;
  import javax.swing.JComboBox;
  import javax.swing.JComponent;
  import javax.swing.JToolBar;
  import javax.swing.table.DefaultTableCellRenderer;
  import javax.swing.table.TableColumn;
  import javax.swing.table.TableModel;
  import javax.swing.tree.TreeModel;
  
  /**
   * Subclass of the SelectQueryOrderingTab configured to work with prefetches.
   * 
   */
  public class SelectQueryPrefetchTab extends SelectQueryOrderingTab {
  
      static final String JOINT_PREFETCH_SEMANTICS = "Joint";
      static final String DISJOINT_PREFETCH_SEMANTICS = "Disjoint";
      static final String DISJOINT_BY_ID_PREFETCH_SEMANTICS = "Disjoint by id";
      static final String UNDEFINED_SEMANTICS = "Undefined semantics";
  
      public SelectQueryPrefetchTab(ProjectController mediator) {
          super(mediator);
      }
  
      protected void initFromModel(){
          super.initFromModel();
          if(table.getColumnModel().getColumns().hasMoreElements()) {
              setUpPrefetchBox(table.getColumnModel().getColumn(2));
          }
      }
  
      protected void setUpPrefetchBox(TableColumn column) {
  
          JComboBox<String> prefetchBox = new JComboBox<>();
          prefetchBox.addItem(JOINT_PREFETCH_SEMANTICS);
          prefetchBox.addItem(DISJOINT_PREFETCH_SEMANTICS);
          prefetchBox.addItem(DISJOINT_BY_ID_PREFETCH_SEMANTICS);
  
          prefetchBox.addActionListener(e -> Application.getInstance().getFrameController().getEditorView().getEventController().setDirty(true));
  
          column.setCellEditor(new DefaultCellEditor(prefetchBox));
  
          DefaultTableCellRenderer renderer =
                  new DefaultTableCellRenderer();
          renderer.setToolTipText("Click for combo box");
          column.setCellRenderer(renderer);
      }
  
      protected JComponent createToolbar() {
  
          JButton add = new CayenneAction.CayenneToolbarButton(null, 1);
          add.setText("Add Prefetch");
          Icon addIcon = ModelerUtil.buildIcon("icon-plus.png");
          add.setIcon(addIcon);
          add.setDisabledIcon(FilteredIconFactory.createDisabledIcon(addIcon));
          
          add.addActionListener(e -> {
              String prefetch = getSelectedPath();
  
              if (prefetch == null) {
                  return;
              }
  
              addPrefetch(prefetch);
  
              Application.getInstance().getUndoManager().addEdit(new AddPrefetchUndoableEdit(prefetch, SelectQueryPrefetchTab.this));
          });
  
          JButton remove = new CayenneAction.CayenneToolbarButton(null, 3);
          remove.setText("Remove Prefetch");
          Icon removeIcon = ModelerUtil.buildIcon("icon-trash.png");
          remove.setIcon(removeIcon);
          remove.setDisabledIcon(FilteredIconFactory.createDisabledIcon(removeIcon));
          remove.addActionListener(e -> {
              int selection = table.getSelectedRow();
  
              if (selection < 0) {
                  return;
              }
  
              String prefetch = (String) table.getModel().getValueAt(selection, 0);
  
              removePrefetch(prefetch);
          });
  
          JToolBar toolBar = new JToolBar();
          toolBar.setBorder(BorderFactory.createEmptyBorder());
          toolBar.setFloatable(false);
          toolBar.add(add);
          toolBar.add(remove);
          return toolBar;
      }
  
      protected TreeModel createBrowserModel(Entity<?,?,?> entity) {
          EntityTreeModel treeModel = new EntityTreeModel(entity);
          treeModel.setFilter(
                  new EntityTreeFilter() {
                      public boolean attributeMatch(Object node, Attribute<?,?,?> attr) {
                          return false;
                      }
  
                      public boolean relationshipMatch(Object node, Relationship<?,?,?> rel) {
                          return true;
                      }
                  });
          return treeModel;
      }
  
      protected TableModel createTableModel() {
          return new PrefetchModel(selectQuery.getPrefetchesMap(), selectQuery.getRoot());
      }
  
      public void addPrefetch(String prefetch) {
          
          // check if such prefetch already exists
          if (!selectQuery.getPrefetchesMap().isEmpty() && selectQuery.getPrefetchesMap().containsKey(prefetch)) {
              return;
          }
  
          //default value id disjoint
          selectQuery.addPrefetch(prefetch, PrefetchModel.getPrefetchType(DISJOINT_PREFETCH_SEMANTICS));
         
          // reset the model, since it is immutable
          table.setModel(createTableModel());
          setUpPrefetchBox(table.getColumnModel().getColumn(2));
          
          mediator.fireQueryEvent(new QueryEvent(this, selectQuery));
      }
  
      public void removePrefetch(String prefetch) {
          selectQuery.removePrefetch(prefetch);
  
          // reset the model, since it is immutable
          table.setModel(createTableModel());
          setUpPrefetchBox(table.getColumnModel().getColumn(2));
  
          mediator.fireQueryEvent(new QueryEvent(this, selectQuery));
      }
  
  }
  