/*******************************************************************************
* 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.mappingsmodel.db;
import java.util.List;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel;
import org.eclipse.persistence.tools.workbench.mappingsmodel.ProblemConstants;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWColumnHandle;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWHandle;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWHandle.NodeReferenceScrubber;
import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.db.ExternalForeignKeyColumnPair;
import org.eclipse.persistence.tools.workbench.utility.node.Node;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.tools.schemaframework.ForeignKeyConstraint;
/**
* Simple class that pairs a source column and a target column
* for a reference.
*/
public final class MWColumnPair extends MWModel {
private MWColumnHandle sourceColumnHandle;
public static final String SOURCE_COLUMN_PROPERTY = "sourceColumn";
private MWColumnHandle targetColumnHandle;
public static final String TARGET_COLUMN_PROPERTY = "targetColumn";
// ********** constructors **********
/**
* Default constructor - for TopLink use only.
*/
private MWColumnPair() {
super();
}
MWColumnPair(MWReference parent, MWColumn sourceColumn, MWColumn targetColumn) {
super(parent);
this.sourceColumnHandle.setColumn(sourceColumn);
this.targetColumnHandle.setColumn(targetColumn);
}
// ********** initialization **********
/**
* initialize persistent state
*/
protected void initialize(Node parent) {
super.initialize(parent);
this.sourceColumnHandle = new MWColumnHandle(this, this.buildSourceColumnScrubber());
this.targetColumnHandle = new MWColumnHandle(this, this.buildTargetColumnScrubber());
}
// ********** accessors **********
public MWReference getReference() {
return (MWReference) this.getParent();
}
public MWColumn getSourceColumn() {
return this.sourceColumnHandle.getColumn();
}
public void setSourceColumn(MWColumn sourceColumn) {
if ((sourceColumn != null) && (sourceColumn.getTable() != this.getReference().getSourceTable())) {
throw new IllegalArgumentException();
}
Object old = this.sourceColumnHandle.getColumn();
this.sourceColumnHandle.setColumn(sourceColumn);
this.firePropertyChanged(SOURCE_COLUMN_PROPERTY, old, sourceColumn);
}
public MWColumn getTargetColumn() {
return this.targetColumnHandle.getColumn();
}
public void setTargetColumn(MWColumn targetColumn) {
if ((targetColumn != null) && (targetColumn.getTable() != this.getReference().getTargetTable())) {
throw new IllegalArgumentException();
}
Object old = this.targetColumnHandle.getColumn();
this.targetColumnHandle.setColumn(targetColumn);
this.firePropertyChanged(TARGET_COLUMN_PROPERTY, old, targetColumn);
}
// ********** queries **********
/**
* the pair's name is calculated from the two column names
*/
public String getName() {
StringBuffer sb = new StringBuffer(200);
this.appendColumn(sb, this.getSourceColumn());
sb.append('=');
this.appendColumn(sb, this.getTargetColumn());
return sb.toString();
}
private void appendColumn(StringBuffer sb, MWColumn column) {
if (column != null) {
sb.append(column.qualifiedName());
}
}
/**
* return whether the column pair matches up the specified columns
*/
boolean pairs(MWColumn sourceColumn, MWColumn targetColumn) {
return (this.getSourceColumn() == sourceColumn) &&
(this.getTargetColumn() == targetColumn);
}
public MWTable sourceTable() {
return this.tableFrom(this.getSourceColumn());
}
public MWTable targetTable() {
return this.tableFrom(this.getTargetColumn());
}
private MWTable tableFrom(MWColumn column) {
return (column == null) ? null : column.getTable();
}
// ********** behavior **********
public void setSourceAndTargetColumns(MWColumn sourceColumn, MWColumn targetColumn) {
this.setSourceColumn(sourceColumn);
this.setTargetColumn(targetColumn);
}
// ********** problems **********
protected void addProblemsTo(List currentProblems) {
super.addProblemsTo(currentProblems);
if ((this.getSourceColumn() == null) || (this.getTargetColumn() == null)) {
currentProblems.add(this.buildProblem(ProblemConstants.INCOMPLETE_COLUMN_PAIR, this.getReference().getName()));
}
}
// ********** containment hierarchy **********
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
children.add(this.sourceColumnHandle);
children.add(this.targetColumnHandle);
}
private NodeReferenceScrubber buildSourceColumnScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWColumnPair.this.setSourceColumn(null);
}
public String toString() {
return "MWColumnPair.buildSourceColumnScrubber()";
}
};
}
private NodeReferenceScrubber buildTargetColumnScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWColumnPair.this.setTargetColumn(null);
}
public String toString() {
return "MWColumnPair.buildTargetColumnScrubber()";
}
};
}
// ********** importing/refreshing **********
/**
* return whether the column pair corresponds to the specified
* "external" column pair;
* if the column pair matches an "external" column pair we keep,
* otherwise, we remove it from the reference
*/
boolean matches(ExternalForeignKeyColumnPair externalPair) {
return (this.getSourceColumn() == this.sourceColumn(externalPair)) &&
(this.getTargetColumn() == this.targetColumn(externalPair));
}
/**
* return the column in the source table with the same name as the
* "external" column pair's source column
*/
private MWColumn sourceColumn(ExternalForeignKeyColumnPair externalPair) {
return this.getReference().sourceColumn(externalPair);
}
/**
* return the column in the target table with the same name as the
* "external" column pair's target column
*/
private MWColumn targetColumn(ExternalForeignKeyColumnPair externalPair) {
return this.getReference().targetColumn(externalPair);
}
// ********** runtime conversion **********
void configureRuntimeConstraint(ForeignKeyConstraint fkc) {
if ((this.getSourceColumn() == null) || (this.getTargetColumn() == null)) {
return;
}
fkc.addSourceField(this.getSourceColumn().getName());
fkc.addTargetField(this.getTargetColumn().getName());
}
// ********** displaying and printing **********
public String displayString() {
return this.getName();
}
public void toString(StringBuffer sb) {
super.toString(sb);
this.printColumnNameOn(this.getSourceColumn(), sb);
sb.append("=>");
this.printColumnNameOn(this.getTargetColumn(), sb);
}
private void printColumnNameOn(MWColumn column, StringBuffer sb) {
sb.append((column == null) ? "null" : column.getName());
}
// ********** TopLink methods **********
public static XMLDescriptor buildDescriptor() {
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWColumnPair.class);
XMLCompositeObjectMapping sourceColumnHandleMapping = new XMLCompositeObjectMapping();
sourceColumnHandleMapping.setAttributeName("sourceColumnHandle");
sourceColumnHandleMapping.setGetMethodName("getSourceColumnHandleForTopLink");
sourceColumnHandleMapping.setSetMethodName("setSourceColumnHandleForTopLink");
sourceColumnHandleMapping.setReferenceClass(MWColumnHandle.class);
sourceColumnHandleMapping.setXPath("source-column-handle");
descriptor.addMapping(sourceColumnHandleMapping);
XMLCompositeObjectMapping targetColumnHandleMapping = new XMLCompositeObjectMapping();
targetColumnHandleMapping.setAttributeName("targetColumnHandle");
targetColumnHandleMapping.setGetMethodName("getTargetColumnHandleForTopLink");
targetColumnHandleMapping.setSetMethodName("setTargetColumnHandleForTopLink");
targetColumnHandleMapping.setReferenceClass(MWColumnHandle.class);
targetColumnHandleMapping.setXPath("target-column-handle");
descriptor.addMapping(targetColumnHandleMapping);
return descriptor;
}
/**
* check for null
*/
private MWColumnHandle getSourceColumnHandleForTopLink() {
return (this.sourceColumnHandle.getColumn() == null) ? null : this.sourceColumnHandle;
}
private void setSourceColumnHandleForTopLink(MWColumnHandle handle) {
NodeReferenceScrubber scrubber = this.buildSourceColumnScrubber();
this.sourceColumnHandle = ((handle == null) ? new MWColumnHandle(this, scrubber) : handle.setScrubber(scrubber));
}
/**
* check for null
*/
private MWColumnHandle getTargetColumnHandleForTopLink() {
return (this.targetColumnHandle.getColumn() == null) ? null : this.targetColumnHandle;
}
private void setTargetColumnHandleForTopLink(MWColumnHandle handle) {
NodeReferenceScrubber scrubber = this.buildTargetColumnScrubber();
this.targetColumnHandle = ((handle == null) ? new MWColumnHandle(this, scrubber) : handle.setScrubber(scrubber));
}
}