1414import java .util .Map ;
1515import java .util .Objects ;
1616import java .util .Optional ;
17+ import java .util .function .Consumer ;
1718import java .util .function .Supplier ;
1819import java .util .stream .Collectors ;
1920import java .util .stream .Stream ;
@@ -30,17 +31,17 @@ public ScheduledStateRegistry(Supplier<ZonedDateTime> currentTime, HueApi api) {
3031 lightStates = new LinkedHashMap <>();
3132 }
3233
33- public void addState (ScheduledState state ) {
34+ public synchronized void addState (ScheduledState state ) {
3435 lightStates .computeIfAbsent (state .getId (), _ -> new ArrayList <>()).add (state );
3536 state .setPreviousStateLookup (this ::getPreviousState );
3637 state .setNextStateLookup (this ::getNextStateAfter );
3738 }
3839
39- public void remove (ScheduledState state ) {
40+ public synchronized void remove (ScheduledState state ) {
4041 lightStates .get (state .getId ()).remove (state );
4142 }
4243
43- public ScheduledStateSnapshot getPreviousState (ScheduledStateSnapshot currentStateSnapshot ) {
44+ public synchronized ScheduledStateSnapshot getPreviousState (ScheduledStateSnapshot currentStateSnapshot ) {
4445 return getDistinctPreviousStatesBefore (currentStateSnapshot ).stream ()
4546 .findFirst ()
4647 .orElse (null );
@@ -66,7 +67,7 @@ private List<ScheduledStateSnapshot> getDistinctPreviousStatesBefore(ScheduledSt
6667 .collect (Collectors .toList ());
6768 }
6869
69- public ScheduledStateSnapshot getNextStateAfter (ScheduledStateSnapshot currentState , ZonedDateTime definedStart ) {
70+ public synchronized ScheduledStateSnapshot getNextStateAfter (ScheduledStateSnapshot currentState , ZonedDateTime definedStart ) {
7071 ZonedDateTime theDayAfter = definedStart .plusDays (1 ).truncatedTo (ChronoUnit .DAYS ).withEarlierOffsetAtOverlap ();
7172 return findStatesForId (currentState ).stream ()
7273 .flatMap (state -> Stream .of (state .getSnapshot (definedStart ), state .getSnapshot (theDayAfter )))
@@ -76,11 +77,11 @@ public ScheduledStateSnapshot getNextStateAfter(ScheduledStateSnapshot currentSt
7677 .orElse (null );
7778 }
7879
79- public ScheduledState getLastSeenState (ScheduledStateSnapshot state ) {
80+ public synchronized ScheduledState getLastSeenState (ScheduledStateSnapshot state ) {
8081 return getLastSeenState (state .getId ());
8182 }
8283
83- public ScheduledState getLastSeenState (String id ) {
84+ public synchronized ScheduledState getLastSeenState (String id ) {
8485 List <ScheduledState > lightStatesForId = findStatesForId (id );
8586 if (lightStatesForId == null ) {
8687 return null ;
@@ -91,7 +92,7 @@ public ScheduledState getLastSeenState(String id) {
9192 .orElse (null );
9293 }
9394
94- public long countOverlappingGroupStatesWithMoreLights (ScheduledStateSnapshot state ) {
95+ public synchronized long countOverlappingGroupStatesWithMoreLights (ScheduledStateSnapshot state ) {
9596 List <String > groupLights = getGroupLights (state );
9697 return getAssignedGroupsSortedBySizeDesc (groupLights )
9798 .stream ()
@@ -109,7 +110,7 @@ private List<String> getGroupLights(ScheduledStateSnapshot state) {
109110 }
110111 }
111112
112- public List <GroupInfo > getAssignedGroups (ScheduledStateSnapshot state ) {
113+ public synchronized List <GroupInfo > getAssignedGroups (ScheduledStateSnapshot state ) {
113114 List <String > groupLights = getGroupLights (state );
114115 List <GroupInfo > assignedGroups = getAssignedGroupsSortedBySizeDesc (groupLights );
115116 List <GroupInfo > additionalAreas = api .getAdditionalAreas (groupLights );
@@ -137,7 +138,7 @@ private List<GroupInfo> getAssignedGroupsSortedBySizeDesc(List<String> lightIds)
137138 * @param groupLights the list of light IDs for which to retrieve the active PutCall objects
138139 * @return a list of active PutCall objects corresponding to the provided light IDs
139140 */
140- public List <PutCall > getPutCalls (List <String > groupLights ) {
141+ public synchronized List <PutCall > getPutCalls (List <String > groupLights ) {
141142 ZonedDateTime now = currentTime .get ();
142143 Map <String , PutCall > putCalls = getActivePutCallsFromGroups (groupLights , now );
143144 findActivePutCalls (groupLights , now ).stream ()
@@ -223,27 +224,28 @@ private List<ScheduledState> findStatesForId(ScheduledStateSnapshot snapshot) {
223224 return findStatesForId (snapshot .getId ());
224225 }
225226
226- public List <ScheduledState > findStatesForId (String id ) {
227- return lightStates .get (id );
227+ public synchronized List <ScheduledState > findStatesForId (String id ) {
228+ List <ScheduledState > states = lightStates .get (id );
229+ return states != null ? new ArrayList <>(states ) : null ;
228230 }
229231
230- public Collection <List <ScheduledState >> values ( ) {
231- return lightStates .values ();
232+ public synchronized void forEach ( Consumer <List <ScheduledState >> consumer ) {
233+ lightStates .values (). forEach ( consumer );
232234 }
233235
234- public List <ScheduledState > findStatesWithSceneId (String sceneId ) {
236+ public synchronized List <ScheduledState > findStatesWithSceneId (String sceneId ) {
235237 return lightStates .values ().stream ()
236238 .flatMap (List ::stream )
237239 .filter (ScheduledState ::isSceneBased )
238240 .filter (state -> sceneId .equals (state .getSceneId ()))
239241 .toList ();
240242 }
241243
242- public List <ScheduledStateSnapshot > findCurrentlyActiveStates () {
244+ public synchronized List <ScheduledStateSnapshot > findCurrentlyActiveStates () {
243245 ZonedDateTime now = currentTime .get ();
244- return values ().stream ()
245- .map (lightStatesForId -> findActiveSnapshot (lightStatesForId , now ))
246- .flatMap (Optional ::stream )
247- .toList ();
246+ return lightStates . values ().stream ()
247+ .map (lightStatesForId -> findActiveSnapshot (lightStatesForId , now ))
248+ .flatMap (Optional ::stream )
249+ .toList ();
248250 }
249251}
0 commit comments