/*
Copyright (C) 2009 by Claas Wilke (claaswilke@gmx.net)
This file is part of the Model Bus Plug-in of Dresden OCL2 for Eclipse.
Dresden OCL2 for Eclipse is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
Dresden OCL2 for Eclipse is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
for more details.
You should have received a copy of the GNU Lesser General Public License along
with Dresden OCL2 for Eclipse. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dresdenocl.modelinstancetype.types.base;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.osgi.util.NLS;
import org.dresdenocl.essentialocl.EssentialOclPlugin;
import org.dresdenocl.essentialocl.expressions.CollectionKind;
import org.dresdenocl.essentialocl.types.CollectionType;
import org.dresdenocl.modelinstancetype.ModelInstanceTypePlugin;
import org.dresdenocl.modelinstancetype.exception.AsTypeCastException;
import org.dresdenocl.modelinstancetype.internal.ModelInstanceMessages;
import org.dresdenocl.modelinstancetype.types.IModelInstanceCollection;
import org.dresdenocl.modelinstancetype.types.IModelInstanceElement;
import org.dresdenocl.pivotmodel.Type;
/**
* <p>
* Implements the interface {@link IModelInstanceCollection} for
* {@link JavaModelInstance} {@link Collection}s.
* </p>
*
* <p>
* This type is located in the ModelBus plug-in because the standard library and
* the Java model instance type plug-in both require such an implementation but
* are not allowed to know each other.
* </p>
*
* @author Claas Wilke
*/
public class JavaModelInstanceCollection<T extends IModelInstanceElement>
extends AbstractModelInstanceCollection<T> implements
IModelInstanceCollection<T> {
/** The {@link Logger} for this class. */
private static final Logger LOGGER =
ModelInstanceTypePlugin.getLogger(JavaModelInstanceCollection.class);
/**
* The {@link Object}s contained in this {@link JavaModelInstanceCollection}.
*/
private Collection<T> myContainedObjects;
/**
* <p>
* Creates a new {@link JavaModelInstanceCollection}.
* </p>
*
* @param containedObjects
* The {@link Object}s contained in this
* {@link JavaModelInstanceCollection}.
*/
protected JavaModelInstanceCollection(Collection<T> containedObjects,
Type elementType) {
/* Eventually debug the entry of this method. */
if (LOGGER.isDebugEnabled()) {
String msg;
msg = "JavaModelInstanceCollection("; //$NON-NLS-1$
msg += "containedObjects = " + containedObjects; //$NON-NLS-1$
msg += ")"; //$NON-NLS-1$
LOGGER.debug(msg);
}
// no else.
this.initialize(containedObjects);
/* Check if a List or set is given. */
if (containedObjects instanceof Set<?>) {
this.myType =
EssentialOclPlugin.getOclLibraryProvider().getOclLibrary()
.getSetType(elementType);
}
else {
this.myType =
EssentialOclPlugin.getOclLibraryProvider().getOclLibrary()
.getBagType(elementType);
}
/* Eventually debug the exit of this method. */
if (LOGGER.isDebugEnabled()) {
String msg;
msg = "JavaModelInstanceCollection(Collection<?>) - exit"; //$NON-NLS-1$
LOGGER.debug(msg);
}
// no else.
}
/**
* <p>
* Creates a new {@link JavaModelInstanceCollection}.
* </p>
*
* @param containedObjects
* The {@link Object}s contained in this
* {@link JavaModelInstanceCollection}.
* @param type
* The {@link CollectionType} that the created
* {@link JavaModelInstanceCollection} should have.
*/
protected JavaModelInstanceCollection(Collection<T> containedObjects,
CollectionType type) {
this.initialize(containedObjects);
/* Check if sets and sequences have the right type of collection. */
if (type.getKind().equals(CollectionKind.SET)
&& this.myContainedObjects != null
&& !(this.myContainedObjects instanceof Set<?>)) {
this.myContainedObjects = new HashSet<T>(this.myContainedObjects);
}
else if (type.getKind().equals(CollectionKind.ORDERED_SET)
&& this.myContainedObjects != null
&& !(this.myContainedObjects instanceof UniqueEList<?>)) {
this.myContainedObjects = new UniqueEList<T>(this.myContainedObjects);
}
else if (type.getKind().equals(CollectionKind.SEQUENCE)
&& this.myContainedObjects != null
&& !(this.myContainedObjects instanceof List<?>)) {
this.myContainedObjects = new ArrayList<T>(this.myContainedObjects);
}
else if (type.getKind().equals(CollectionKind.BAG)
&& this.myContainedObjects != null
&& !(this.myContainedObjects instanceof List<?>)) {
this.myContainedObjects = new ArrayList<T>(this.myContainedObjects);
}
// no else.
this.myType = type;
}
/**
* <p>
* A helper method that contains the common initialization of all constructors
* of {@link JavaModelInstanceCollection}.
* </p>
*
* @param containedObjects
* The {@link Object}s contained in this
* {@link JavaModelInstanceCollection}.
*/
private void initialize(Collection<T> containedObjects) {
this.myContainedObjects = containedObjects;
}
/*
* (non-Javadoc)
* @see org.dresdenocl.modelinstancetype.types.IModelInstanceElement
* #asType(org.dresdenocl.pivotmodel.Type)
*/
public IModelInstanceElement asType(Type type) throws AsTypeCastException {
if (type == null) {
throw new IllegalArgumentException(
"The parameter 'type' must not be null.");
}
// no else.
IModelInstanceElement result;
/* By default, the result is undefined. */
result = null;
/* Collections can only be casted to collections. */
if (type instanceof CollectionType) {
Collection<T> adaptedCollection;
CollectionType collectionType;
collectionType = (CollectionType) type;
switch (collectionType.getKind()) {
case BAG:
/* Create a new List to avoid side effects. */
adaptedCollection = new ArrayList<T>(this.myContainedObjects);
result =
new JavaModelInstanceCollection<T>(adaptedCollection,
EssentialOclPlugin.getOclLibraryProvider().getOclLibrary()
.getBagType(collectionType.getElementType()));
break;
case SEQUENCE:
/* Create a new List to avoid side effects. */
adaptedCollection = new ArrayList<T>(this.myContainedObjects);
result =
new JavaModelInstanceCollection<T>(adaptedCollection,
EssentialOclPlugin.getOclLibraryProvider().getOclLibrary()
.getSequenceType(collectionType.getElementType()));
break;
case SET:
/* Create a new Set to avoid side effects. */
adaptedCollection = new HashSet<T>(this.myContainedObjects);
result =
new JavaModelInstanceCollection<T>(adaptedCollection,
EssentialOclPlugin.getOclLibraryProvider().getOclLibrary()
.getSetType(collectionType.getElementType()));
break;
case ORDERED_SET:
/* Create a new List to avoid side effects. */
adaptedCollection = new UniqueEList<T>(this.myContainedObjects);
result =
new JavaModelInstanceCollection<T>(adaptedCollection,
EssentialOclPlugin.getOclLibraryProvider().getOclLibrary()
.getOrderedSetType(collectionType.getElementType()));
break;
default:
/*
* Else create the most common type of collection that is possible
* (Decide on the given java collection).
*/
/* Create a new List to avoid side effects. */
adaptedCollection = new ArrayList<T>(this.myContainedObjects);
result =
new JavaModelInstanceCollection<T>(adaptedCollection,
collectionType.getElementType());
break;
}
// end switch.
}
// no else.
/* Probably throw an AsTypeCastException. */
if (result == null) {
String msg;
msg = ModelInstanceMessages.IModelInstanceElement_CannotCast;
msg = NLS.bind(msg, this.getName(), type.getName());
throw new AsTypeCastException(msg);
}
// no else.
return result;
}
/*
* @see org.dresdenocl.modelinstancetype.types.IModelInstanceElement
* #copyForAtPre()
*/
public IModelInstanceElement copyForAtPre() {
/* For a collection, normally only the collection will be copied. */
return new JavaModelInstanceCollection<T>(this.myContainedObjects,
(CollectionType) this.getType());
}
/*
* (non-Javadoc)
* @see org.dresdenocl.modelinstancetype.types.IModelInstanceCollection
* #getCollection()
*/
public Collection<T> getCollection() {
return this.myContainedObjects;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuffer result = new StringBuffer();
result.append(this.getClass().getName());
result.append("[");
result.append(this.getCollection().toString());
result.append("]");
return result.toString();
}
}