X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=plugins%2Fnet.mograsim.plugin.core%2Fsrc%2Fnet%2Fmograsim%2Fplugin%2Fnature%2FProjectMachineContext.java;h=ecce9e818f68226e1340e0f0bddd7bf02b8d8ed7;hb=0eb525202d3c871a2a20f789af1728248f3cff11;hp=0e6185c410045ad5d5fcf0a8c385700de556f02d;hpb=363c9377b3c542c87fc5e7f57674751439246dbd;p=Mograsim.git diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java index 0e6185c4..ecce9e81 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java @@ -2,24 +2,56 @@ package net.mograsim.plugin.nature; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.ui.preferences.ScopedPreferenceStore; +import net.mograsim.machine.MachineRegistry; +import net.mograsim.plugin.nature.ProjectContextEvent.ProjectContextEventType; + +/** + * This class is a register for {@link MachineContext} mapped by their {@link IProject} + *

+ * It can be used to obtain (and thereby create if necessary) {@link MachineContext}s for projects and {@link IAdaptable}s that are somewhat + * associated to Mograsim nature. The register is unique and static context of this class. Since it also depends on the installed machines, + * it listens to changes of the {@link MachineRegistry}. + * + * @author Christian Femers + * + */ public class ProjectMachineContext { private static Map projectMachineContexts = Collections.synchronizedMap(new HashMap<>()); + private static final Set listeners = Collections.synchronizedSet(new HashSet<>()); public static final String MOGRASIM_PROJECT_PREFS_NODE = "net.mograsim"; public static final String MACHINE_PROPERTY = "net.mograsim.projectMachineId"; + private ProjectMachineContext() + { + + } + + /** + * This method returns the associated machine context or created a new one if none is associated yet. + * + * @param project the project to get the {@link MachineContext} for (or create one, if possible). It must have Mograsim nature. + * + * @throws IllegalArgumentException if the project is not accessible or has no mograsim nature + * @throws NullPointerException if the project is null + * + */ public static MachineContext getMachineContextOf(IProject project) { MachineContext mc = projectMachineContexts.get(project); @@ -28,9 +60,21 @@ public class ProjectMachineContext validateMograsimNatureProject(project); mc = new MachineContext(project); projectMachineContexts.put(project, mc); + notifyListeners(new ProjectContextEvent(mc, ProjectContextEventType.NEW)); return mc; } + /** + * This method returns the associated machine context or created a new one if none is associated yet. The given resource must be + * adaptable to {@link IProject}. + * + * @param mograsimProjectAdapable the {@link IProject}-{@link IAdaptable} to get the {@link MachineContext} for (or create one, if + * possible). Must be contained in a Mograsim nature project. + * + * @throws IllegalArgumentException if the project is not accessible or has no mograsim nature + * @throws NullPointerException if the {@link IAdaptable} is null or it cannot be adapted to {@link IProject} + * + */ public static MachineContext getMachineContextOf(IAdaptable mograsimProjectAdapable) { IProject project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true); @@ -38,6 +82,14 @@ public class ProjectMachineContext return getMachineContextOf(project); } + /** + * Returns all {@link MachineContext} known, in the sense of all that got ever created during this runtime. + */ + public static Map getAllProjectMachineContexts() + { + return Collections.unmodifiableMap(projectMachineContexts); + } + static ScopedPreferenceStore getProjectPrefs(IProject mograsimProject) { return new ScopedPreferenceStore(new ProjectScope(mograsimProject), MOGRASIM_PROJECT_PREFS_NODE); @@ -49,6 +101,7 @@ public class ProjectMachineContext if (mograsimProjectAdapable instanceof IProject) { project = (IProject) mograsimProjectAdapable; + Objects.requireNonNull(project, "Project was null"); } else { project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true); @@ -67,6 +120,9 @@ public class ProjectMachineContext return project; } + /** + * Tests for Mograsim nature. This method is null safe and will not throw any exception. + */ static boolean hasMograsimNature(IProject project) { if (project == null) @@ -88,4 +144,48 @@ public class ProjectMachineContext return Optional.of(preferenceStore.getString(MACHINE_PROPERTY)); return Optional.empty(); } + + static void notifyListeners(ProjectContextEvent projectContextEvent) + { + listeners.forEach(l -> l.onProjectContextChange(projectContextEvent)); + } + + public static void addProjectContextListener(ProjectContextListener listener) + { + listeners.add(listener); + } + + public static void removeProjectContextListener(ProjectContextListener listener) + { + listeners.remove(listener); + } + + static + { + ResourcesPlugin.getWorkspace().addResourceChangeListener(ProjectMachineContext::resourceChanged); + MachineRegistry.addMachineRegistryListener(newMap -> updateAllStatus()); + } + + private static void updateAllStatus() + { + projectMachineContexts.forEach((p, mc) -> mc.updateStatus()); + } + + private static void resourceChanged(IResourceChangeEvent event) + { + // We try to do as many cheap tests first as possible, because this listener is not limited to plain project actions. + if (event.getResource() == null) + return; + IProject project = event.getResource().getProject(); + if (project == null) + return; + MachineContext mc = projectMachineContexts.get(project); + if (mc == null) + return; + ProjectContextEventType eventType = ProjectContextEventType.ofResourceChangeEvent(event.getType()); +// if (eventType == ProjectContextEventType.OTHER_CHANGE && project.isOpen()) +// return; // we don't care about all small changes (TODO: research if this has any drawbacks) + eventType.getForcedStatus().ifPresent(mc::forceUpdateStatus); + notifyListeners(new ProjectContextEvent(mc, eventType)); + } }