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.dialog.autorelationship;
  
  import java.awt.Component;
  
  import javax.swing.DefaultComboBoxModel;
  import javax.swing.JOptionPane;
  
  import org.apache.cayenne.map.DataMap;
  import org.apache.cayenne.map.DbEntity;
  import org.apache.cayenne.map.DbJoin;
  import org.apache.cayenne.map.DbRelationship;
  import org.apache.cayenne.map.event.MapEvent;
  import org.apache.cayenne.map.event.RelationshipEvent;
  import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
  import org.apache.cayenne.modeler.Application;
  import org.apache.cayenne.modeler.ClassLoadingService;
  import org.apache.cayenne.modeler.ProjectController;
  import org.apache.cayenne.modeler.dialog.ErrorDebugDialog;
  import org.apache.cayenne.modeler.undo.CreateRelationshipUndoableEdit;
  import org.apache.cayenne.modeler.undo.InferRelationshipsUndoableEdit;
  import org.apache.cayenne.modeler.util.CayenneController;
  import org.apache.cayenne.modeler.util.NameGeneratorPreferences;
  import org.apache.cayenne.swing.BindingBuilder;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  public class InferRelationshipsController extends InferRelationshipsControllerBase {
  
      public static final int SELECT = 1;
      public static final int CANCEL = 0;
  
      private static Logger logObj = LoggerFactory.getLogger(ErrorDebugDialog.class);
  
      protected InferRelationshipsDialog view;
  
      protected InferRelationshipsTabController entitySelector;
  
      protected ObjectNameGenerator strategy;
  
      public InferRelationshipsController(CayenneController parent, DataMap dataMap) {
          super(parent, dataMap);
          strategy = createNamingStrategy(NameGeneratorPreferences
                  .getInstance()
                  .getLastUsedStrategies()
                  .get(0));
          setNamingStrategy(strategy);
          setRelationships();
          this.entitySelector = new InferRelationshipsTabController(this);
      }
  
      public ObjectNameGenerator createNamingStrategy(String strategyClass) {
          try {
              ClassLoadingService classLoader = application.getClassLoadingService();
  
              return classLoader.loadClass(ObjectNameGenerator.class, strategyClass).getDeclaredConstructor().newInstance();
          }
          catch (Throwable th) {
              logObj.error("Error in " + getClass().getName(), th);
  
              JOptionPane.showMessageDialog(
                      view,
                      "Naming Strategy Initialization Error: " + th.getMessage(),
                      "Naming Strategy Initialization Error",
                      JOptionPane.ERROR_MESSAGE);
              return null;
          }
      }
  
      @Override
      public Component getView() {
          return view;
      }
  
      public void startup() {
          // show dialog even on empty DataMap, as custom generation may still take
          // advantage of it
  
          view = new InferRelationshipsDialog(entitySelector.getView());
          initBindings();
  
          view.pack();
          view.setModal(true);
          centerView();
          makeCloseableOnEscape();
          view.setVisible(true);
  
      }
  
      protected void initBindings() {
          BindingBuilder builder = new BindingBuilder(
                  getApplication().getBindingFactory(),
                  this);
  
          builder.bindToAction(view.getCancelButton(), "cancelAction()");
          builder.bindToAction(view.getGenerateButton(), "generateAction()");
          builder.bindToAction(this, "entitySelectedAction()", SELECTED_PROPERTY);
          builder.bindToAction(view.getStrategyCombo(), "strategyComboAction()");
      }
  
      public void entitySelectedAction() {
          int size = getSelectedEntitiesSize();
          String label;
  
          if (size == 0) {
              label = "No DbRelationships selected";
          }
          else if (size == 1) {
              label = "One DbRelationships selected";
          }
          else {
              label = size + " DbRelationships selected";
          }
  
          view.getEntityCount().setText(label);
      }
  
      public void strategyComboAction() {
          try {
  
              String strategyClass = (String) view.getStrategyCombo().getSelectedItem();
  
              this.strategy = createNamingStrategy(strategyClass);
  
              /*
               * Be user-friendly and update preferences with specified strategy
               */
              if (strategy == null) {
                  return;
              }
              NameGeneratorPreferences.getInstance().addToLastUsedStrategies(strategyClass);
              view.getStrategyCombo().setModel(
                      new DefaultComboBoxModel<>(NameGeneratorPreferences.getInstance().getLastUsedStrategies()));
          }
          catch (Throwable th) {
              logObj.error("Error in " + getClass().getName(), th);
              return;
          }
  
          setNamingStrategy(strategy);
          createNames();
          entitySelector.initBindings();
          view.setChoice(SELECT);
  
      }
  
      public ObjectNameGenerator getNamingStrategy() {
          return strategy;
      }
  
      public void cancelAction() {
          view.dispose();
      }
  
      public void generateAction() {
          
          ProjectController mediator = application.getFrameController().getProjectController();
          InferRelationshipsUndoableEdit undoableEdit = new InferRelationshipsUndoableEdit();
          
          for (InferredRelationship temp : selectedEntities) {
              DbRelationship rel = new DbRelationship(uniqueRelName(temp.getSource(), temp
                      .getName()));
  
              RelationshipEvent e = new RelationshipEvent(Application.getFrame(), rel, temp
                      .getSource(), MapEvent.ADD);
              mediator.fireDbRelationshipEvent(e);
  
              rel.setSourceEntity(temp.getSource());
              rel.setTargetEntityName(temp.getTarget());
              DbJoin join = new DbJoin(rel, temp.getJoinSource().getName(), temp
                      .getJoinTarget()
                      .getName());
              rel.addJoin(join);
              rel.setToMany(temp.isToMany());
              temp.getSource().addRelationship(rel);
              
              undoableEdit.addEdit(new CreateRelationshipUndoableEdit(temp.getSource(), new DbRelationship[] { rel }));
          }
          JOptionPane.showMessageDialog(this.getView(), getSelectedEntitiesSize()
                  + " relationships generated");
          view.dispose();
      }
  
      private String uniqueRelName(DbEntity entity, String preferredName) {
          int currentSuffix = 1;
          String relName = preferredName;
  
          while (entity.getRelationship(relName) != null
                  || entity.getAttribute(relName) != null) {
              relName = preferredName + currentSuffix;
              currentSuffix++;
          }
          return relName;
      }
  
  }