Package org.waveprotocol.wave.client.testing

Source Code of org.waveprotocol.wave.client.testing.UndercurrentHarness$Timeline

/**
* 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.testing;

import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Command;

import org.waveprotocol.wave.client.StageOne;
import org.waveprotocol.wave.client.StageThree;
import org.waveprotocol.wave.client.StageTwo;
import org.waveprotocol.wave.client.StageZero;
import org.waveprotocol.wave.client.Stages;
import org.waveprotocol.wave.client.common.safehtml.SafeHtmlBuilder;
import org.waveprotocol.wave.client.common.util.AsyncHolder;
import org.waveprotocol.wave.client.concurrencycontrol.MuxConnector;
import org.waveprotocol.wave.client.doodad.DoodadInstallers;
import org.waveprotocol.wave.client.doodad.attachment.AttachmentManagerProvider;
import org.waveprotocol.wave.client.doodad.attachment.testing.FakeAttachmentsManager;
import org.waveprotocol.wave.client.util.ClientFlags;
import org.waveprotocol.wave.client.util.NullTypedSource;
import org.waveprotocol.wave.client.util.OverridingTypedSource;
import org.waveprotocol.wave.client.wavepanel.impl.toolbar.color.ComplexColorPicker;
import org.waveprotocol.wave.client.wavepanel.impl.toolbar.color.SampleCustomColorPicker;
import org.waveprotocol.wave.common.bootstrap.FlagConstants;
import org.waveprotocol.wave.concurrencycontrol.channel.WaveViewService;
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.conversation.WaveBasedConversationView;
import org.waveprotocol.wave.model.document.util.XmlStringBuilder;
import org.waveprotocol.wave.model.id.IdGenerator;
import org.waveprotocol.wave.model.schema.SchemaProvider;
import org.waveprotocol.wave.model.schema.conversation.ConversationSchemas;
import org.waveprotocol.wave.model.testing.BasicFactories;
import org.waveprotocol.wave.model.testing.FakeIdGenerator;
import org.waveprotocol.wave.model.util.CollectionUtils;
import org.waveprotocol.wave.model.util.ReadableStringMap.ProcV;
import org.waveprotocol.wave.model.util.StringMap;
import org.waveprotocol.wave.model.wave.ParticipantId;
import org.waveprotocol.wave.model.wave.data.DocumentFactory;
import org.waveprotocol.wave.model.wave.data.ObservableWaveletData;
import org.waveprotocol.wave.model.wave.data.ReadableWaveletData;
import org.waveprotocol.wave.model.wave.data.WaveViewData;
import org.waveprotocol.wave.model.wave.data.impl.WaveViewDataImpl;
import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl;
import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
import org.waveprotocol.wave.model.wave.opbased.WaveViewImpl;
import org.waveprotocol.wave.model.wave.opbased.WaveViewImpl.WaveletConfigurator;
import org.waveprotocol.wave.model.wave.opbased.WaveViewImpl.WaveletFactory;

/**
* Kicks off some initial actions for development purposes.
*
*/
public class UndercurrentHarness implements EntryPoint {

  private UndercurrentHarness() {
  }

  private static boolean loaded;

  /**
   * Runs the harness script.
   */
  @Override
  public void onModuleLoad() {
    AttachmentManagerProvider.init(new FakeAttachmentsManager());
    if (loaded) {
      return;
    }
    loaded = true;

    final Timeline timeline = new Timeline();
    new Stages() {

      @Override
      protected AsyncHolder<StageZero> createStageZeroLoader() {
        return new StageZero.DefaultProvider() {

          @Override
          protected void onStageInit() {
            timeline.add("stage0_start");
          }

          @Override
          protected void onStageLoaded() {
            timeline.add("stage0_end");
          }

          @Override
          protected UncaughtExceptionHandler createUncaughtExceptionHandler() {
            return GWT.getUncaughtExceptionHandler();
          }
        };
      }

      @Override
      protected AsyncHolder<StageOne> createStageOneLoader(StageZero zero) {
        return new StageOne.DefaultProvider(zero) {
          @Override
          protected void onStageInit() {
            timeline.add("stage1_start");
          }

          @Override
          protected void onStageLoaded() {
            timeline.add("stage1_end");
          }

          @Override
          protected Element createWaveHolder() {
            return Document.get().getElementById("initialHtml");
          }
        };
      }

      @Override
      protected AsyncHolder<StageTwo> createStageTwoLoader(StageOne one) {
        return new StageTwo.DefaultProvider(one, null) {

          @Override
          protected void onStageInit() {
            timeline.add("stage2_start");
          }

          @Override
          protected void onStageLoaded() {
            timeline.add("stage2_end");
          }

          @Override
          protected void fetchWave(Accessor<WaveViewData> whenReady) {
            timeline.add("fakewave_start");
            WaveViewData fake = WaveFactory.create(getDocumentRegistry());
            timeline.add("fakewave_end");
            whenReady.use(fake);
          }

          @Override
          protected ParticipantId createSignedInUser() {
            return ParticipantId.ofUnsafe("nobody@example.com");
          }

          @Override
          protected String createSessionId() {
            return "session";
          }

          @Override
          protected MuxConnector createConnector() {
            return new MuxConnector() {
              @Override
              public void connect(Command whenOpened) {
                if (whenOpened != null) {
                  whenOpened.execute();
                }
              }

              @Override
              public void close() {
                // Ignore
              }
            };
          }

          @Override
          protected WaveViewService createWaveViewService() {
            // The vacuous MuxConnector should avoid the need for a
            // communication layer.
            throw new UnsupportedOperationException();
          }

          @Override
          protected SchemaProvider createSchemas() {
            return new ConversationSchemas();
          }
        };
      }

      @Override
      protected AsyncHolder<StageThree> createStageThreeLoader(StageTwo two) {
        ClientFlags.resetWithSourceForTesting(OverridingTypedSource.of(new NullTypedSource())
            .withBoolean(FlagConstants.ENABLE_UNDERCURRENT_EDITING, true)
            .build());

        // Only for test additional color pickers
        new SampleCustomColorPicker(ComplexColorPicker.getInstance());

        return new StageThree.DefaultProvider(two) {
          @Override
          protected void onStageInit() {
            timeline.add("stage3_start");
          }

          @Override
          protected void onStageLoaded() {
            timeline.add("stage3_end");
          }
        };
      }
    }.load(new Command() {
      @Override
      public void execute() {
        showInfo(timeline);
      }
    });
  }

  /**
   * Populates the info box. Continuously reports which element has browser
   * focus, and reports timing information for the stage loading.
   *
   * @param timeline timeline to report
   */
  private static void showInfo(Timeline timeline) {
    Element timeBox = Document.get().getElementById("timeline");
    timeline.dump(timeBox);

    Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
      private final Element activeBox = Document.get().getElementById("active");

      @Override
      public boolean execute() {
        Element e = getActiveElement();
        String text = (e != null ? e.getTagName() + " id:" + e.getId() : "none");
        activeBox.setInnerText(text);
        return true;
      }

      private native Element getActiveElement() /*-{
        return $doc.activeElement;
      }-*/;
    }, 1000);
  }

  /**
   * Creates a sample wave with a conversation in it.
   */
  private final static class WaveFactory {

    /**
     * Creates a sample wave.
     *
     * @param docFactory factory/registry for documents in the wave
     * @return the wave state of the sample wave.
     */
    public static WaveViewDataImpl create(DocumentFactory<?> docFactory) {
      // Create a sample wave.
      WaveViewData sampleData = createSampleWave();

      // Now build one that has the same setup state as that required by
      // undercurrent (complex issue with the per-document output sinks).
      WaveViewDataImpl newData = WaveViewDataImpl.create(sampleData.getWaveId());
      WaveletDataImpl.Factory copier = WaveletDataImpl.Factory.create(docFactory);
      for (ReadableWaveletData src : sampleData.getWavelets()) {
        WaveletDataImpl copied = copier.create(src);
        for (ParticipantId p : src.getParticipants()) {
          copied.addParticipant(p);
        }
        copied.setVersion(copied.getVersion());
        copied.setHashedVersion(src.getHashedVersion());
        copied.setLastModifiedTime(src.getLastModifiedTime());
        newData.addWavelet(copied);
      }
      return newData;
    }

    /** @return a sample wave with a conversation in it. */
    private static WaveViewData createSampleWave() {
      final ParticipantId sampleAuthor = ParticipantId.ofUnsafe("nobody@example.com");
      IdGenerator gen = FakeIdGenerator.create();
      final WaveViewDataImpl waveData = WaveViewDataImpl.create(gen.newWaveId());
      final DocumentFactory<?> docFactory = BasicFactories.fakeDocumentFactory();
      final ObservableWaveletData.Factory<?> waveletDataFactory =
          new ObservableWaveletData.Factory<WaveletDataImpl>() {
            private final ObservableWaveletData.Factory<WaveletDataImpl> inner =
                WaveletDataImpl.Factory.create(docFactory);

            @Override
            public WaveletDataImpl create(ReadableWaveletData data) {
              WaveletDataImpl wavelet = inner.create(data);
              waveData.addWavelet(wavelet);
              return wavelet;
            }
          };
      WaveletFactory<OpBasedWavelet> waveletFactory = BasicFactories
            .opBasedWaveletFactoryBuilder()
            .with(waveletDataFactory)
            .with(sampleAuthor)
            .build();

      WaveViewImpl<?> wave = WaveViewImpl.create(
          waveletFactory, waveData.getWaveId(), gen, sampleAuthor, WaveletConfigurator.ADD_CREATOR);

      // Build a conversation in that wave.
      ConversationView v = WaveBasedConversationView.create(wave, gen);
      Conversation c = v.createRoot();
      ConversationThread root = c.getRootThread();
      sampleReply(root.appendBlip());
      write(root.appendBlip());
      write(root.appendBlip());
      write(root.appendBlip());

      return waveData;
    }

    private static void write(ConversationBlip blip) {
      org.waveprotocol.wave.model.document.Document d = blip.getContent();
      d.emptyElement(d.getDocumentElement());
      d.appendXml(XmlStringBuilder.createFromXmlString("<body><line></line>Hello World</body>"));
    }

    private static void sampleReply(ConversationBlip blip) {
      write(blip);
      ConversationThread thread = blip.addReplyThread(8);
      write(thread.appendBlip());
    }

    private static void biggerSampleReply(ConversationBlip blip) {
      write(blip);
      ConversationThread thread = blip.addReplyThread();
      sampleReply(thread.appendBlip());
      sampleReply(thread.appendBlip());
      write(thread.appendBlip());
    }
  }

  private static class Timeline {
    private final StringMap<Integer> events = CollectionUtils.createStringMap();
    private final Duration duration = new Duration();

    void add(String name) {
      events.put(name, duration.elapsedMillis());
    }

    void dump(Element timeBox) {
      final SafeHtmlBuilder timeHtml = new SafeHtmlBuilder();
      timeHtml.appendHtmlConstant("<table cellpadding='0' cellspacing='0'>");
      events.each(new ProcV<Integer>() {
        @Override
        public void apply(String key, Integer value) {
          timeHtml.appendHtmlConstant("<tr><td>");
          timeHtml.appendEscaped(key);
          timeHtml.appendHtmlConstant(":</td><td>");
          timeHtml.appendEscaped("" + value);
          timeHtml.appendHtmlConstant("</td></tr>");
        }
      });
      timeHtml.appendHtmlConstant("</table>");
      timeBox.setInnerHTML(timeHtml.toSafeHtml().asString());

    }
  }
}
TOP

Related Classes of org.waveprotocol.wave.client.testing.UndercurrentHarness$Timeline

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.