Package org.waveprotocol.wave.client.wavepanel.view.fake

Source Code of org.waveprotocol.wave.client.wavepanel.view.fake.FakeRenderer$ViewStore

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.wave.client.wavepanel.view.fake;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;

import org.waveprotocol.wave.client.common.util.LinkedSequence;
import org.waveprotocol.wave.client.render.ReductionBasedRenderer;
import org.waveprotocol.wave.client.render.RenderingRules;
import org.waveprotocol.wave.client.render.WaveRenderer;
import org.waveprotocol.wave.client.wavepanel.view.AnchorView;
import org.waveprotocol.wave.client.wavepanel.view.BlipMetaView;
import org.waveprotocol.wave.client.wavepanel.view.BlipView;
import org.waveprotocol.wave.client.wavepanel.view.InlineThreadView;
import org.waveprotocol.wave.client.wavepanel.view.ParticipantView;
import org.waveprotocol.wave.client.wavepanel.view.ParticipantsView;
import org.waveprotocol.wave.client.wavepanel.view.RootThreadView;
import org.waveprotocol.wave.client.wavepanel.view.ThreadView;
import org.waveprotocol.wave.client.wavepanel.view.TopConversationView;
import org.waveprotocol.wave.client.wavepanel.view.View;
import org.waveprotocol.wave.client.wavepanel.view.dom.ModelAsViewProvider;
import org.waveprotocol.wave.model.conversation.Conversation;
import org.waveprotocol.wave.model.conversation.ConversationBlip;
import org.waveprotocol.wave.model.conversation.ConversationThread;
import org.waveprotocol.wave.model.conversation.ConversationView;
import org.waveprotocol.wave.model.util.CollectionUtils;
import org.waveprotocol.wave.model.util.IdentityMap;
import org.waveprotocol.wave.model.util.IdentityMap.ProcV;
import org.waveprotocol.wave.model.util.IdentityMap.Reduce;
import org.waveprotocol.wave.model.util.Pair;
import org.waveprotocol.wave.model.util.StringMap;
import org.waveprotocol.wave.model.wave.ParticipantId;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
* A wave renderer that renders waves into fake view objects.
*/
public final class FakeRenderer implements WaveRenderer<View>, ModelAsViewProvider {

  /** Factory and registry of fake views. */
  class ViewStore {
    final BiMap<ConversationBlip, FakeBlipView> blipUis = HashBiMap.create();
    final BiMap<Conversation, FakeConversationView> convUis = HashBiMap.create();
    final BiMap<ConversationThread, FakeRootThreadView> rootThreadUis = HashBiMap.create();
    final BiMap<ConversationThread, FakeInlineThreadView> inlineThreadUis = HashBiMap.create();
    final BiMap<ConversationThread, FakeAnchor> defaultAnchorUis = HashBiMap.create();
    final BiMap<ConversationThread, FakeAnchor> inlineAnchorUis = HashBiMap.create();

    /** Puts a value in a map and returns it. */
    private <K, V> V put(Map<? super K, ? super V> map, K key, V value) {
      map.put(key, value);
      return value;
    }

    FakeBlipView createBlipView(ConversationBlip blip, LinkedSequence<FakeAnchor> anchors,
        LinkedSequence<FakeInlineConversationView> convos) {
      return put(blipUis, blip, new FakeBlipView(FakeRenderer.this, anchors, convos));
    }

    FakeConversationView createTopConversationView(Conversation conv, FakeRootThreadView thread) {
      return put(convUis, conv, new FakeTopConversationView(thread));
    }

    FakeConversationView createInlineConversationView(
        Conversation conv, FakeRootThreadView thread) {
      return put(convUis, conv, new FakeInlineConversationView(thread));
    }

    FakeThreadView createRootThreadView(
        ConversationThread thread, LinkedSequence<FakeBlipView> blipUis) {
      return put(rootThreadUis, thread, new FakeRootThreadView(FakeRenderer.this, blipUis));
    }

    FakeThreadView createInlineThreadView(
        ConversationThread thread, LinkedSequence<FakeBlipView> blipUis) {
      return put(inlineThreadUis, thread, new FakeInlineThreadView(FakeRenderer.this, blipUis));
    }

    FakeAnchor createDefaultAnchorView(ConversationThread thread) {
      return put(defaultAnchorUis, thread, new FakeAnchor());
    }

    FakeAnchor createInlineAnchorView(ConversationThread thread) {
      return put(inlineAnchorUis, thread, new FakeAnchor());
    }
  }

  class Rules implements RenderingRules<View> {

    @Override
    public View render(ConversationBlip blip, IdentityMap<ConversationThread, View> replies) {
      return new FakeDocumentView(blip.getContent().toXmlString());
    }

    @Override
    public FakeBlipView render(ConversationBlip blip, View document,
        IdentityMap<ConversationThread, View> defaultAnchors,
        IdentityMap<Conversation, View> nestedReplies) {
      LinkedSequence<FakeAnchor> anchorsUi = LinkedSequence.create();
      for (ConversationThread reply : blip.getReplyThreads()) {
        anchorsUi.append((FakeAnchor) defaultAnchors.get(reply));
      }
      LinkedSequence<FakeInlineConversationView> nestedUis = LinkedSequence.create();
      // Order by conversation id. Ideally, the sort key would be creation
      // time, but that is not exposed in the conversation API.
      final List<Conversation> ordered = CollectionUtils.newArrayList();
      nestedReplies.each(new ProcV<Conversation, View>() {
        @Override
        public void apply(Conversation conv, View ui) {
          ordered.add(conv);
        }
      });
      Collections.sort(ordered, new Comparator<Conversation>() {
        @Override
        public int compare(Conversation o1, Conversation o2) {
          return o1.getId().compareTo(o2.getId());
        }
      });
      for (Conversation nested : ordered) {
        nestedUis.append((FakeInlineConversationView) nestedReplies.get(nested));
      }
      FakeBlipView blipUi = views.createBlipView(blip, anchorsUi, nestedUis);
      blipUi.getMeta().setContent((FakeDocumentView) document);
      return blipUi;
    }

    @Override
    public FakeThreadView render(
        ConversationThread thread, IdentityMap<ConversationBlip, View> blips) {
      LinkedSequence<FakeBlipView> blipUis = LinkedSequence.create();
      for (ConversationBlip blip : thread.getBlips()) {
        blipUis.append((FakeBlipView) blips.get(blip));
      }
      if (thread.getConversation().getRootThread().equals(thread)) {
        return views.createRootThreadView(thread, blipUis);
      } else {
        return views.createInlineThreadView(thread, blipUis);
      }
    }

    @Override
    public FakeConversationView render(Conversation conversation, View participants, View thread) {
      if (!conversation.hasAnchor()) {
        return views.createTopConversationView(conversation, (FakeRootThreadView) thread);
      } else {
        return views.createInlineConversationView(conversation, (FakeRootThreadView) thread);
      }
    }

    @Override
    public View render(Conversation conversation, ParticipantId participant) {
      // Ignore participants; not yet exercised by tests.
      return null;
    }

    @Override
    public View render(Conversation conversation, StringMap<View> participants) {
      // Ignore participants; not yet exercised by tests.
      return null;
    }

    @Override
    public TopConversationView render(
        ConversationView wave, IdentityMap<Conversation, View> conversations) {
      // Pick the first one.
      return conversations.isEmpty() ? null :
        conversations.reduce(null, new Reduce<Conversation, View, TopConversationView>() {
          @Override
          public TopConversationView apply(TopConversationView soFar, Conversation key, View item) {
            return soFar != null ? soFar : (TopConversationView) item;
          }
        });
    }

    @Override
    public FakeAnchor render(ConversationThread thread, View threadUi) {
      FakeAnchor anchor = views.createDefaultAnchorView(thread);
      anchor.attach((InlineThreadView) threadUi);
      return anchor;
    }

  }

  private final ViewStore views = new ViewStore();
  private final WaveRenderer<View> renderer;

  private FakeRenderer(ConversationView wave) {
    this.renderer = ReductionBasedRenderer.of(new Rules(), wave);
  }

  /**
   * Creates a renderer of fake views.
   */
  public static FakeRenderer create(ConversationView wave) {
    return new FakeRenderer(wave);
  }

  // TODO: Expose view store, so that fake views can remove themselves after
  // destruction, so that view lookups below do not report spurious results.
  // This code path is unique to this fake renderer, because in a DOM renderer,
  // cleanup occurs implicitly by virtue of lookups being based on
  // Document.getElementById().

  public FakeAnchor createInlineAnchor(ConversationThread thread) {
    return views.createInlineAnchorView(thread);
  }

  // Delegate wave-rendering to the internal driver.

  @Override
  public View render(Conversation conversation, ParticipantId participant) {
    return renderer.render(conversation, participant);
  }

  @Override
  public View render(Conversation conversation) {
    return renderer.render(conversation);
  }

  @Override
  public View render(ConversationBlip blip) {
    return renderer.render(blip);
  }

  @Override
  public View render(ConversationThread thread) {
    return renderer.render(thread);
  }

  @Override
  public View render(ConversationView wave) {
    return renderer.render(wave);
  }

  // Delegate view lookup to view store.

  @Override
  public BlipView getBlipView(ConversationBlip blip) {
    return views.blipUis.get(blip);
  }

  @Override
  public InlineThreadView getInlineThreadView(ConversationThread thread) {
    return views.inlineThreadUis.get(thread);
  }

  @Override
  public RootThreadView getRootThreadView(ConversationThread thread) {
    return views.rootThreadUis.get(thread);
  }

  @Override
  public org.waveprotocol.wave.client.wavepanel.view.ConversationView getConversationView(
      Conversation conv) {
    return views.convUis.get(conv);
  }

  @Override
  public BlipMetaView getBlipMetaView(ConversationBlip blip) {
    BlipView blipUi = getBlipView(blip);
    return blipUi != null ? blipUi.getMeta() : null;
  }

  @Override
  public AnchorView getDefaultAnchor(ConversationThread thread) {
    return views.defaultAnchorUis.get(thread);
  }

  @Override
  public AnchorView getInlineAnchor(ConversationThread thread) {
    return views.inlineAnchorUis.get(thread);
  }

  @Override
  public ParticipantsView getParticipantsView(Conversation conv) {
    // Participant views not supported.
    return null;
  }

  @Override
  public ParticipantView getParticipantView(Conversation conv, ParticipantId source) {
    return null;
  }

  // Inverse lookup.

  @Override
  public ConversationBlip getBlip(BlipView blipUi) {
    return views.blipUis.inverse().get(blipUi);
  }

  @Override
  public ConversationThread getThread(ThreadView threadUi) {
    ConversationThread inline = views.inlineThreadUis.inverse().get(threadUi);
    return inline != null ? inline : views.rootThreadUis.inverse().get(threadUi);
  }

  @Override
  public Pair<Conversation, ParticipantId> getParticipant(ParticipantView participantUi) {
    return null;
  }

  @Override
  public Conversation getParticipants(ParticipantsView participantsUi) {
    return null;
  }
}
TOP

Related Classes of org.waveprotocol.wave.client.wavepanel.view.fake.FakeRenderer$ViewStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.