/******************************************************************************* * 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.descriptor.relational; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.TreeSet; import java.util.Vector; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWDataField; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel; import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWColumn; import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWTable; 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.utility.CollectionTools; import org.eclipse.persistence.tools.workbench.utility.iterators.CloneIterator; import org.eclipse.persistence.tools.workbench.utility.iterators.FilteringIterator; import org.eclipse.persistence.tools.workbench.utility.iterators.NullIterator; import org.eclipse.persistence.tools.workbench.utility.iterators.TransformationIterator; 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.XMLCompositeCollectionMapping; public final class MWRelationalPrimaryKeyPolicy extends MWModel { protected Collection primaryKeyHandles; public final static String PRIMARY_KEYS_COLLECTION = "primaryKeys"; private NodeReferenceScrubber primaryKeyScrubber; // **************** Constructors ****************************************** /** Default constructor - for TopLink use only. */ private MWRelationalPrimaryKeyPolicy() { super(); } MWRelationalPrimaryKeyPolicy(MWRelationalTransactionalPolicy parent) { super(parent); } // **************** Initialization **************************************** protected void initialize(Node parent) { super.initialize(parent); this.primaryKeyHandles = new Vector(); } // **************** Primary keys ****************************************** private Iterator primaryKeyHandles() { return new CloneIterator(this.primaryKeyHandles) { protected void remove(Object current) { MWRelationalPrimaryKeyPolicy.this.removePrimaryKeyHandle((MWColumnHandle) current); } }; } void removePrimaryKeyHandle(MWColumnHandle handle) { this.primaryKeyHandles.remove(handle); this.fireItemRemoved(PRIMARY_KEYS_COLLECTION, handle.getColumn()); } public Iterator primaryKeys() { return new TransformationIterator(this.primaryKeyHandles()) { protected Object transform(Object next) { return ((MWColumnHandle) next).getColumn(); } }; } public int primaryKeysSize() { return this.primaryKeyHandles.size(); } public void addPrimaryKey(MWColumn primaryKey) { if (this.containsPrimaryKey(primaryKey)) { throw new IllegalArgumentException(primaryKey.toString()); } this.primaryKeyHandles.add(new MWColumnHandle(this, primaryKey, this.primaryKeyScrubber())); this.fireItemAdded(PRIMARY_KEYS_COLLECTION, primaryKey); } public void removePrimaryKey(MWColumn primaryKey) { for (Iterator stream = this.primaryKeys(); stream.hasNext(); ) { if (stream.next() == primaryKey) { stream.remove(); return; } } throw new IllegalArgumentException(primaryKey.toString()); } public boolean containsPrimaryKey(MWColumn primaryKey) { return CollectionTools.contains(this.primaryKeys(), primaryKey); } public void clearPrimaryKeys() { for (Iterator stream = this.primaryKeyHandles(); stream.hasNext(); ) { stream.next(); stream.remove(); } } // **************** Model Synchronization ************************************************ protected void addChildrenTo(List children) { super.addChildrenTo(children); synchronized (this.primaryKeyHandles) { children.addAll(this.primaryKeyHandles); } } private NodeReferenceScrubber primaryKeyScrubber() { if (this.primaryKeyScrubber == null) { this.primaryKeyScrubber = this.buildPrimaryKeyScrubber(); } return this.primaryKeyScrubber; } private NodeReferenceScrubber buildPrimaryKeyScrubber() { return new NodeReferenceScrubber() { public void nodeReferenceRemoved(Node node, MWHandle handle) { MWRelationalPrimaryKeyPolicy.this.removePrimaryKeyHandle((MWColumnHandle) handle); } public String toString() { return "MWRelationalPrimaryKeyPolicy.buildPrimaryKeyScrubber()"; } }; } // **************** "Public" ********************************************** /** * The relational descriptor's primary table changed. * Clear out old primary keys and initialize new primary keys. */ void descriptorPrimaryTableChanged(MWTable primaryTable) { this.clearPrimaryKeys(); if (primaryTable == null) { return; } for (Iterator stream = primaryTable.primaryKeyColumns(); stream.hasNext(); ) { this.addPrimaryKey((MWColumn) stream.next()); } } public MWTableDescriptor getTableDescriptor() { return (MWTableDescriptor) ((MWRelationalTransactionalPolicy) getParent()).getParent(); } public Iterator primaryKeyChoices() { MWTable primaryTable = getTableDescriptor().getPrimaryTable(); if (primaryTable == null) { return NullIterator.instance(); } return new FilteringIterator(primaryTable.columns()) { protected boolean accept(Object next) { return ! MWRelationalPrimaryKeyPolicy.this.containsPrimaryKey((MWColumn) next); } }; } // **************** Runtime Conversion ************************************ public void adjustRuntimeDescriptor(ClassDescriptor runtimeDescriptor) { for (Iterator primaryKeys = primaryKeys(); primaryKeys.hasNext(); ) { runtimeDescriptor.addPrimaryKeyField(((MWDataField) primaryKeys.next()).runtimeField()); } } // **************** TopLink methods *************************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(MWRelationalPrimaryKeyPolicy.class); XMLCompositeCollectionMapping primaryKeyHandlesMapping = new XMLCompositeCollectionMapping(); primaryKeyHandlesMapping.setReferenceClass(MWColumnHandle.class); primaryKeyHandlesMapping.setAttributeName("primaryKeyHandles"); primaryKeyHandlesMapping.setGetMethodName("getPrimaryKeyHandlesForTopLink"); primaryKeyHandlesMapping.setSetMethodName("setPrimaryKeyHandlesForTopLink"); primaryKeyHandlesMapping.setXPath("primary-key-handles/column-handle"); descriptor.addMapping(primaryKeyHandlesMapping); return descriptor; } private Collection getPrimaryKeyHandlesForTopLink() { synchronized (this.primaryKeyHandles) { return new TreeSet(this.primaryKeyHandles); } } private void setPrimaryKeyHandlesForTopLink(Collection handles) { for (Iterator stream = handles.iterator(); stream.hasNext(); ) { ((MWColumnHandle) stream.next()).setScrubber(this.primaryKeyScrubber()); } this.primaryKeyHandles = handles; } /** * this is called by MWTableDescriptor.legacyXXPrePostProjectBuild() */ protected void legacySetPrimaryKeys(Collection handles) { this.setPrimaryKeyHandlesForTopLink(handles); } }