public ImmutableSet<WaveletId> lookupWavelets(WaveId waveId) throws WaveletStateException {
   ListenableFuture<ImmutableSet<WaveletId>> future = waves.get(waveId).lookedupWavelets;
   try {
     return FutureUtil.getResultOrPropagateException(future, PersistenceException.class);
   } catch (PersistenceException e) {
     throw new WaveletStateException("Failed to look up wave " + waveId, e);
   } catch (InterruptedException e) {
     Thread.currentThread().interrupt();
     throw new WaveletStateException("Interrupted while looking up wave " + waveId, e);
   }
 }
 private <T extends WaveletContainer> T getWavelet(
     WaveletId waveletId, ConcurrentMap<WaveletId, T> waveletsMap) throws WaveletStateException {
   ImmutableSet<WaveletId> storedWavelets;
   try {
     storedWavelets =
         FutureUtil.getResultOrPropagateException(lookedupWavelets, PersistenceException.class);
   } catch (PersistenceException e) {
     throw new WaveletStateException(
         "Failed to lookup wavelet " + WaveletName.of(waveId, waveletId), e);
   } catch (InterruptedException e) {
     Thread.currentThread().interrupt();
     throw new WaveletStateException(
         "Interrupted looking up wavelet " + WaveletName.of(waveId, waveletId), e);
   }
   // Since waveletsMap is a computing map, we must call containsKey(waveletId)
   // to tell if waveletId is mapped, we cannot test if get(waveletId) returns null.
   if (!storedWavelets.contains(waveletId) && !waveletsMap.containsKey(waveletId)) {
     return null;
   } else {
     T wavelet = waveletsMap.get(waveletId);
     Preconditions.checkNotNull(wavelet, "computingMap returned null");
     return wavelet;
   }
 }