/*****************************************************************
* 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.dialog.db.merge;
import org.apache.cayenne.dbsync.merge.context.MergeDirection;
import org.apache.cayenne.dbsync.merge.token.MergerToken;
import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
import org.apache.cayenne.modeler.Application;
import org.apache.cayenne.modeler.util.CayenneController;
import org.apache.cayenne.modeler.util.ModelerUtil;
import org.apache.cayenne.swing.BindingBuilder;
import org.apache.cayenne.swing.ObjectBinding;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MergerTokenSelectorController extends CayenneController {
protected MergerTokenSelectorView view;
protected ObjectBinding tableBinding;
protected MergerToken token;
protected int permanentlyExcludedCount;
protected Set<MergerToken> excludedTokens;
protected List<MergerToken> selectableTokensList;
protected MergerTokenFactory mergerTokenFactory;
protected boolean isReverse;
public MergerTokenSelectorController(CayenneController parent) {
super(parent);
this.view = new MergerTokenSelectorView();
this.excludedTokens = new HashSet<>();
this.selectableTokensList = new ArrayList<>();
initController();
}
public void setMergerTokenFactory(MergerTokenFactory mergerTokenFactory) {
this.mergerTokenFactory = mergerTokenFactory;
}
public void setTokens(List<MergerToken> tokens) {
selectableTokensList.clear();
selectableTokensList.addAll(tokens);
excludedTokens.addAll(tokens);
}
public List<MergerToken> getSelectedTokens() {
List<MergerToken> t = new ArrayList<>(selectableTokensList);
t.removeAll(excludedTokens);
return Collections.unmodifiableList(t);
}
public List<MergerToken> getSelectableTokens() {
return Collections.unmodifiableList(selectableTokensList);
}
public void removeToken(MergerToken token) {
selectableTokensList.remove(token);
excludedTokens.remove(token);
AbstractTableModel model = (AbstractTableModel) view.getTokens().getModel();
model.fireTableDataChanged();
}
// ----- properties -----
public Component getView() {
return view;
}
/**
* Called by table binding script to set current token.
*/
public void setToken(MergerToken token) {
this.token = token;
}
/**
* Returns {@link MergerToken}s that are excluded from DB generation.
*/
/*
* public Collection getExcludedTokens() { return excludedTokens; }
*/
public boolean isIncluded() {
if (token == null) {
return false;
}
return !excludedTokens.contains(token);
}
public void setIncluded(boolean b) {
if (token == null) {
return;
}
if (b) {
excludedTokens.remove(token);
} else {
excludedTokens.add(token);
}
tableSelectedAction();
}
/**
* A callback action that updates the state of Select All checkbox.
*/
public void tableSelectedAction() {
int unselectedCount = excludedTokens.size() - permanentlyExcludedCount;
if (unselectedCount == selectableTokensList.size()) {
view.getCheckAll().setSelected(false);
} else if (unselectedCount == 0) {
view.getCheckAll().setSelected(true);
}
}
// ------ other stuff ------
protected void initController() {
BindingBuilder builder = new BindingBuilder(
getApplication().getBindingFactory(),
this);
builder.bindToAction(view.getCheckAll(), "checkAllAction()");
builder.bindToAction(view.getReverseAll(), "reverseAllAction()");
TableModel model = new MergerTokenTableModel(this);
MergeDirection[] dirs = new MergeDirection[] {
MergeDirection.TO_DB, MergeDirection.TO_MODEL
};
view.getTokens().setModel(model);
TableColumnModel columnModel = view.getTokens().getColumnModel();
// dropdown for direction column
JComboBox directionCombo = Application.getWidgetFactory().createComboBox(dirs, false);
directionCombo.setEditable(false);
TableColumn directionColumn = columnModel.getColumn(
MergerTokenTableModel.COL_DIRECTION);
directionColumn.setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setHorizontalTextPosition(SwingConstants.LEFT);
setIcon(ModelerUtil.buildIcon("icon-arrow-open.png"));
return this;
}
});
directionColumn.setCellEditor(new DefaultCellEditor(directionCombo));
columnModel.getColumn(MergerTokenTableModel.COL_SELECT).setPreferredWidth(50);
columnModel.getColumn(MergerTokenTableModel.COL_DIRECTION).setPreferredWidth(100);
columnModel.getColumn(MergerTokenTableModel.COL_SELECT).setMaxWidth(50);
columnModel.getColumn(MergerTokenTableModel.COL_DIRECTION).setMaxWidth(100);
}
public boolean isSelected(MergerToken token) {
return (selectableTokensList.contains(token) && !excludedTokens.contains(token));
}
public void select(MergerToken token, boolean select) {
if (select) {
excludedTokens.remove(token);
} else {
excludedTokens.add(token);
}
}
public void setDirection(MergerToken token, MergeDirection direction) {
if (token.getDirection().equals(direction)) {
return;
}
int i = selectableTokensList.indexOf(token);
MergerToken reverse = token.createReverse(mergerTokenFactory);
selectableTokensList.set(i, reverse);
if (excludedTokens.remove(token)) {
excludedTokens.add(reverse);
}
// Repaint, so that "Operation" column updates properly
view.getTokens().repaint();
}
public void checkAllAction() {
boolean isCheckAllSelected = view.getCheckAll().isSelected();
if (isCheckAllSelected) {
excludedTokens.clear();
} else {
excludedTokens.addAll(selectableTokensList);
}
AbstractTableModel model = (AbstractTableModel) view.getTokens().getModel();
model.fireTableDataChanged();
}
public boolean isReverse() {
return isReverse;
}
public void reverseAllAction() {
isReverse = !isReverse;
for (int i = 0; i < selectableTokensList.size(); i++) {
MergerToken token = selectableTokensList.get(i);
MergerToken reverse = token.createReverse(mergerTokenFactory);
selectableTokensList.set(i, reverse);
if (excludedTokens.remove(token)) {
excludedTokens.add(reverse);
}
}
Collections.sort(selectableTokensList);
AbstractTableModel model = (AbstractTableModel) view.getTokens().getModel();
model.fireTableDataChanged();
}
}