| /******************************************************************************* |
| * Copyright (c) 2005, 2007 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 |
| * |
| |
| *******************************************************************************/ |
| package org.eclipse.dltk.core.mixin; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceChangeEvent; |
| import org.eclipse.core.resources.IResourceChangeListener; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.ListenerList; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.ElementChangedEvent; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IElementChangedListener; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelElementDelta; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.mixin.IMixinRequestor.ElementInfo; |
| import org.eclipse.dltk.core.search.SearchEngine; |
| import org.eclipse.dltk.core.search.indexing.IIndexConstants; |
| import org.eclipse.dltk.internal.core.ModelCache; |
| import org.eclipse.dltk.internal.core.mixin.IInternalMixinElement; |
| import org.eclipse.dltk.internal.core.mixin.MixinCache; |
| import org.eclipse.dltk.internal.core.mixin.MixinManager; |
| |
| public class MixinModel { |
| public static final String SEPARATOR = "" + IIndexConstants.SEPARATOR; |
| private MixinCache cache = null; |
| |
| /** |
| * Contains map of source modules to mixin elemens. |
| */ |
| private Map elementToMixinCache = new HashMap(); |
| private IDLTKLanguageToolkit toolkit = null; |
| |
| private MixinRequestor mixinRequestor = new MixinRequestor(); |
| |
| private ISourceModule currentModule; |
| private Set modulesToReparse = new HashSet(); // list of modules required |
| // to be reparsed. |
| public long removes = 1; |
| double ratio = 10000; |
| |
| public MixinModel(IDLTKLanguageToolkit toolkit) { |
| this.toolkit = toolkit; |
| |
| // long maxMemory = Runtime.getRuntime().freeMemory(); |
| |
| this.cache = new MixinCache( |
| (int) (ModelCache.DEFAULT_ROOT_SIZE * ratio)); |
| DLTKCore.addElementChangedListener(changedListener); |
| ResourcesPlugin.getWorkspace().addResourceChangeListener( |
| changedListener); |
| } |
| |
| public void stop() { |
| DLTKCore.removeElementChangedListener(changedListener); |
| ResourcesPlugin.getWorkspace().removeResourceChangeListener( |
| changedListener); |
| } |
| |
| public IMixinElement get(String key) { |
| |
| if (DLTKCore.VERBOSE) { |
| } |
| if (notExistKeysCache.contains(key)) { |
| return null; |
| } |
| if (removes == 0) { |
| if (cache.get(key) == null) { |
| return null; |
| } |
| } |
| MixinElement element = getCreateEmpty(key); |
| if (DLTKCore.VERBOSE) { |
| System.out.println("Filling ratio:" + this.cache.fillingRatio()); |
| this.cache.printStats(); |
| } |
| buildElementTree(element); |
| if (element.isFinal() && element.sourceModules.size() > 0) { |
| existKeysCache.add(key); |
| return element; |
| } |
| notExistKeysCache.add(key); |
| synchronized (this.cache) { |
| this.cache.remove(element); |
| cache.resetSpaceLimit(ModelCache.DEFAULT_ROOT_SIZE, element); |
| this.cache.removeKey(element); |
| } |
| return null; |
| } |
| |
| public IMixinElement[] find(String pattern, long delta) { |
| Map set = new HashMap(); |
| |
| ISourceModule[] containedModules = SearchEngine.searchMixinSources( |
| pattern, toolkit, set); |
| Set modules = new HashSet(); |
| modules.addAll(Arrays.asList(containedModules)); |
| |
| if (modules.size() == 0) { |
| return new IMixinElement[0]; |
| } |
| |
| // long start = System.currentTimeMillis(); |
| // for (int i = 0; i < containedModules.length; ++i) { |
| for (Iterator iterator = modules.iterator(); iterator.hasNext();) { |
| ISourceModule module = (ISourceModule) iterator.next(); |
| reportModule(module); |
| // if (delta != -1) { |
| // // if (System.currentTimeMillis() - start > delta) { |
| // // System.out.println("Mixin timeout break:" |
| // // + Long.toString(System.currentTimeMillis() - start) |
| // // + ":" |
| // // + Integer.toString(containedModules.length - i)); |
| // // break; |
| // // } |
| // } |
| } |
| |
| List result = new ArrayList(); |
| |
| // int i = 0; |
| for (Iterator iterator = set.keySet().iterator(); iterator.hasNext();) { |
| ISourceModule module = (ISourceModule) iterator.next(); |
| if (this.elementToMixinCache.containsKey(module)) { |
| Set keys = (Set) set.get(module); |
| for (Iterator iterator2 = keys.iterator(); iterator2.hasNext();) { |
| String key = (String) iterator2.next(); |
| MixinElement element = getCreateEmpty(key); |
| markElementAsFinal(element); |
| result.add(element); |
| existKeysCache.add(key); |
| } |
| } |
| } |
| |
| return (IMixinElement[]) result |
| .toArray(new IMixinElement[result.size()]); |
| } |
| |
| public IMixinElement[] find(String pattern) { |
| return find(pattern, -1); |
| } |
| |
| public String[] findKeys(String pattern) { |
| return SearchEngine.searchMixinPatterns(pattern, toolkit); |
| } |
| |
| private Set existKeysCache = new HashSet(); |
| private Set notExistKeysCache = new HashSet(); |
| |
| public boolean keyExists(String key) { |
| // TODO: For this version we cache all information, so should be 0. |
| if (removes == 0) { |
| return this.cache.get(key) != null; |
| } |
| MixinElement e = (MixinElement) this.cache.get(key); |
| if (e != null && e.sourceModules.size() > 0) { |
| return true; |
| } |
| if (existKeysCache.contains(key)) { |
| return true; |
| } |
| if (notExistKeysCache.contains(key)) { |
| return false; |
| } |
| boolean exist = get(key) != null; |
| // System.out.println("1"); |
| if (exist) { |
| if (existKeysCache.size() > 500000) { |
| existKeysCache.clear(); |
| } |
| existKeysCache.add(key); |
| } else { |
| if (notExistKeysCache.size() > 500000) { |
| notExistKeysCache.clear(); |
| } |
| notExistKeysCache.add(key); |
| } |
| |
| return exist; |
| } |
| |
| private void buildElementTree(MixinElement element) { |
| // TODO: This is consistend cache stage |
| if (element.isFinal()) { |
| return; |
| } |
| ISourceModule[] containedModules = findModules(element.getKey()); |
| if (containedModules.length == 0) { |
| synchronized (cache) { |
| cache.remove(element); |
| cache.resetSpaceLimit(ModelCache.DEFAULT_ROOT_SIZE, element); |
| cache.removeKey(element.key); |
| } |
| return; |
| } |
| for (int i = 0; i < containedModules.length; ++i) { |
| reportModule(containedModules[i]); |
| } |
| // mark selected element and all subelements as finished. |
| markElementAsFinal(element); |
| } |
| |
| private synchronized void markElementAsFinal(MixinElement element) { |
| element.bFinal = true; |
| for (Iterator i = element.children.iterator(); i.hasNext();) { |
| markElementAsFinal((MixinElement) i.next()); |
| } |
| } |
| |
| public synchronized void reportModule(ISourceModule sourceModule) { |
| // if (DLTKCore.VERBOSE) { |
| // System.out.println("Filling ratio:" + this.cache.fillingRatio()); |
| // this.cache.printStats(); |
| // } |
| if (!this.elementToMixinCache.containsKey(sourceModule)) { |
| this.elementToMixinCache.put(sourceModule, new ArrayList()); |
| } else { // Module already in model. So we do not to rebuild it. |
| if (!this.modulesToReparse.contains(sourceModule)) { |
| return; |
| } |
| this.modulesToReparse.remove(sourceModule); |
| // We need to reparse module if some elements are moved from it. |
| } |
| IMixinParser mixinParser; |
| try { |
| mixinParser = MixinManager.getMixinParser(sourceModule); |
| if (mixinParser != null) { |
| this.currentModule = sourceModule; |
| mixinParser.setRequirestor(mixinRequestor); |
| // System.out.println("Mixins: reporting " + |
| // sourceModule.getPath()); |
| mixinParser.parserSourceModule(true, sourceModule); |
| this.currentModule = null; |
| } |
| } catch (CoreException e) { |
| if (DLTKCore.DEBUG) |
| e.printStackTrace(); |
| return; |
| } |
| } |
| |
| /** |
| * Should find all elements source modules to be shure we build complete |
| * child tree. |
| * |
| * @param element |
| * @return |
| */ |
| private ISourceModule[] findModules(String key) { |
| ISourceModule[] searchMixinSources = SearchEngine.searchMixinSources( |
| key, toolkit); |
| return searchMixinSources; |
| } |
| |
| /** |
| * Returns a mixin element from this.cache by it's key, or creates new one |
| * if cache doesn't contain required element |
| * |
| * @param key |
| * @return |
| */ |
| private synchronized MixinElement getCreateEmpty(String key) { |
| MixinElement element = (MixinElement) MixinModel.this.cache.get(key); |
| if (element == null) { |
| element = new MixinElement(key, currentModule); |
| this.cache.put(key, element); |
| this.cache.ensureSpaceLimit(1, element); |
| } |
| return element; |
| } |
| |
| private interface IMixinChangedListener extends IElementChangedListener, |
| IResourceChangeListener { |
| } |
| |
| private IMixinChangedListener changedListener = new IMixinChangedListener() { |
| public void elementChanged(ElementChangedEvent event) { |
| IModelElementDelta delta = event.getDelta(); |
| processDelta(delta); |
| } |
| |
| private void processDelta(IModelElementDelta delta) { |
| IModelElement element = delta.getElement(); |
| if (delta.getKind() == IModelElementDelta.REMOVED |
| || delta.getKind() == IModelElementDelta.CHANGED |
| || (delta.getFlags() & IModelElementDelta.F_REMOVED_FROM_BUILDPATH) != 0 |
| || (delta.getFlags() & IModelElementDelta.CHANGED) != 0) { |
| if (element.getElementType() != IModelElement.SOURCE_MODULE |
| && element.getElementType() != IModelElement.PROJECT_FRAGMENT |
| && element.getElementType() != IModelElement.SCRIPT_FOLDER |
| && element.getElementType() != IModelElement.SCRIPT_MODEL |
| && element.getElementType() != IModelElement.SCRIPT_PROJECT) { |
| ISourceModule module = (ISourceModule) element |
| .getAncestor(IModelElement.SOURCE_MODULE); |
| MixinModel.this.remove(module); |
| } |
| if (element.getElementType() == IModelElement.SOURCE_MODULE) { |
| MixinModel.this.remove((ISourceModule) element); |
| } |
| } |
| |
| if (delta.getKind() == IModelElementDelta.CHANGED |
| && ((delta.getFlags() & IModelElementDelta.F_REMOVED_FROM_BUILDPATH) != 0)) { |
| MixinModel.this.cache.flush(); |
| } |
| |
| if (delta.getKind() == IModelElementDelta.CHANGED |
| && ((delta.getFlags() & IModelElementDelta.F_ADDED_TO_BUILDPATH) != 0)) { |
| MixinModel.this.notExistKeysCache.clear(); |
| } |
| if (delta.getKind() == IModelElementDelta.ADDED) { |
| if (element.getElementType() == IModelElement.SOURCE_MODULE) { |
| if (!modulesToReparse.contains(element)) { |
| modulesToReparse.add(element); |
| reportModule((ISourceModule) element); |
| } |
| } |
| MixinModel.this.notExistKeysCache.clear(); |
| } |
| |
| if ((delta.getFlags() & IModelElementDelta.F_CHILDREN) != 0) { |
| IModelElementDelta[] affectedChildren = delta |
| .getAffectedChildren(); |
| for (int i = 0; i < affectedChildren.length; i++) { |
| IModelElementDelta child = affectedChildren[i]; |
| processDelta(child); |
| } |
| } |
| } |
| |
| public void resourceChanged(IResourceChangeEvent event) { |
| int eventType = event.getType(); |
| IResource resource = event.getResource(); |
| // IResourceDelta delta = event.getDelta(); |
| |
| switch (eventType) { |
| case IResourceChangeEvent.PRE_DELETE: |
| if (resource.getType() == IResource.PROJECT |
| && DLTKLanguageManager |
| .hasScriptNature((IProject) resource)) { |
| // remove all resources with given project from model. |
| List toRemove = new ArrayList(); |
| synchronized (elementToMixinCache) { |
| IProject project = (IProject) resource; |
| for (Iterator iterator = elementToMixinCache.keySet() |
| .iterator(); iterator.hasNext();) { |
| ISourceModule module = (ISourceModule) iterator |
| .next(); |
| IScriptProject scriptProject = module |
| .getScriptProject(); |
| if (scriptProject != null) { |
| IProject prj = scriptProject.getProject(); |
| if ((prj != null && prj.equals(project)) |
| || prj == null) { |
| toRemove.add(module); |
| } |
| } else { |
| toRemove.add(module); |
| } |
| } |
| } |
| for (Iterator iterator = toRemove.iterator(); iterator |
| .hasNext();) { |
| ISourceModule module = (ISourceModule) iterator.next(); |
| remove(module); |
| } |
| } |
| return; |
| } |
| } |
| }; |
| |
| // private synchronized void clearAllElementsState() { |
| // Enumeration elements = cache.elements(); |
| // while( elements.hasMoreElements() ) { |
| // MixinElement o = (MixinElement)elements.nextElement(); |
| // o.bFinal = false; |
| // } |
| // } |
| |
| public synchronized void remove(ISourceModule element) { |
| if (this.elementToMixinCache.containsKey(element)) { |
| List elements = (List) this.elementToMixinCache.get(element); |
| for (int i = 0; i < elements.size(); ++i) { |
| removes++; |
| MixinElement mixin = (MixinElement) elements.get(i); |
| existKeysCache.remove(mixin.key); |
| notExistKeysCache.remove(mixin.key); |
| mixin.bFinal = false; |
| mixin.sourceModules.remove(element); |
| mixin.sourceModuleToObject.remove(element); |
| if (mixin.sourceModules.size() == 0) { |
| // Remove frob parent. |
| String parentKey = mixin.getParentKey(); |
| if (parentKey != null) { |
| MixinElement parent = (MixinElement) this.cache |
| .get(parentKey); |
| if (parent != null) { |
| parent.children.remove(mixin); |
| parent.bFinal = false; |
| } |
| } |
| // Remove from cache |
| cache.remove(mixin); |
| cache.resetSpaceLimit(ModelCache.DEFAULT_ROOT_SIZE, mixin); |
| } |
| } |
| this.elementToMixinCache.remove(element); |
| } |
| } |
| |
| /*************************************************************************** |
| * Then getObjects are called, special initialize listener are called. |
| * |
| */ |
| public interface IMixinObjectInitializeListener { |
| void initialize(IMixinElement element, Object object, |
| ISourceModule module); |
| } |
| |
| private final ListenerList mixinObjectInitializeListeners = new ListenerList(); |
| |
| private class MixinElement implements IMixinElement, IInternalMixinElement { |
| private String key; |
| private boolean bFinal = false; |
| private List sourceModules = new ArrayList(); |
| private Map sourceModuleToObject = new HashMap(); |
| |
| /** |
| * List of Strings. |
| */ |
| private Set children = new HashSet(); |
| |
| public boolean equals(Object obj) { |
| if (obj instanceof MixinElement) { |
| return this.key.equals(((MixinElement) obj).key); |
| } |
| return false; |
| } |
| |
| public int hashCode() { |
| return this.key.hashCode(); |
| } |
| |
| public MixinElement(String key) { |
| this.key = key; |
| } |
| |
| public String toString() { |
| return this.getLastKeySegment() + " final[" + this.bFinal + "]" |
| + this.children + " "; |
| } |
| |
| public MixinElement(ElementInfo info, ISourceModule module) { |
| this(info.key, currentModule); |
| addInfo(info, module); |
| } |
| |
| void addInfo(ElementInfo info, ISourceModule module) { |
| if (info.object != null) { |
| Object object = this.sourceModuleToObject.get(module); |
| if (object != null) { |
| if (object instanceof List) { |
| ((List) object).add(info.object); |
| } else { |
| List l = new ArrayList(); |
| l.add(object); |
| l.add(info.object); |
| object = l; |
| this.sourceModuleToObject.put(module, object); |
| } |
| } else { |
| List l = new ArrayList(); |
| l.add(info.object); |
| object = l; |
| this.sourceModuleToObject.put(module, object); |
| } |
| } |
| } |
| |
| public MixinElement(String key, ISourceModule currentModule) { |
| this.key = key; |
| addModule(currentModule); |
| } |
| |
| void addModule(ISourceModule currentModule) { |
| if (currentModule != null) { |
| if (!this.sourceModules.contains(currentModule)) { |
| this.sourceModules.add(currentModule); |
| } |
| } |
| } |
| |
| public IMixinElement[] getChildren() { |
| this.validate(); |
| return (IMixinElement[]) this.children |
| .toArray(new IMixinElement[this.children.size()]); |
| } |
| |
| public IMixinElement getChildren(String key) { |
| this.validate(); |
| return MixinModel.this.get(this.key |
| + IMixinRequestor.MIXIN_NAME_SEPARATOR + key); |
| } |
| |
| public String getKey() { |
| return this.key; |
| } |
| |
| protected String getParentKey() { |
| if (this.key.indexOf(IMixinRequestor.MIXIN_NAME_SEPARATOR) == -1) { |
| return null; |
| } |
| return this.key.substring(0, this.key |
| .lastIndexOf(IMixinRequestor.MIXIN_NAME_SEPARATOR)); |
| } |
| |
| public String getLastKeySegment() { |
| if (this.key.indexOf(IMixinRequestor.MIXIN_NAME_SEPARATOR) == -1) { |
| return this.key; |
| } |
| return this.key.substring(1 + this.key |
| .lastIndexOf(IMixinRequestor.MIXIN_NAME_SEPARATOR)); |
| } |
| |
| public IMixinElement getParent() { |
| String parentKey = this.getParentKey(); |
| if (parentKey == null) { |
| return null; |
| } |
| return get(parentKey); |
| |
| } |
| |
| public ISourceModule[] getSourceModules() { |
| this.validate(); |
| if (!this.isFinal()) { |
| get(this.key); |
| } |
| return (ISourceModule[]) this.sourceModules |
| .toArray(new ISourceModule[this.sourceModules.size()]); |
| } |
| |
| public Object[] getObjects(ISourceModule module) { |
| this.validate(); |
| Object o = this.sourceModuleToObject.get(module); |
| if (o instanceof List) { |
| |
| Object[] objs = ((List) o).toArray(); |
| for (int i = 0; i < objs.length; i++) { |
| notifyInitializeListener(this, module, objs[i]); |
| } |
| return objs; |
| } |
| if (o != null) { |
| notifyInitializeListener(this, module, o); |
| return new Object[] { o }; |
| } |
| return new Object[0]; |
| } |
| |
| public Object[] getAllObjects() { |
| this.validate(); |
| HashSet objects = new HashSet(); |
| for (Iterator iterator = this.sourceModules.iterator(); iterator |
| .hasNext();) { |
| ISourceModule module = (ISourceModule) iterator.next(); |
| Object[] objs = this.getObjects(module); |
| for (int j = 0; j < objs.length; ++j) { |
| objects.add(objs[j]); |
| } |
| } |
| return objects.toArray(); |
| } |
| |
| public boolean isFinal() { |
| return this.bFinal; |
| } |
| |
| public void close() { |
| existKeysCache.remove(key); |
| notExistKeysCache.remove(key); |
| removes++; |
| this.bFinal = false; |
| for (int i = 0; i < sourceModules.size(); i++) { |
| Object module = sourceModules.get(i); |
| List list = (List) elementToMixinCache.get(module); |
| if (list != null) { |
| list.remove(this); |
| if (list.size() == 0) { |
| elementToMixinCache.remove(module); |
| } |
| } |
| if (!modulesToReparse.contains(module) |
| && elementToMixinCache.containsKey(module)) { |
| modulesToReparse.add(module); |
| } |
| } |
| this.sourceModules.clear(); |
| this.sourceModuleToObject.clear(); |
| |
| // Lets also clean parent data |
| // Remove frob parent. |
| String parentKey = getParentKey(); |
| MixinElement element = this; |
| while (parentKey != null) { |
| MixinElement parent = (MixinElement) cache.get(parentKey); |
| if (parent != null) { |
| existKeysCache.remove(parent.key); |
| notExistKeysCache.remove(parent.key); |
| parent.children.remove(element); |
| parent.bFinal = false; |
| element = parent; |
| parentKey = parent.getParentKey(); |
| } else { |
| break; |
| } |
| } |
| |
| } |
| |
| private void validate() { |
| if (!isFinal()) { |
| buildElementTree(this); |
| } |
| } |
| }; |
| |
| private class MixinRequestor implements IMixinRequestor { |
| public void reportElement(ElementInfo info) { |
| // if( DLTKCore.VERBOSE_MIXIN ) { |
| // System.out.println("Append mixin:" + info.key); |
| // } |
| existKeysCache.add(info.key); |
| String[] list = info.key.split("\\" |
| + IMixinRequestor.MIXIN_NAME_SEPARATOR); |
| MixinElement element = getCreateEmpty(info.key); |
| addElementToModules(element); |
| element.addModule(currentModule); |
| element.addInfo(info, currentModule); |
| // Append as childs for all other elements. Also append modules to |
| // all selected elements. |
| if (list.length != 1) { |
| for (int i = 0; i < list.length - 1; ++i) { |
| MixinElement parent = getCreateEmpty(element.getParentKey()); |
| if (!parent.children.contains(element)) { |
| parent.children.add(element); |
| } |
| addElementToModules(parent); |
| element = parent; |
| } |
| } |
| } |
| |
| private void addElementToModules(MixinElement element) { |
| List elements = (List) MixinModel.this.elementToMixinCache |
| .get(currentModule); |
| if (elements == null) { |
| elements = new ArrayList(); |
| MixinModel.this.elementToMixinCache |
| .put(currentModule, elements); |
| } |
| // if( !elements.contains(element)) { |
| elements.add(element); |
| // } |
| } |
| } |
| |
| public void makeAllModuleElementsFinal(ISourceModule module) { |
| if (this.elementToMixinCache.containsKey(module)) { |
| List elements = (List) this.elementToMixinCache.get(module); |
| for (int i = 0; i < elements.size(); ++i) { |
| removes++; |
| MixinElement mixin = (MixinElement) elements.get(i); |
| mixin.bFinal = true; |
| } |
| } |
| } |
| |
| public void makeAllElementsFinalIfNoCacheRemoves() { |
| if (removes != 0) { |
| return; |
| } |
| Enumeration elements = cache.elements(); |
| while (elements.hasMoreElements()) { |
| MixinElement e = (MixinElement) elements.nextElement(); |
| e.bFinal = true; |
| } |
| |
| } |
| |
| public void setRemovesToZero() { |
| removes = 0; |
| } |
| |
| public void clearKeysCashe(String key) { |
| existKeysCache.remove(key); |
| notExistKeysCache.remove(key); |
| // MixinElement e = (MixinElement)this.cache.get(key); |
| } |
| |
| // // Mixin object initialize listeners code |
| public void addObjectInitializeListener( |
| IMixinObjectInitializeListener mixinObjectInitializeListener) { |
| this.mixinObjectInitializeListeners.add(mixinObjectInitializeListener); |
| } |
| |
| public void removeObjectInitializeListener( |
| IMixinObjectInitializeListener mixinObjectInitializeListener) { |
| this.mixinObjectInitializeListeners |
| .remove(mixinObjectInitializeListener); |
| } |
| |
| private void notifyInitializeListener(IMixinElement element, |
| ISourceModule module, Object o) { |
| Object[] listeners = mixinObjectInitializeListeners.getListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| ((IMixinObjectInitializeListener) (listeners[i])).initialize( |
| element, o, module); |
| } |
| } |
| } |