/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.mappingsplugin.ui.mapping.relational;
import java.util.Iterator;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContextHolder;
import org.eclipse.persistence.tools.workbench.framework.resources.ResourceRepository;
import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWColumn;
import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWColumnPair;
import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWTable;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.relational.MWRelationalDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWOneToOneMapping;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.db.ColumnPairsPanel;
import org.eclipse.persistence.tools.workbench.uitools.app.CollectionAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.CollectionPropertyValueModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.CollectionValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ValuePropertyPropertyValueModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.ColumnAdapter;
/**
* this is the panel used to pick (and/or build) the reference from the
* mapping's "parent" descriptor's table(s) to the reference descriptor,
* or vice-versa (target foreign key), or some combination of both(!)
*/
final class OneToOneTableReferencePanel
extends AbstractTableReferencePanel
{
OneToOneTableReferencePanel(PropertyValueModel oneToOneMappingHolder, WorkbenchContextHolder contextHolder) {
super(oneToOneMappingHolder, contextHolder);
}
/**
* add a column for the "target foreign key" flag
*/
protected ColumnPairsPanel buildColumnPairsPanel() {
return new ExpandedColumnPairsPanel(this.getSubjectHolder(), this.getWorkbenchContextHolder(), this.buildTableReferenceHolder());
}
/**
* the reference source can be on either side;
* default to a "source" foreign key
*/
protected MWTable defaultNewReferenceSourceTable() {
Iterator candidateTables = this.mapping().getParentRelationalDescriptor().candidateTables();
return candidateTables.hasNext() ? (MWTable) candidateTables.next() : null;
}
/**
* the reference target can be on either side
* default to a "source" foreign key
*/
protected MWTable defaultNewReferenceTargetTable() {
MWRelationalDescriptor descriptor = (MWRelationalDescriptor) this.mapping().getReferenceDescriptor();
if (descriptor == null) {
return null;
}
Iterator candidateTables = descriptor.candidateTables();
return candidateTables.hasNext() ? (MWTable) candidateTables.next() : null;
}
private MWOneToOneMapping mapping() {
return (MWOneToOneMapping) this.subject();
}
// ********** member classes **********
private static class ExpandedColumnPairsPanel extends ColumnPairsPanel {
private ValueModel mappingHolder;
private ExpandedColumnPairsPanel(ValueModel mappingHolder, WorkbenchContextHolder contextHolder, PropertyValueModel referenceHolder) {
super(contextHolder, referenceHolder);
this.mappingHolder = mappingHolder;
}
protected ColumnAdapter buildColumnAdapter() {
return new ExpandedColumnPairsColumnAdapter(this, this.resourceRepository());
}
ValueModel getMappingHolder() {
return this.mappingHolder;
}
}
private static class ExpandedColumnPairsColumnAdapter implements ColumnAdapter {
private ExpandedColumnPairsPanel panel;
private ResourceRepository resourceRepository;
private static final String[] COLUMN_NAME_KEYS = new String[] {
"ONE_TO_ONE_SOURCE_FIELD_COLUMN",
"ONE_TO_ONE_TARGET_FIELD_COLUMN",
"ONE_TO_ONE_TARGET_FOREIGN_KEY"
};
private static final int COLUMN_COUNT = 3;
private static final int SOURCE_COLUMN_COLUMN = 0;
private static final int TARGET_COLUMN_COLUMN = 1;
private static final int TARGET_FOREIGN_KEY_COLUMN = 2;
private ExpandedColumnPairsColumnAdapter(ExpandedColumnPairsPanel panel, ResourceRepository resourceRepository) {
super();
this.panel = panel;
this.resourceRepository = resourceRepository;
}
// ********** ColumnAdapter implementation **********
public PropertyValueModel[] cellModels(Object subject) {
MWColumnPair columnPair = (MWColumnPair) subject;
PropertyValueModel[] result = new PropertyValueModel[COLUMN_COUNT];
result[SOURCE_COLUMN_COLUMN] = this.buildSourceColumnAdapter(columnPair);
result[TARGET_COLUMN_COLUMN] = this.buildTargetColumnAdapter(columnPair);
result[TARGET_FOREIGN_KEY_COLUMN] = this.buildTargetForeignKeyAdapter(columnPair);
return result;
}
public Class getColumnClass(int index) {
switch (index) {
case TARGET_FOREIGN_KEY_COLUMN:
return Boolean.class;
default:
return Object.class;
}
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public String getColumnName(int index) {
return this.resourceRepository.getString(COLUMN_NAME_KEYS[index]);
}
public boolean isColumnEditable(int index) {
return true;
}
// ********** internal methods **********
private PropertyValueModel buildSourceColumnAdapter(MWColumnPair columnPair) {
PropertyValueModel adapter = new PropertyAspectAdapter(MWColumnPair.SOURCE_COLUMN_PROPERTY, columnPair) {
protected Object getValueFromSubject() {
return ((MWColumnPair) this.subject).getSourceColumn();
}
protected void setValueOnSubject(Object value) {
((MWColumnPair) this.subject).setSourceColumn((MWColumn) value);
}
};
return new ValuePropertyPropertyValueModelAdapter(adapter, MWColumn.NAME_PROPERTY);
}
private PropertyValueModel buildTargetColumnAdapter(MWColumnPair columnPair) {
PropertyValueModel adapter = new PropertyAspectAdapter(MWColumnPair.TARGET_COLUMN_PROPERTY, columnPair) {
protected Object getValueFromSubject() {
return ((MWColumnPair) this.subject).getTargetColumn();
}
protected void setValueOnSubject(Object value) {
((MWColumnPair) this.subject).setTargetColumn((MWColumn) value);
}
};
return new ValuePropertyPropertyValueModelAdapter(adapter, MWColumn.NAME_PROPERTY);
}
ValueModel mappingHolder() {
return this.panel.getMappingHolder();
}
private PropertyValueModel buildTargetForeignKeyAdapter(MWColumnPair columnPair) {
return new TargetForeignKeyAdapter(this.buildTargetForeignKeysAdapter(), this, columnPair);
}
private CollectionValueModel buildTargetForeignKeysAdapter() {
return new CollectionAspectAdapter(this.mappingHolder(), MWOneToOneMapping.TARGET_FOREIGN_KEYS_COLLECTION) {
protected Iterator getValueFromSubject() {
return ((MWOneToOneMapping) this.subject).targetForeignKeys();
}
};
}
}
private static class TargetForeignKeyAdapter extends CollectionPropertyValueModelAdapter {
private ExpandedColumnPairsColumnAdapter columnAdapter;
private MWColumnPair columnPair;
public TargetForeignKeyAdapter(CollectionValueModel collectionHolder, ExpandedColumnPairsColumnAdapter columnAdapter, MWColumnPair columnPair) {
super(collectionHolder);
this.columnAdapter = columnAdapter;
this.columnPair = columnPair;
}
// ********** ValueModel implementation **********
/**
* always return a Boolean
*/
public Object getValue() {
Object result = super.getValue();
return (result == null) ? Boolean.FALSE : result;
}
// ********** PropertyValueModel implementation **********
public void setValue(Object value) {
if (this.booleanValue()) {
if ( ! this.booleanValueOf(value)) {
// the value is changing from true to false
this.mapping().removeTargetForeignKey(this.columnPair);
}
} else {
if (this.booleanValueOf(value)) {
// the value is changing from false to true
this.mapping().addTargetForeignKey(this.columnPair);
}
}
}
// ********** CollectionPropertyValueModelAdapter implementation **********
protected Object buildValue() {
return Boolean.valueOf(this.columnPairIsTargetForeignKey());
}
// ********** internal methods **********
private boolean booleanValue() {
return this.booleanValueOf(this.value);
}
private boolean booleanValueOf(Object b) {
return (b == null) ? false : ((Boolean) b).booleanValue();
}
private ValueModel mappingHolder() {
return this.columnAdapter.mappingHolder();
}
private MWOneToOneMapping mapping() {
return (MWOneToOneMapping) this.mappingHolder().getValue();
}
private boolean columnPairIsTargetForeignKey() {
MWOneToOneMapping mapping = this.mapping();
if (mapping == null) {
return false; // the mapping will be null when the table is cleared out
}
return mapping.containsTargetForeignKey(this.columnPair);
}
}
}