Home | History | Annotate | Download | only in trigger
      1 /*
      2  * Copyright (C) 2016 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.trigger;
     18 
     19 import com.google.common.collect.Maps;
     20 import com.googlecode.android_scripting.facade.FacadeConfiguration;
     21 import com.googlecode.android_scripting.facade.FacadeManager;
     22 import com.googlecode.android_scripting.rpc.MethodDescriptor;
     23 import com.googlecode.android_scripting.trigger.TriggerRepository.TriggerRepositoryObserver;
     24 
     25 import java.util.Map;
     26 
     27 import org.json.JSONArray;
     28 
     29 /**
     30  * A {@link TriggerRepositoryObserver} that starts and stops the monitoring of events depending on
     31  * whether or not triggers for the event exist.
     32  *
     33  * @author Felix Arends (felix.arends (at) gmail.com)
     34  */
     35 public class EventGenerationControllingObserver implements TriggerRepositoryObserver {
     36   private final FacadeManager mFacadeManager;
     37   private final Map<String, MethodDescriptor> mStartEventGeneratingMethodDescriptors;
     38   private final Map<String, MethodDescriptor> mStopEventGeneratingMethodDescriptors;
     39   private final Map<String, Integer> mEventTriggerRefCounts = Maps.newHashMap();
     40 
     41   /**
     42    * Creates a new StartEventMonitoringObserver for the given trigger repository.
     43    *
     44    * @param facadeManager
     45    * @param triggerRepository
     46    */
     47   public EventGenerationControllingObserver(FacadeManager facadeManager) {
     48     mFacadeManager = facadeManager;
     49     mStartEventGeneratingMethodDescriptors =
     50         FacadeConfiguration.collectStartEventMethodDescriptors();
     51     mStopEventGeneratingMethodDescriptors = FacadeConfiguration.collectStopEventMethodDescriptors();
     52   }
     53 
     54   private synchronized int incrementAndGetRefCount(String eventName) {
     55     int refCount =
     56         (mEventTriggerRefCounts.containsKey(eventName)) ? mEventTriggerRefCounts.get(eventName) : 0;
     57     refCount++;
     58     mEventTriggerRefCounts.put(eventName, refCount);
     59     return refCount;
     60   }
     61 
     62   private synchronized int decrementAndGetRefCount(String eventName) {
     63     int refCount =
     64         (mEventTriggerRefCounts.containsKey(eventName)) ? mEventTriggerRefCounts.get(eventName) : 0;
     65     refCount--;
     66     mEventTriggerRefCounts.put(eventName, refCount);
     67     return refCount;
     68   }
     69 
     70   @Override
     71   public synchronized void onPut(Trigger trigger) {
     72     // If we're not already monitoring the events corresponding to this trigger, do so.
     73     if (incrementAndGetRefCount(trigger.getEventName()) == 1) {
     74       startMonitoring(trigger.getEventName());
     75     }
     76   }
     77 
     78   @Override
     79   public synchronized void onRemove(Trigger trigger) {
     80     // If there are no more triggers listening to this event, then we need to stop monitoring.
     81     if (decrementAndGetRefCount(trigger.getEventName()) == 1) {
     82       stopMonitoring(trigger.getEventName());
     83     }
     84   }
     85 
     86   private void startMonitoring(String eventName) {
     87     MethodDescriptor startEventGeneratingMethod =
     88         mStartEventGeneratingMethodDescriptors.get(eventName);
     89     try {
     90       startEventGeneratingMethod.invoke(mFacadeManager, new JSONArray());
     91     } catch (Throwable t) {
     92       throw new RuntimeException(t);
     93     }
     94   }
     95 
     96   private void stopMonitoring(String eventName) {
     97     MethodDescriptor stopEventGeneratingMethod =
     98         mStopEventGeneratingMethodDescriptors.get(eventName);
     99     try {
    100       stopEventGeneratingMethod.invoke(mFacadeManager, new JSONArray());
    101     } catch (Throwable t) {
    102       throw new RuntimeException(t);
    103     }
    104   }
    105 }
    106