/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.mapping.factory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.mapping.Mapping;
import org.eclipse.emf.mapping.MappingRoot;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.I18nUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.util.ModelContents;
import org.teiid.designer.core.util.ModelResourceContainerFactory;
import org.teiid.designer.mapping.PluginConstants;
import org.teiid.designer.metamodels.transformation.FragmentMappingRoot;
/**
* The <code>FragmentMappingAdapter</code> class is responsible for managing the
* {@link org.teiid.designer.metamodels.transformation.FragmentMappingRoot) of a tree root.
*
* @since 8.0
*/
public class FragmentMappingAdapter implements PluginConstants {
// /////////////////////////////////////////////////////////////////////////////////////////////
// CONSTANTS
// /////////////////////////////////////////////////////////////////////////////////////////////
/** Properties file key prefix. Used for logging and localization. */
private static final String PREFIX = I18nUtil.getPropertyPrefix(FragmentMappingAdapter.class);
// /////////////////////////////////////////////////////////////////////////////////////////////
// FIELDS
// /////////////////////////////////////////////////////////////////////////////////////////////
/** The fragment root. */
private FragmentMappingRoot fragmentRoot;
/** The tree root. */
private EObject root;
// /////////////////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
// /////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructs a <code>FragmentMappingAdapter</code> for the specified tree root. The fragment roots are found by using the
* transformation container.
*
* @param theTreeRoot the tree root
* @throws IllegalArgumentException if input is <code>null</code>
*/
public FragmentMappingAdapter( EObject theTreeRoot ) {
CoreArgCheck.isNotNull(theTreeRoot);
root = theTreeRoot;
// get all mapping roots for the tree root. cache each fragment root. however, should only have
// one fragment root. this fragment root will have nested mappings each of which is a fragment.
List fragmentRoots = new ArrayList();
ModelContents mc = ModelerCore.getModelEditor().getModelContents(root);
if (mc != null) {
List mappingRoots = mc.getTransformations(theTreeRoot);
if ((mappingRoots == null) || mappingRoots.isEmpty()) {
} else {
for (int size = mappingRoots.size(), i = 0; i < size; i++) {
MappingRoot mappingRoot = (MappingRoot)mappingRoots.get(i);
if (mappingRoot instanceof FragmentMappingRoot) {
fragmentRoots.add(mappingRoot);
}
}
}
setFragmentRoots(fragmentRoots);
}
}
/**
* Constructs a <code>TreeMappingAdapter</code> for the specified tree root.
*
* @param theTreeRoot the tree root
* @param theFragmentRoots the fragment roots
* @throws IllegalArgumentException if either input is <code>null</code>
*/
public FragmentMappingAdapter( EObject theTreeRoot,
List theFragmentRoots ) {
CoreArgCheck.isNotNull(theTreeRoot);
root = theTreeRoot;
setFragmentRoots(theFragmentRoots);
}
// /////////////////////////////////////////////////////////////////////////////////////////////
// METHODS
// /////////////////////////////////////////////////////////////////////////////////////////////
/**
* Adds a fragment mapping.
*
* @param theFragmentReference the reference to the fragment
* @param theFragment the fragment
* @throws IllegalArgumentException if either input is <code>null</code>
*/
public void addFragment( EObject theFragmentReference, // NO_UCD
EObject theFragment ) {
CoreArgCheck.isNotNull(theFragmentReference);
CoreArgCheck.isNotNull(theFragment);
if (fragmentRoot == null) {
ModelContents mc = ModelerCore.getModelEditor().getModelContents(root);
if (mc != null) {
// bmlTODO: We need to refactor the createFragmentMapping() logic similar to
// the createSqlTransformationMapping() and createTreeMapping() so the additional
// work to allow full "Undoable" events to be added.
fragmentRoot = ModelResourceContainerFactory.createNewFragmentMappingRoot(root);
}
}
boolean createFragment = true;
List mappings = getMappings();
// make sure fragment reference is not already in a fragment
if (!mappings.isEmpty()) {
for (int size = 0, i = 0; i < size; i++) {
Mapping mapping = (Mapping)mappings.get(i);
EObject fragmentReference = getFragmentReference(mapping);
if (theFragmentReference.equals(fragmentReference)) {
createFragment = false;
break;
}
}
}
// create or log error
if (createFragment) {
fragmentRoot.createMapping(Collections.singletonList(theFragment), Collections.singletonList(theFragmentReference));
} else {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "duplicateFragment", new Object[] {theFragmentReference})); //$NON-NLS-1$
}
}
/**
* Indicates if fragments exist for this adapter's tree root.
*
* @return <code>true</code> if contains one or more fragments; <code>false</code> otherwise.
*/
public boolean containsFragments() {
return (getFragmentCount() > 0);
}
/**
* Obtains the fragment for the specified fragment reference.
*
* @param theFramentReference the fragment reference whose fragment is being requested
* @return the fragment or <code>null</code> if none exists
* @throws IllegalArgumentException if input is <code>null</code>
*/
public EObject getFragment( EObject theFragmentReference ) {
CoreArgCheck.isNotNull(theFragmentReference);
EObject result = null;
if (containsFragments()) {
List fragmentMappings = getMappings();
if (!fragmentMappings.isEmpty()) {
for (int size = fragmentMappings.size(), i = 0; i < size; i++) {
Mapping mapping = (Mapping)fragmentMappings.get(i);
EObject fragmentReference = getFragmentReference(mapping);
// find the fragment reference. each output list should only have one entry.
if (theFragmentReference.equals(fragmentReference)) {
result = getFragment(mapping);
break;
}
}
}
}
return result;
}
/**
* Obtains the fragment of the specified <code>Mapping</code>.
*
* @param theMapping the <code>Mapping</code> whose fragment is being requested
* @return the fragment (should never be <code>null</code>)
* @throws IllegalArgumentException if input is <code>null</code>
*/
private EObject getFragment( Mapping theMapping ) {
CoreArgCheck.isNotNull(theMapping);
List inputs = theMapping.getInputs();
return (inputs.isEmpty()) ? null : (EObject)inputs.get(0);
}
/**
* Obtains the number of fragment <code>Mapping</code>s.
*
* @return the count of fragment <code>Mapping</code>s
*/
private int getFragmentCount() {
return (fragmentRoot == null) ? 0 : getMappings().size();
}
/**
* Obtains the fragment reference of the specified <code>Mapping</code>.
*
* @param theMapping the <code>Mapping</code> whose fragment reference is being requested
* @return the fragment reference (should never be <code>null</code>)
* @throws IllegalArgumentException if input is <code>null</code>
*/
private EObject getFragmentReference( Mapping theMapping ) {
CoreArgCheck.isNotNull(theMapping);
List outputs = theMapping.getOutputs();
return (outputs.isEmpty()) ? null : (EObject)outputs.get(0);
}
public EObject getInputSet() {
EObject result = null;
if (fragmentRoot != null) {
// fragmentRoot.getHelper();
}
return result;
}
public EObject getInputSet( EObject theFragmentReference ) { // NO_UCD
CoreArgCheck.isNotNull(theFragmentReference);
EObject result = null;
if (containsFragments()) {
List mappings = getMappings();
if (!mappings.isEmpty()) {
for (int size = mappings.size(), i = 0; i < size; i++) {
Mapping mapping = (Mapping)mappings.get(i);
EObject fragmentReference = getFragmentReference(mapping);
if (theFragmentReference.equals(fragmentReference)) {
// result = mapping.getHelper();
}
}
}
}
return result;
}
/**
* Obtains the fragment <code>Mapping</code>s.
*
* @return the <code>Mapping</code>s (may be empty) or <code>null</code> if no fragment root exists
*/
private List getMappings() {
return (fragmentRoot == null) ? null : fragmentRoot.getNested();
}
/**
* Removes the specified fragment from this adapter's tree root.
*
* @param theFragmentReference the fragment whose fragment mapping is being removed
* @throws IllegalArgumentException if input is <code>null</code>
*/
public void removeFragment( EObject theFragmentReference ) { // NO_UCD
CoreArgCheck.isNotNull(theFragmentReference);
if (containsFragments()) {
boolean foundIt = false;
List mappings = getMappings();
for (int size = mappings.size(), i = 0; i < size; i++) {
Mapping mapping = (Mapping)mappings.get(i);
EObject fragmentReference = getFragmentReference(mapping);
if (theFragmentReference.equals(fragmentReference)) {
foundIt = true;
break;
}
}
if (!foundIt) {
Util.log(IStatus.ERROR,
Util.getString(PREFIX + "removeFragmentProblemNotFound", new Object[] {theFragmentReference})); //$NON-NLS-1$
}
} else {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "removeFragmentProblemNoRoot", new Object[] {theFragmentReference})); //$NON-NLS-1$
}
}
/**
* Sets the {@link FragmentMappingRoot} from the specified input. Should only have one root.
*
* @param theFragmentRoots the collection of fragment roots
* @throws IllegalArgumentException if input is <code>null</code>
*/
private void setFragmentRoots( List theFragmentRoots ) {
CoreArgCheck.isNotNull(theFragmentRoots);
if (!theFragmentRoots.isEmpty()) {
for (int size = theFragmentRoots.size(), i = 0; i < size; i++) {
Object potentialRoot = theFragmentRoots.get(i);
if (potentialRoot instanceof FragmentMappingRoot) {
if (fragmentRoot == null) {
fragmentRoot = (FragmentMappingRoot)potentialRoot;
} else {
Util.log(IStatus.ERROR,
Util.getString(PREFIX + "multipleFragmentRootsFound", new Object[] {potentialRoot})); //$NON-NLS-1$
}
} else {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "notFragmentRoot", new Object[] {potentialRoot})); //$NON-NLS-1$
}
}
}
}
}