/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.mof.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.edt.mof.EClass;
import org.eclipse.edt.mof.EField;
import org.eclipse.edt.mof.EFunction;
import org.eclipse.edt.mof.EMember;
import org.eclipse.edt.mof.EObject;
import org.eclipse.edt.mof.MofFactory;
import org.eclipse.edt.mof.serialization.ProxyEObject;
import org.eclipse.edt.mof.utils.EList;
public class EClassImpl extends EClassifierImpl implements EClass {
private static final long serialVersionUID = 1L;
private static int Slot_superTypes = 0;
private static int Slot_isAbstract = 1;
private static int Slot_isInterface = 2;
protected static int Slot_fields = 3;
protected static int Slot_functions = 4;
private static int totalSlots = 5;
public static int totalSlots() {
return totalSlots + EClassifierImpl.totalSlots();
}
static {
int offset = EClassifierImpl.totalSlots();
Slot_superTypes += offset;
Slot_isAbstract += offset;
Slot_isInterface += offset;
Slot_fields += offset;
Slot_functions += offset;
}
protected Class<EObject> clazz;
protected boolean noClazz = false;
private List<EField> allFields;
public EClassImpl() { super(); }
public EClassImpl(boolean init) {
if (init) {
EClass eClassClass = MofFactory.INSTANCE.getEClassClass();
eClassClass.initialize(this);
}
}
@Override
@SuppressWarnings("unchecked")
public List<EClass> getSuperTypes() {
if (slotGet(Slot_superTypes) == null) {
slotSet(Slot_superTypes, new EList<EClass>());
}
return (List<EClass>)slotGet(Slot_superTypes);
}
/**
* Basic method to use to add supertypes to an EClass which will
* validate basic inheritance rules as well as add appropriate
* fields for handling multiple inheritance
* @param eClass
*/
@Override
public void addSuperTypes(List<EClass> superTypes) {
if (superTypes.isEmpty()) return;
getSuperTypes().addAll(superTypes);
if (superTypes.size() > 1) {
List<EField> fields = new ArrayList<EField>();
collectAllUniqueFields(fields);
for (EField field : fields) {
addMember((EField)field.clone());
}
allFields = null;
}
return;
}
@Override
public boolean isAbstract() {
if (slotGet(Slot_isAbstract) == null) {
slotSet(Slot_isAbstract, Boolean.FALSE);
}
return (Boolean)slotGet(Slot_isAbstract);
}
@Override
public void setIsAbstract(boolean value) {
slotSet(Slot_isAbstract, value);
}
@Override
public boolean isInterface() {
if (slotGet(Slot_isInterface) == null) {
slotSet(Slot_isInterface, Boolean.FALSE);
}
return (Boolean)slotGet(Slot_isInterface);
}
@Override
public void setIsInterface(boolean value) {
slotSet(Slot_isInterface, value);
}
@Override
@SuppressWarnings("unchecked")
public List<EField> getEFields() {
if (slotGet(Slot_fields) == null) {
slotSet(Slot_fields, new EList<EField>());
}
return (List<EField>)slotGet(Slot_fields);
}
@Override
// Handle returning fields from super type as well
public EField getEField(String name) {
EField field = null;
for (EField f : getEFields()) {
if (f.getName().equalsIgnoreCase(name))
return f;
}
if (field == null) {
if (!getSuperTypes().isEmpty()) {
field = getSuperTypes().get(0).getEField(name);
}
}
return field;
}
@Override
public EField getEField(int index) {
return getAllEFields().get(index);
}
@Override
public List<EField> getAllEFields() {
List<EField> allFields = new EList<EField>();
allFields.addAll(getEFields());
if (!getSuperTypes().isEmpty()) {
allFields.addAll(0, getSuperTypes().get(0).getAllEFields());
}
return allFields;
}
private void collectAllUniqueFields(List<EField> fields) {
if (getSuperTypes().isEmpty()) {
fields.addAll(getEFields());;
}
else {
List<EField> common = getAllEFields();
for (EClass superType : getSuperTypes()) {
for (EField field : superType.getAllEFields()) {
if (common.indexOf(field) == -1 && fields.indexOf(field) == -1) {
fields.add(field);
}
}
}
}
}
@Override
@SuppressWarnings("unchecked")
public List<EFunction> getEFunctions() {
if (slotGet(Slot_functions) == null) {
slotSet(Slot_functions, new EList<EFunction>());
}
return (List<EFunction>)slotGet(Slot_functions);
}
@Override
public void addMember(EMember mbr) {
mbr.setDeclarer(this);
if (mbr instanceof EField) {
getEFields().add((EField)mbr);
allFields = null;
}
else if (mbr instanceof EFunction) {
getEFunctions().add((EFunction)mbr);
}
else {
throw new IllegalArgumentException("Object " + mbr.toString() + " is not a valid member type for " + this.toString());
}
}
public int getTotalSlots() {
int totalSlots = getEFields().size();
if (!getSuperTypes().isEmpty()) {
totalSlots += ((EClassImpl)getSuperTypes().get(0)).getTotalSlots();
}
return totalSlots;
}
@Override
public EObject newInstance() {
return newInstance(true, true);
}
@Override
public EObject newInstance(boolean init) {
return newInstance(init, true);
}
@Override
public EObject newInstance(boolean init, boolean useInitialValues) {
EObject obj = null;
if (getClazz() == null) {
obj = newEObject();
} else {
try {
obj = clazz.newInstance();
} catch (Exception e) {
obj = newEObject();
}
}
if (init) {
initialize(obj, useInitialValues);
}
return obj;
}
/**
* Override this method is subclasses to create different EObject implementation class
* @return
*/
public EObject newEObject() {
return new EObjectImpl();
}
@SuppressWarnings("unchecked")
/**
* This method works on the convention that the implementation package
* is named by extending the interface package with "impl" and that the
* class names are referenced by extending the Interface class name with
* "Impl". Failure to follow this convention results in the method always
* returning null.
*/
protected Class<EObject> getClazz() {
if (noClazz) return null;
if (clazz == null) {
try {
String typeSignature = getImplTypeSignature();
clazz = (Class<EObject>)Class.forName(typeSignature);
} catch (ClassNotFoundException e) {
for (EClass superType : getSuperTypes()) {
clazz = ((EClassImpl)superType).getClazz();
if (clazz != null) break;
}
if (clazz == null) noClazz = true;
}
}
return clazz;
}
public String getImplTypeSignature() {
return getCaseSensitivePackageName() + ".impl." + getName() + "Impl";
}
@Override
public void initialize(EObject object) {
initialize(object, true);
}
@Override
public void initialize(EObject object, boolean useInitialValues) {
((EObjectImpl)object).init(this, useInitialValues);
}
@Override
public boolean isInstance(EObject object) {
if (object == null) return true;
if (object instanceof ProxyEObject) return true;
if (!(object instanceof EObject)) return false;
EClass type = (EClass)((EObject)object).getEClass();
return ( type == this || type.isSubClassOf(this));
}
@Override
public boolean isSubClassOf(EClass eClass) {
if (!getSuperTypes().isEmpty()) {
for (EClass superType : getSuperTypes()) {
if (superType == eClass) {
return true;
}
}
for (EClass superType : getSuperTypes()) {
if (superType.isSubClassOf(eClass)) return true;
}
return false;
}
else {
return false;
}
}
}