Added listener and event structure to ProjectMachineContexts
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / nature / ProjectMachineContext.java
1 package net.mograsim.plugin.nature;
2
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.Map;
7 import java.util.Objects;
8 import java.util.Optional;
9 import java.util.Set;
10
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;
19
20 import net.mograsim.plugin.nature.ProjectContextEvent.ProjectContextEventType;
21
22 public class ProjectMachineContext
23 {
24         private static Map<IProject, MachineContext> projectMachineContexts = Collections.synchronizedMap(new HashMap<>());
25         private static final Set<ProjectContextListener> listeners = Collections.synchronizedSet(new HashSet<>());
26
27         public static final String MOGRASIM_PROJECT_PREFS_NODE = "net.mograsim";
28         public static final String MACHINE_PROPERTY = "net.mograsim.projectMachineId";
29
30         public static MachineContext getMachineContextOf(IProject project)
31         {
32                 MachineContext mc = projectMachineContexts.get(project);
33                 if (mc != null)
34                         return mc;
35                 validateMograsimNatureProject(project);
36                 mc = new MachineContext(project);
37                 projectMachineContexts.put(project, mc);
38                 notifyListeners(new ProjectContextEvent(mc, ProjectContextEventType.NEW));
39                 return mc;
40         }
41
42         public static MachineContext getMachineContextOf(IAdaptable mograsimProjectAdapable)
43         {
44                 IProject project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
45                 Objects.requireNonNull(project, "project was null / no project found for " + mograsimProjectAdapable);
46                 return getMachineContextOf(project);
47         }
48
49         public static Map<IProject, MachineContext> getAllProjectMachineContexts()
50         {
51                 return Collections.unmodifiableMap(projectMachineContexts);
52         }
53
54         static ScopedPreferenceStore getProjectPrefs(IProject mograsimProject)
55         {
56                 return new ScopedPreferenceStore(new ProjectScope(mograsimProject), MOGRASIM_PROJECT_PREFS_NODE);
57         }
58
59         static IProject validateMograsimNatureProject(IAdaptable mograsimProjectAdapable)
60         {
61                 IProject project;
62                 if (mograsimProjectAdapable instanceof IProject)
63                 {
64                         project = (IProject) mograsimProjectAdapable;
65                 } else
66                 {
67                         project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
68                         Objects.requireNonNull(project, () -> mograsimProjectAdapable + " is not adaptable to IProject");
69                 }
70                 try
71                 {
72                         if (!project.isNatureEnabled(MograsimNature.NATURE_ID))
73                                 throw new IllegalArgumentException(mograsimProjectAdapable + "is not (in) a Mograsim project");
74                 }
75                 catch (CoreException e)
76                 {
77                         e.printStackTrace();
78                         throw new IllegalArgumentException(mograsimProjectAdapable + " project nature could not be evaluated", e);
79                 }
80                 return project;
81         }
82
83         static boolean hasMograsimNature(IProject project)
84         {
85                 if (project == null)
86                         return false;
87                 try
88                 {
89                         return project.isNatureEnabled(MograsimNature.NATURE_ID);
90                 }
91                 catch (CoreException e)
92                 {
93                         e.printStackTrace();
94                         return false;
95                 }
96         }
97
98         static Optional<String> getMachineIdFrom(ScopedPreferenceStore preferenceStore)
99         {
100                 if (preferenceStore.contains(MACHINE_PROPERTY))
101                         return Optional.of(preferenceStore.getString(MACHINE_PROPERTY));
102                 return Optional.empty();
103         }
104
105         static void notifyListeners(ProjectContextEvent projectContextEvent)
106         {
107                 listeners.forEach(l -> l.onProjectContextChange(projectContextEvent));
108         }
109
110         public static void addProjectContextListener(ProjectContextListener listener)
111         {
112                 listeners.add(listener);
113         }
114
115         public static void removeProjectContextListener(ProjectContextListener listener)
116         {
117                 listeners.remove(listener);
118         }
119
120         static
121         {
122                 ResourcesPlugin.getWorkspace().addResourceChangeListener(ProjectMachineContext::resourceChanged);
123         }
124
125         private static void resourceChanged(IResourceChangeEvent event)
126         {
127                 ProjectContextEventType eventType = ProjectContextEventType.ofResourceChangeEvent(event.getType());
128                 if (eventType == null)
129                         return;
130                 IProject p = event.getResource().getProject();
131                 if (p == null)
132                         return;
133                 MachineContext mc = projectMachineContexts.get(p);
134                 if (mc == null)
135                         return;
136                 notifyListeners(new ProjectContextEvent(mc, eventType));
137         }
138 }