1 package net.mograsim.plugin.nature;
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.HashSet;
7 import java.util.Objects;
8 import java.util.Optional;
11 import org.eclipse.core.resources.IProject;
12 import org.eclipse.core.resources.IResourceChangeEvent;
13 import org.eclipse.core.resources.ProjectScope;
14 import org.eclipse.core.resources.ResourcesPlugin;
15 import org.eclipse.core.runtime.Adapters;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IAdaptable;
18 import org.eclipse.ui.preferences.ScopedPreferenceStore;
20 import net.mograsim.plugin.nature.ProjectContextEvent.ProjectContextEventType;
23 * This class is a register for {@link MachineContext} mapped by their {@link IProject}
25 * It can be used to obtain (and thereby create if necessary) {@link MachineContext}s for projects and {@link IAdaptable}s that are somewhat
26 * associated to Mograsim nature. The register is unique and static context of this class.
28 * @author Christian Femers
31 public class ProjectMachineContext
33 private static Map<IProject, MachineContext> projectMachineContexts = Collections.synchronizedMap(new HashMap<>());
34 private static final Set<ProjectContextListener> listeners = Collections.synchronizedSet(new HashSet<>());
36 public static final String MOGRASIM_PROJECT_PREFS_NODE = "net.mograsim";
37 public static final String MACHINE_PROPERTY = "net.mograsim.projectMachineId";
39 private ProjectMachineContext()
45 * This method returns the associated machine context or created a new one if none is associated yet.
47 * @param project the project to get the {@link MachineContext} for (or create one, if possible). It must have Mograsim nature.
49 * @throws IllegalArgumentException if the project is not accessible or has no mograsim nature
50 * @throws NullPointerException if the project is null
53 public static MachineContext getMachineContextOf(IProject project)
55 MachineContext mc = projectMachineContexts.get(project);
58 validateMograsimNatureProject(project);
59 mc = new MachineContext(project);
60 projectMachineContexts.put(project, mc);
61 notifyListeners(new ProjectContextEvent(mc, ProjectContextEventType.NEW));
66 * This method returns the associated machine context or created a new one if none is associated yet. The given resource must be
67 * adaptable to {@link IProject}.
69 * @param mograsimProjectAdapable the {@link IProject}-{@link IAdaptable} to get the {@link MachineContext} for (or create one, if
70 * possible). Must be contained in a Mograsim nature project.
72 * @throws IllegalArgumentException if the project is not accessible or has no mograsim nature
73 * @throws NullPointerException if the {@link IAdaptable} is null or it cannot be adapted to {@link IProject}
76 public static MachineContext getMachineContextOf(IAdaptable mograsimProjectAdapable)
78 IProject project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
79 Objects.requireNonNull(project, "project was null / no project found for " + mograsimProjectAdapable);
80 return getMachineContextOf(project);
84 * Returns all {@link MachineContext} known, in the sense of all that got ever created during this runtime.
86 public static Map<IProject, MachineContext> getAllProjectMachineContexts()
88 return Collections.unmodifiableMap(projectMachineContexts);
91 static ScopedPreferenceStore getProjectPrefs(IProject mograsimProject)
93 return new ScopedPreferenceStore(new ProjectScope(mograsimProject), MOGRASIM_PROJECT_PREFS_NODE);
96 static IProject validateMograsimNatureProject(IAdaptable mograsimProjectAdapable)
99 if (mograsimProjectAdapable instanceof IProject)
101 project = (IProject) mograsimProjectAdapable;
102 Objects.requireNonNull(project, "Project was null");
105 project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
106 Objects.requireNonNull(project, () -> mograsimProjectAdapable + " is not adaptable to IProject");
110 if (!project.isNatureEnabled(MograsimNature.NATURE_ID))
111 throw new IllegalArgumentException(mograsimProjectAdapable + "is not (in) a Mograsim project");
113 catch (CoreException e)
116 throw new IllegalArgumentException(mograsimProjectAdapable + " project nature could not be evaluated", e);
122 * Tests for Mograsim nature. This method is null safe and will not throw any exception.
124 static boolean hasMograsimNature(IProject project)
130 return project.isNatureEnabled(MograsimNature.NATURE_ID);
132 catch (CoreException e)
139 static Optional<String> getMachineIdFrom(ScopedPreferenceStore preferenceStore)
141 if (preferenceStore.contains(MACHINE_PROPERTY))
142 return Optional.of(preferenceStore.getString(MACHINE_PROPERTY));
143 return Optional.empty();
146 static void notifyListeners(ProjectContextEvent projectContextEvent)
148 listeners.forEach(l -> l.onProjectContextChange(projectContextEvent));
151 public static void addProjectContextListener(ProjectContextListener listener)
153 listeners.add(listener);
156 public static void removeProjectContextListener(ProjectContextListener listener)
158 listeners.remove(listener);
163 ResourcesPlugin.getWorkspace().addResourceChangeListener(ProjectMachineContext::resourceChanged);
166 private static void resourceChanged(IResourceChangeEvent event)
168 // System.out.println(((ResourceChangeEvent) event).toDebugString());
169 ProjectContextEventType eventType = ProjectContextEventType.ofResourceChangeEvent(event.getType());
170 if (eventType == null)
172 if (event.getResource() == null || event.getResource().getProject() == null)
174 MachineContext mc = projectMachineContexts.get(event.getResource().getProject());
177 // System.out.println(" " + eventType + " - " + mc.getProject());
178 notifyListeners(new ProjectContextEvent(mc, eventType));