blob: c3083f266fb1ed2f4d670927c877bb19c629dd89 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2015 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.core.compiler.model;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AbstractAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.CallinMethodMappingsAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementor;
/**
* @author stephan
*/
public class ModelElement {
/** OT-specific bytecode attributes for this model element. */
public AbstractAttribute[] _attributes;
/** Add an OT-specific bytecode attribute. */
public void addAttribute (AbstractAttribute attr) {
if (this._attributes == null) {
this._attributes = new AbstractAttribute[]{attr};
} else {
int len = this._attributes.length;
AbstractAttribute[] newAttrs = new AbstractAttribute[len+1];
System.arraycopy(this._attributes, 0, newAttrs, 0, len);
newAttrs[len] = attr;
this._attributes = newAttrs;
}
}
/**
* Add an attribute possibly merging it with an existing attribute of the same kind.
* @param attr
*/
public void addOrMergeAttribute (AbstractAttribute attr) {
AbstractAttribute existingAttr = null;
if (this._attributes != null) {
for (int i = 0; i < this._attributes.length; i++) {
if (this._attributes[i].nameEquals(attr)) {
existingAttr = this._attributes[i];
break;
}
}
}
if (existingAttr == null) {
if (!attr.nameEquals(IOTConstants.CALLIN_METHOD_MAPPINGS))
{
addAttribute(attr);
return;
}
addAttribute(existingAttr = new CallinMethodMappingsAttribute(new CallinMappingDeclaration[0]));
}
// this call also creates bindings from the attribute:
existingAttr.merge(this, attr);
if (attr.nameEquals(IOTConstants.CALLIN_METHOD_MAPPINGS))
CallinImplementor.checkCopyCallinBinding((CallinMethodMappingsAttribute)attr, this);
// FIXME(SH): enable once CallinImplemtorDyn implements this:
// if (attr.nameEquals(OTDynCallinBindingsAttribute.ATTRIBUTE_NAME))
// CallinImplementorDyn.checkCopyCallinBinding((OTDynCallinBindingsAttribute)attr, this);
}
/** Find an attribute by its name, return null if not present. */
public AbstractAttribute getAttribute(char[] name) {
if (this._attributes == null)
return null;
for (AbstractAttribute attr : this._attributes) {
if (attr.nameEquals(name))
return attr;
}
return null;
}
public void removeAttribute(AbstractAttribute attr) {
if (this._attributes == null) return;
int newLength = this._attributes.length-1;
AbstractAttribute[] newAttributes = new AbstractAttribute[newLength];
int i = 0;
for (AbstractAttribute anAttr : this._attributes) {
if (anAttr != attr) {
if (i == newLength)
return; // trying to insert the last item means: not found, so just don't change
newAttributes[i++] = anAttr;
}
}
this._attributes = newAttributes;
}
/**
* Write all OT-specific attributes of a given type binding to the given class file
* @param type the element whose attributes should be written
* @param file the destination class file
* @return number of attributes written
*/
public static int writeAttributes(ReferenceBinding type, ClassFile file)
{
int count = 0;
if (type.isTeam())
count += type.getTeamModel().writeAttributes(file);
if (type.isRole() && (type.roleModel != null))
count += type.roleModel.writeAttributes(file);
if (type.model != null)
count += type.model.writeAttributes(file);
return count;
}
/**
* Write all OT-specific attributes of this model element to the given class file.
* @param file
* @return number of attributes written
*/
public int writeAttributes(ClassFile file)
{
if (this._attributes == null)
return 0;
int count = 0;
for (int i=0; i<this._attributes.length; i++)
if (this._attributes[i].setupForWriting()) {
this._attributes[i].write(file);
count++;
}
return count;
}
public static void evaluateLateAttributes(ReferenceBinding type, int state)
{
if (type.isTeam())
type.getTeamModel().evaluateLateAttributes(state);
if (type.isRole() && (type.roleModel != null)) {
type.roleModel.evaluateLateAttributes(state);
// method mappings in role interfaces need to be implemented them in sub-classes:
type.roleModel.implementMethodBindingsFromSuperinterfaces();
}
/*
if (type.model != null)
count += type.model.evaluateLateAttributes();
*/
}
}