001    package org.hackystat.telemetry.analyzer.configuration;
002    
003    import java.util.ArrayList;
004    import java.util.Collection;
005    import java.util.HashMap;
006    import java.util.List;
007    import java.util.Map;
008    
009    import org.hackystat.sensorbase.resource.users.jaxb.User;
010    import org.hackystat.telemetry.analyzer.configuration.jaxb.TelemetryDefinition;
011    
012    /**
013     * Implements the non-persistent TelemetryDefinitionManager.
014     * This class can be made to merge its repository with the global singleton instance of
015     * <code>PersistentTelemetryDefinitionManager</code>. The effect is that (1)
016     * All telemetry definitions in this instance and in the global instance share
017     * one single name space. (2) When searching, both the repository managed by
018     * this instance and the repository managed by the global instance will be
019     * searched. (3) Adding and deleting are only performed on the repository
020     * managed by this instance. (4) The repository managed by this instance only
021     * exists in memory, it will not be persisted.
022     * <p>
023     * V8 Notes: Not sure if this class is needed for the initial implementation. It may be
024     * useful later on when someone wants to send a Telemetry definition via REST for 
025     * execution. 
026     * 
027     * @author (Cedric) Qin Zhang 
028     */
029    class NonPersistentTelemetryDefinitionManager extends TelemetryDefinitionManager {
030      
031      private boolean linkToGlobalSingleton;
032      private PersistentTelemetryDefinitionManager globalSingleton;
033      private Map<TelemetryDefinitionType, TelemetryDefinitionInfoRepository> defInfoRepositoryMap = 
034        new HashMap<TelemetryDefinitionType, TelemetryDefinitionInfoRepository>(11);
035      
036      /**
037       * Constructs this instance.
038       * 
039       * @param linkToGlobalSingleton True if the definitions in global singleton telemetry manager
040       *        should be merged to this instance.
041       */
042      NonPersistentTelemetryDefinitionManager(boolean linkToGlobalSingleton) {
043        this.linkToGlobalSingleton = linkToGlobalSingleton;
044        if (this.linkToGlobalSingleton) {
045          this.globalSingleton = (PersistentTelemetryDefinitionManager) 
046              TelemetryDefinitionManagerFactory.getGlobalPersistentInstance();
047        }
048        
049        this.defInfoRepositoryMap.put(TelemetryDefinitionType.STREAMS, 
050            new TelemetryDefinitionInfoRepository());
051        this.defInfoRepositoryMap.put(TelemetryDefinitionType.CHART, 
052            new TelemetryDefinitionInfoRepository());
053        this.defInfoRepositoryMap.put(TelemetryDefinitionType.YAXIS, 
054            new TelemetryDefinitionInfoRepository());
055        this.defInfoRepositoryMap.put(TelemetryDefinitionType.REPORT, 
056            new TelemetryDefinitionInfoRepository());
057      }
058      
059      /**
060       * Gets the telemetry definition information by name.
061       * 
062       * @param owner The owner under which to find the telemetry definition object.
063       * @param name The name of the telemetry definition.
064       * @param includeShared If true, then those telemetry definitions owned by other users, 
065       *        but is shared will also be returned.
066       * @param type The definition type.
067       * 
068       * @return The object if found, or null.
069       */
070      @Override
071      public synchronized TelemetryDefinitionInfo get(
072          User owner, String name, boolean includeShared, TelemetryDefinitionType type) {
073        TelemetryDefinitionInfo defInfo = null;
074        if (this.linkToGlobalSingleton) {
075          defInfo = this.globalSingleton.get(owner, name, includeShared, type);
076        }
077        if (defInfo == null) {
078          TelemetryDefinitionInfoRepository repository 
079              = this.defInfoRepositoryMap.get(type);
080          if (repository == null) {
081            throw new RuntimeException("Unknow telemetry definition type " + type);
082          }
083          else {
084            defInfo = repository.find(owner, name, includeShared);   
085          }
086        }
087        return defInfo;
088      }
089    
090      /**
091       * Gets all telemetry definitions that this user has access to.
092       * 
093       * @param owner The owner of the telemetry definitions returned.
094       * @param includeShared If true, then those telemetry definitions owned by
095       *        other users, but is shared will also be returned.
096       * @param type The definition type.
097       *       
098       * @return A collection of found objects.
099       */
100      @Override
101      public synchronized Collection<TelemetryDefinitionInfo> getAll(User owner, boolean includeShared, 
102          TelemetryDefinitionType type) {
103        ArrayList<TelemetryDefinitionInfo> result = new ArrayList<TelemetryDefinitionInfo>();
104        if (this.linkToGlobalSingleton) {
105          result.addAll(this.globalSingleton.getAll(owner, includeShared, type));
106        }
107        TelemetryDefinitionInfoRepository repository 
108            = this.defInfoRepositoryMap.get(type);
109        if (repository == null) {
110            throw new RuntimeException("Unknown telemetry definition type " + type);
111        }
112        else {
113          result.addAll(repository.findAll(owner, includeShared));
114        }
115        return result;
116      }
117    
118      /**
119       * Adds information about a definition.
120       * 
121       * @param defInfo Information about the definition to be added.
122       * 
123       * @throws TelemetryConfigurationException If there is duplicated definition.
124       */
125      @Override
126      public synchronized void add(TelemetryDefinitionInfo defInfo) 
127          throws TelemetryConfigurationException {
128        if (this.linkToGlobalSingleton && this.globalSingleton.isDefinition(defInfo.getName())) {
129          throw new TelemetryConfigurationException(
130              "All telemetry definitions (chart, report) share a global namespace. The name '"
131              + defInfo.getName() + "' is already used by either you or other user.");        
132        }
133        
134        TelemetryDefinitionInfoRepository repository 
135            = this.defInfoRepositoryMap.get(defInfo.getType());
136        if (repository == null) {
137            throw new RuntimeException("Unknow telemetry definition: " + defInfo.getClass().getName());
138        }
139        else {
140          //check namespace constraint.
141          for (TelemetryDefinitionInfoRepository rep : this.defInfoRepositoryMap.values()) {
142            if (rep.exists(defInfo.getName())) {
143              throw new TelemetryConfigurationException(
144                  "All telemetry definitions (chart, report) share a global namespace. The name '"
145                  + defInfo.getName() + "' is already used by either you or other user.");    
146            }
147          }
148          //add
149          repository.add(defInfo);
150        }  
151      }
152    
153      /**
154       * Deletes a telemetry object definition. Does nothing if the definition does not exist.
155       * 
156       * @param owner The owner of the definition.
157       * @param name The name of the definition.
158       * @param type The definition type.
159       */
160      @Override
161      public synchronized void remove(User owner, String name, TelemetryDefinitionType type) {
162        TelemetryDefinitionInfoRepository repository 
163            = this.defInfoRepositoryMap.get(type);
164        if (repository == null) {
165            throw new RuntimeException("Unknow telemetry definition type " + type);
166        }
167        else {
168          repository.remove(owner, name);  
169        } 
170      }
171    
172      /**
173       * Not yet implemented.
174       * @return Returns null.
175       */
176      @Override
177      public List<TelemetryDefinition> getDefinitions() {
178        return null;
179      }
180    }