blob: 890e62a93cec9e53070c45db056cbdd45ee0ef9c [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ltk.model.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 org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImIdentityList;
import org.eclipse.statet.ltk.core.LTK;
import org.eclipse.statet.ltk.core.WorkingContext;
import org.eclipse.statet.ltk.model.core.IElementChangedListener;
import org.eclipse.statet.ltk.model.core.IModelManager;
import org.eclipse.statet.ltk.model.core.elements.ISourceUnit;
public abstract class AbstractModelManager implements IModelManager {
protected static class ContextItem {
public final WorkingContext context;
public final CopyOnWriteIdentityListSet<IElementChangedListener> listeners= new CopyOnWriteIdentityListSet<>();
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 ImIdentityList<IElementChangedListener> NO_LISTENERS= ImCollections.emptyIdentityList();
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 CopyOnWriteIdentityListSet<ContextItem> contexts= new CopyOnWriteIdentityListSet<>();
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 ImIdentityList<ContextItem> contextItems= this.contexts.toList();
for (final ContextItem contextItem : contextItems) {
if (contextItem.context == context) {
return contextItem;
}
}
if (!create) {
return null;
}
synchronized (this.contexts) {
if (contextItems == this.contexts.toList()) {
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 ImIdentityList<IElementChangedListener> getElementChangedListeners(final WorkingContext context) {
final ContextItem contextItem= getContextItem(context, false);
if (contextItem == null) {
return NO_LISTENERS;
}
return contextItem.listeners.toList();
}
/**
* 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) {
}
}