/*=============================================================================#
# Copyright (c) 2009-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.ecommons.ltk.core.impl;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import de.walware.ecommons.FastList;
import de.walware.ecommons.ltk.IElementChangedListener;
import de.walware.ecommons.ltk.IModelManager;
import de.walware.ecommons.ltk.LTK;
import de.walware.ecommons.ltk.WorkingContext;
import de.walware.ecommons.ltk.core.model.ISourceUnit;
public abstract class AbstractModelManager implements IModelManager {
protected static class ContextItem {
public final WorkingContext context;
public final FastList<IElementChangedListener> listeners= new FastList<>(IElementChangedListener.class);
protected ContextItem(final WorkingContext context) {
this.context= context;
}
@Override
public final int hashCode() {
return this.context.hashCode();
}
@Override
public final boolean equals(final Object obj) {
return (this == obj);
}
}
private static final IElementChangedListener[] NO_LISTENERS= new IElementChangedListener[0];
private class RefreshJob extends Job {
private final List<ISourceUnit> list;
private final int flags;
public RefreshJob(final WorkingContext context, final int flags) {
super("Model Refresh"); //$NON-NLS-1$
setUser(false);
setSystem(true);
setPriority(DECORATE);
this.list= LTK.getSourceUnitManager().getOpenSourceUnits(AbstractModelManager.this.typeId, context);
this.flags= flags;
}
@Override
protected IStatus run(final IProgressMonitor monitor) {
for (final ISourceUnit su : this.list) {
su.getModelInfo(null, this.flags, monitor);
}
return Status.OK_STATUS;
}
}
private final String typeId;
private final FastList<ContextItem> contexts= new FastList<>(ContextItem.class, FastList.IDENTITY);
public AbstractModelManager(final String typeId) {
this.typeId= typeId;
}
public String getModelTypeId() {
return this.typeId;
}
protected ContextItem getContextItem(final WorkingContext context, final boolean create) {
while (true) {
final ContextItem[] contextItems= this.contexts.toArray();
for (int i= 0; i < contextItems.length; i++) {
if (contextItems[i].context == context) {
return contextItems[i];
}
}
if (!create) {
return null;
}
synchronized (this.contexts) {
if (contextItems == this.contexts.toArray()) {
final ContextItem item= doCreateContextItem(context);
this.contexts.add(item);
return item;
}
}
}
}
protected ContextItem doCreateContextItem(final WorkingContext context) {
return new ContextItem(context);
}
@Override
public void addElementChangedListener(final IElementChangedListener listener,
final WorkingContext context) {
final ContextItem contextItem= getContextItem(context, true);
contextItem.listeners.add(listener);
}
@Override
public void removeElementChangedListener(final IElementChangedListener listener,
final WorkingContext context) {
final ContextItem contextItem= getContextItem(context, false);
if (contextItem != null) {
contextItem.listeners.remove(listener);
}
}
protected IElementChangedListener[] getElementChangedListeners(final WorkingContext context) {
final ContextItem contextItem= getContextItem(context, false);
if (contextItem == null) {
return NO_LISTENERS;
}
return contextItem.listeners.toArray();
}
/**
* Refresh reuses existing ast
*/
@Override
public void refresh(final WorkingContext context) {
new RefreshJob(context, (MODEL_DEPENDENCIES | RECONCILE)).schedule();
}
@Override
public void registerDependentUnit(final ISourceUnit su) {
}
@Override
public void deregisterDependentUnit(final ISourceUnit su) {
}
}