text:
// Copyright 2008 The open-vcdiff Authors. All Rights Reserved.
//
// Licensed 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.

#include <config.h>
#include "google/vcencoder.h"
#include <stdlib.h>  // free, posix_memalign
#include <string.h>  // memcpy
#include <algorithm>
#include <string>
#include <vector>
#include "blockhash.h"
#include "checksum.h"
#include "testing.h"
#include "varint_bigendian.h"
#include "google/vcdecoder.h"
#include "google/jsonwriter.h"
#include "vcdiff_defs.h"

#ifdef HAVE_EXT_ROPE
#include <ext/rope>
#include "output_string_crope.h"
using __gnu_cxx::crope;
#endif  // HAVE_EXT_ROPE

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif  // HAVE_MALLOC_H

#ifdef HAVE_SYS_MMAN_H
#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
#undef  _XOPEN_SOURCE
#define _XOPEN_SOURCE 600  // posix_memalign
#endif
#include <sys/mman.h>  // mprotect
#endif  // HAVE_SYS_MMAN_H

#ifdef HAVE_UNISTD_H
#include <unistd.h>  // getpagesize
#endif  // HAVE_UNISTD_H

namespace open_vcdiff {
namespace {

static const size_t kFileHeaderSize = sizeof(DeltaFileHeader);

// This is to check the maximum possible encoding size
// if using a single ADD instruction, so assume that the
// dictionary size, the length of the ADD data, the size
// of the target window, and the length of the delta window
// are all two-byte Varints, that is, 128 <= length < 4096.
// This figure includes three extra bytes for a zero-sized
// ADD instruction with a two-byte Varint explicit size.
// Any additional COPY & ADD instructions must reduce
// the length of the encoding from this maximum.
static const size_t kWindowHeaderSize = 21;

class VerifyEncodedBytesTest : public testing::Test {
 public:
  typedef std::string string;

  VerifyEncodedBytesTest() : delta_index_(0) { }
  virtual ~VerifyEncodedBytesTest() { }

  void ExpectByte(unsigned char b) {
    EXPECT_EQ(b, static_cast<unsigned char>(delta_[delta_index_]));
    ++delta_index_;
  }

  void ExpectString(const char* s) {
    const size_t size = strlen(s);  // don't include terminating NULL char
    EXPECT_EQ(s, string(delta_data() + delta_index_, size));
    delta_index_ += size;
  }

  void ExpectNoMoreBytes() {
    EXPECT_EQ(delta_index_, delta_size());
  }

  void ExpectSize(size_t size) {
    const char* delta_size_pos = &delta_[delta_index_];
    EXPECT_EQ(size,
              static_cast<size_t>(
                  VarintBE<int32_t>::Parse(delta_data() + delta_size(),
                                           &delta_size_pos)));
    delta_index_ = delta_size_pos - delta_data();
  }

  void ExpectChecksum(VCDChecksum checksum) {
    const char* delta_checksum_pos = &delta_[delta_index_];
    EXPECT_EQ(checksum,
              static_cast<VCDChecksum>(
                  VarintBE<int64_t>::Parse(delta_data() + delta_size(),
                                           &delta_checksum_pos)));
    delta_index_ = delta_checksum_pos - delta_data();
  }

  const string& delta_as_const() const { return delta_; }
  string* delta() { return &delta_; }

  const char* delta_data() const { return delta_as_const().data(); }
  size_t delta_size() const { return delta_as_const().size(); }

 private:
  string delta_;
  size_t delta_index_;
};

class VCDiffEncoderTest : public VerifyEncodedBytesTest {
 protected:
  static const char kDictionary[];
  static const char kTarget[];
  static const char kJSONDiff[];
  static const char kNonAscii[];

  VCDiffEncoderTest();
  virtual ~VCDiffEncoderTest() { }

  void TestWithFixedChunkSize(VCDiffStreamingEncoder *encoder,
                              VCDiffStreamingDecoder *decoder,
                              size_t chunk_size);
  void TestWithEncodedChunkVector(size_t chunk_size);

  HashedDictionary hashed_dictionary_;
  VCDiffStreamingEncoder encoder_;
  VCDiffStreamingDecoder decoder_;
  VCDiffEncoder simple_encoder_;
  VCDiffDecoder simple_decoder_;
  VCDiffStreamingEncoder json_encoder_;
  VCDiffStreamingEncoder external_encoder_;
  VCDiffEncoder nonascii_simple_encoder_;

  string result_target_;
};

const char VCDiffEncoderTest::kDictionary[] =
    "\"Just the place for a Snark!\" the Bellman cried,\n"
    "As he landed his crew with care;\n"
    "Supporting each man on the top of the tide\n"
    "By a finger entwined in his hair.\n";

const char VCDiffEncoderTest::kTarget[] =
    "\"Just the place for a Snark! I have said it twice:\n"
    "That alone should encourage the crew.\n"
    "Just the place for a Snark! I have said it thrice:\n"
    "What I tell you three times is true.\"\n";

const char VCDiffEncoderTest::kJSONDiff[] =
    "[\"\\\"Just the place for a Snark! I have said it twice:\\n"
    "That alone should encourage the crew.\\n\","
    "161,44,"
    "\"hrice:\\nWhat I tell you three times is true.\\\"\\n\"]";

// NonASCII string "foo\x128".
const char VCDiffEncoderTest::kNonAscii[] = {102, 111, 111, 128, 0};

VCDiffEncoderTest::VCDiffEncoderTest()
    : hashed_dictionary_(kDictionary, sizeof(kDictionary)),
      encoder_(&hashed_dictionary_,
               VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
               /* look_for_target_matches = */ true),
      simple_encoder_(kDictionary, sizeof(kDictionary)),
      json_encoder_(&hashed_dictionary_,
                    VCD_FORMAT_JSON,
                    /* look_for_target_matches = */ true),
      external_encoder_(&hashed_dictionary_,
                    0,
                    /* look_for_target_matches = */ true,
                    new JSONCodeTableWriter()),
      nonascii_simple_encoder_(kNonAscii, sizeof(kNonAscii)) {
  EXPECT_TRUE(hashed_dictionary_.Init());
}

TEST_F(VCDiffEncoderTest, EncodeBeforeStartEncoding) {
  EXPECT_FALSE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
}

TEST_F(VCDiffEncoderTest, FinishBeforeStartEncoding) {
  EXPECT_FALSE(encoder_.FinishEncoding(delta()));
}

TEST_F(VCDiffEncoderTest, EncodeDecodeNothing) {
  HashedDictionary nothing_dictionary("", 0);
  EXPECT_TRUE(nothing_dictionary.Init());
  VCDiffStreamingEncoder nothing_encoder(&nothing_dictionary,
                                         VCD_STANDARD_FORMAT,
                                         false);
  EXPECT_TRUE(nothing_encoder.StartEncoding(delta()));
  EXPECT_TRUE(nothing_encoder.FinishEncoding(delta()));
  decoder_.StartDecoding("", 0);
  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
                                   delta_size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_TRUE(result_target_.empty());
}

TEST_F(VCDiffEncoderTest, EncodeNothingJSON) {
  HashedDictionary nothing_dictionary("", 0);
  EXPECT_TRUE(nothing_dictionary.Init());
  VCDiffStreamingEncoder nothing_encoder(&nothing_dictionary,
                                         VCD_FORMAT_JSON,
                                         false);
  EXPECT_TRUE(nothing_encoder.StartEncoding(delta()));
  EXPECT_TRUE(nothing_encoder.FinishEncoding(delta()));
  EXPECT_EQ("", delta_as_const());
}

// A NULL dictionary pointer is legal as long as the dictionary size is 0.
TEST_F(VCDiffEncoderTest, EncodeDecodeNullDictionaryPtr) {
  HashedDictionary null_dictionary(NULL, 0);
  EXPECT_TRUE(null_dictionary.Init());
  VCDiffStreamingEncoder null_encoder(&null_dictionary,
                                      VCD_STANDARD_FORMAT,
                                      false);
  EXPECT_TRUE(null_encoder.StartEncoding(delta()));
  EXPECT_TRUE(null_encoder.EncodeChunk(kTarget, strlen(kTarget), delta()));
  EXPECT_TRUE(null_encoder.FinishEncoding(delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  decoder_.StartDecoding(NULL, 0);
  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
                                   delta_size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeDecodeSimple) {
  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeDecodeInterleaved) {
  simple_encoder_.SetFormatFlags(VCD_FORMAT_INTERLEAVED);
  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeDecodeInterleavedChecksum) {
  simple_encoder_.SetFormatFlags(VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM);
  EXPECT_TRUE(simple_encoder_.Encode(kTarget,
                                     strlen(kTarget),
                                     delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeDecodeSingleChunk) {
  EXPECT_TRUE(encoder_.StartEncoding(delta()));
  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
  EXPECT_TRUE(encoder_.FinishEncoding(delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
                                   delta_size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeSimpleJSON) {
  EXPECT_TRUE(json_encoder_.StartEncoding(delta()));
  EXPECT_TRUE(json_encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
  EXPECT_TRUE(json_encoder_.FinishEncoding(delta()));
  EXPECT_EQ(kJSONDiff, delta_as_const());
}

TEST_F(VCDiffEncoderTest, EncodeSimpleExternalJSON) {
  EXPECT_TRUE(external_encoder_.StartEncoding(delta()));
  EXPECT_TRUE(external_encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
  EXPECT_TRUE(external_encoder_.FinishEncoding(delta()));
  EXPECT_EQ(kJSONDiff, delta_as_const());
}

TEST_F(VCDiffEncoderTest, EncodeDecodeSeparate) {
  string delta_start, delta_encode, delta_finish;
  EXPECT_TRUE(encoder_.StartEncoding(&delta_start));
  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), &delta_encode));
  EXPECT_TRUE(encoder_.FinishEncoding(&delta_finish));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_start.size() + delta_encode.size() + delta_finish.size());
  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_start.data(),
                                   delta_start.size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_encode.data(),
                                   delta_encode.size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_finish.data(),
                                   delta_finish.size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, NonasciiDictionary) {
  EXPECT_TRUE(nonascii_simple_encoder_.Encode(kTarget,
                                              strlen(kTarget),
                                              delta()));
}

TEST_F(VCDiffEncoderTest, NonasciiDictionaryWithJSON) {
  nonascii_simple_encoder_.SetFormatFlags(VCD_FORMAT_JSON);
  EXPECT_FALSE(nonascii_simple_encoder_.Encode(kTarget,
                                               strlen(kTarget),
                                               delta()));
}

TEST_F(VCDiffEncoderTest, NonasciiTarget) {
  EXPECT_TRUE(simple_encoder_.Encode(kNonAscii, strlen(kNonAscii), delta()));
}

TEST_F(VCDiffEncoderTest, NonasciiTargetWithJSON) {
  simple_encoder_.SetFormatFlags(VCD_FORMAT_JSON);
  EXPECT_FALSE(simple_encoder_.Encode(kNonAscii, strlen(kNonAscii), delta()));
}

#ifdef HAVE_EXT_ROPE
// Test that the crope class can be used in place of a string for encoding
// and decoding.
TEST_F(VCDiffEncoderTest, EncodeDecodeCrope) {
  crope delta_crope, result_crope;
  EXPECT_TRUE(encoder_.StartEncoding(&delta_crope));
  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), &delta_crope));
  EXPECT_TRUE(encoder_.FinishEncoding(&delta_crope));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_crope.size());
  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
  // crope can't guarantee that its characters are contiguous, so the decoding
  // has to be done byte-by-byte.
  for (crope::const_iterator it = delta_crope.begin();
       it != delta_crope.end(); it++) {
    const char this_char = *it;
    EXPECT_TRUE(decoder_.DecodeChunk(&this_char, 1, &result_crope));
  }
  EXPECT_TRUE(decoder_.FinishDecoding());
  crope expected_target(kTarget);
  EXPECT_EQ(expected_target, result_crope);
}
#endif  // HAVE_EXT_ROPE

// Test the encoding and decoding with a fixed chunk size.
// If decoder is null, only test the encoding.
void VCDiffEncoderTest::TestWithFixedChunkSize(VCDiffStreamingEncoder *encoder,
                                               VCDiffStreamingDecoder *decoder,
                                               size_t chunk_size) {
  delta()->clear();
  EXPECT_TRUE(encoder->StartEncoding(delta()));
  for (size_t chunk_start_index = 0;
       chunk_start_index < strlen(kTarget);
       chunk_start_index += chunk_size) {
    size_t this_chunk_size = chunk_size;
    const size_t bytes_available = strlen(kTarget) - chunk_start_index;
    if (this_chunk_size > bytes_available) {
      this_chunk_size = bytes_available;
    }
    EXPECT_TRUE(encoder->EncodeChunk(&kTarget[chunk_start_index],
                                     this_chunk_size,
                                     delta()));
  }
  EXPECT_TRUE(encoder->FinishEncoding(delta()));
  const size_t num_windows = (strlen(kTarget) / chunk_size) + 1;
  const size_t size_of_windows =
      strlen(kTarget) + (kWindowHeaderSize * num_windows);
  EXPECT_GE(kFileHeaderSize + size_of_windows, delta_size());
  result_target_.clear();

  if (!decoder) return;

  decoder->StartDecoding(kDictionary, sizeof(kDictionary));
  for (size_t chunk_start_index = 0;
       chunk_start_index < delta_size();
       chunk_start_index += chunk_size) {
    size_t this_chunk_size = chunk_size;
    const size_t bytes_available = delta_size() - chunk_start_index;
    if (this_chunk_size > bytes_available) {
      this_chunk_size = bytes_available;
    }
    EXPECT_TRUE(decoder->DecodeChunk(delta_data() + chunk_start_index,
                                     this_chunk_size,
                                     &result_target_));
  }
  EXPECT_TRUE(decoder->FinishDecoding());
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeDecodeFixedChunkSizes) {
  // These specific chunk sizes have failed in the past
  TestWithFixedChunkSize(&encoder_, &decoder_, 6);
  TestWithFixedChunkSize(&encoder_, &decoder_, 45);
  TestWithFixedChunkSize(&encoder_, &decoder_, 60);

  // Now loop through all possible chunk sizes
  for (size_t chunk_size = 1; chunk_size < strlen(kTarget); ++chunk_size) {
    TestWithFixedChunkSize(&encoder_, &decoder_, chunk_size);
  }
}

TEST_F(VCDiffEncoderTest, EncodeFixedChunkSizesJSON) {
  // There is no JSON decoder; these diffs are created by hand.
  TestWithFixedChunkSize(&json_encoder_, NULL, 6);
  EXPECT_EQ("[\"\\\"Just \",\"the pl\",\"ace fo\",\"r a Sn\",\"ark! I\","
            "\" have \",\"said i\",\"t twic\",\"e:\\nTha\",\"t alon\","
            "\"e shou\",\"ld enc\",\"ourage\",\" the c\",\"rew.\\nJ\","
            "\"ust th\",\"e plac\",\"e for \",\"a Snar\",\"k! I h\","
            "\"ave sa\",\"id it \",\"thrice\",\":\\nWhat\",\" I tel\","
            "\"l you \",\"three \",\"times \",\"is tru\",\"e.\\\"\\n\"]",
            delta_as_const());
  TestWithFixedChunkSize(&json_encoder_, NULL, 45);
  EXPECT_EQ("[\"\\\"Just the place for a Snark! I have said it t\","
            "\"wice:\\nThat alone should encourage the crew.\\nJ\","
            "\"ust the place for a Snark! I have said it thr\",\"ice:\\n"
            "What I tell you three times is true.\\\"\\n\"]",
            delta_as_const());
  TestWithFixedChunkSize(&json_encoder_, NULL, 60);
  EXPECT_EQ("[\"\\\"Just the place for a Snark! I have said it twice:\\n"
            "That alon\",\"e should encourage the crew.\\n"
            "Just the place for a Snark! I h\",\"ave said it thrice:\\n"
            "What I tell you three times is true.\\\"\\n\"]",
            delta_as_const());
}

// If --allow_vcd_target=false is specified, the decoder will throw away some of
// the internally-stored decoded target beyond the current window.  Try
// different numbers of encoded window sizes to make sure that this behavior
// does not affect the results.
TEST_F(VCDiffEncoderTest, EncodeDecodeFixedChunkSizesNoVcdTarget) {
  decoder_.SetAllowVcdTarget(false);
  // Loop through all possible chunk sizes
  for (size_t chunk_size = 1; chunk_size < strlen(kTarget); ++chunk_size) {
    TestWithFixedChunkSize(&encoder_, &decoder_, chunk_size);
  }
}

// Splits the text to be encoded into fixed-size chunks.  Encodes each
// chunk and puts it into a vector of strings.  Then decodes each string
// in the vector and appends the result into result_target_.
void VCDiffEncoderTest::TestWithEncodedChunkVector(size_t chunk_size) {
  std::vector<string> encoded_chunks;
  string this_encoded_chunk;
  size_t total_chunk_size = 0;
  EXPECT_TRUE(encoder_.StartEncoding(&this_encoded_chunk));
  encoded_chunks.push_back(this_encoded_chunk);
  total_chunk_size += this_encoded_chunk.size();
  for (size_t chunk_start_index = 0;
       chunk_start_index < strlen(kTarget);
       chunk_start_index += chunk_size) {
    size_t this_chunk_size = chunk_size;
    const size_t bytes_available = strlen(kTarget) - chunk_start_index;
    if (this_chunk_size > bytes_available) {
      this_chunk_size = bytes_available;
    }
    this_encoded_chunk.clear();
    EXPECT_TRUE(encoder_.EncodeChunk(&kTarget[chunk_start_index],
                                     this_chunk_size,
                                     &this_encoded_chunk));
    encoded_chunks.push_back(this_encoded_chunk);
    total_chunk_size += this_encoded_chunk.size();
  }
  this_encoded_chunk.clear();
  EXPECT_TRUE(encoder_.FinishEncoding(&this_encoded_chunk));
  encoded_chunks.push_back(this_encoded_chunk);
  total_chunk_size += this_encoded_chunk.size();
  const size_t num_windows = (strlen(kTarget) / chunk_size) + 1;
  const size_t size_of_windows =
      strlen(kTarget) + (kWindowHeaderSize * num_windows);
  EXPECT_GE(kFileHeaderSize + size_of_windows, total_chunk_size);
  result_target_.clear();
  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
  for (std::vector<string>::iterator it = encoded_chunks.begin();
       it != encoded_chunks.end(); ++it) {
    EXPECT_TRUE(decoder_.DecodeChunk(it->data(), it->size(), &result_target_));
  }
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffEncoderTest, EncodeDecodeStreamOfChunks) {
  // Loop through all possible chunk sizes
  for (size_t chunk_size = 1; chunk_size < strlen(kTarget); ++chunk_size) {
    TestWithEncodedChunkVector(chunk_size);
  }
}

// Verify that HashedDictionary stores a copy of the dictionary text,
// rather than just storing a pointer to it.  If the dictionary buffer
// is overwritten after creating a HashedDictionary from it, it shouldn't
// affect an encoder that uses that HashedDictionary.
TEST_F(VCDiffEncoderTest, DictionaryBufferOverwritten) {
  string dictionary_copy(kDictionary, sizeof(kDictionary));
  HashedDictionary hd_copy(dictionary_copy.data(), dictionary_copy.size());
  EXPECT_TRUE(hd_copy.Init());
  VCDiffStreamingEncoder copy_encoder(&hd_copy,
                                      VCD_FORMAT_INTERLEAVED
                                          | VCD_FORMAT_CHECKSUM,
                                      /* look_for_target_matches = */ true);
  // Produce a reference version of the encoded text.
  string delta_before;
  EXPECT_TRUE(copy_encoder.StartEncoding(&delta_before));
  EXPECT_TRUE(copy_encoder.EncodeChunk(kTarget,
                                       strlen(kTarget),
                                       &delta_before));
  EXPECT_TRUE(copy_encoder.FinishEncoding(&delta_before));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_before.size());

  // Overwrite the dictionary text with all 'Q' characters.
  dictionary_copy.replace(0,
                          dictionary_copy.size(),
                          dictionary_copy.size(),
                          'Q');
  // When the encoder is used on the same target text after overwriting
  // the dictionary, it should produce the same encoded output.
  string delta_after;
  EXPECT_TRUE(copy_encoder.StartEncoding(&delta_after));
  EXPECT_TRUE(copy_encoder.EncodeChunk(kTarget, strlen(kTarget), &delta_after));
  EXPECT_TRUE(copy_encoder.FinishEncoding(&delta_after));
  EXPECT_EQ(delta_before, delta_after);
}

// Binary data test part 1: The dictionary and target data should not
// be treated as NULL-terminated.  An embedded NULL should be handled like
// any other byte of data.
TEST_F(VCDiffEncoderTest, DictionaryHasEmbeddedNULLs) {
  const char embedded_null_dictionary_text[] =
      { 0x00, 0xFF, 0xFE, 0xFD, 0x00, 0xFD, 0xFE, 0xFF, 0x00, 0x03 };
  const char embedded_null_target[] =
      { 0xFD, 0x00, 0xFD, 0xFE, 0x03, 0x00, 0x01, 0x00 };
  CHECK_EQ(10, sizeof(embedded_null_dictionary_text));
  CHECK_EQ(8, sizeof(embedded_null_target));
  HashedDictionary embedded_null_dictionary(embedded_null_dictionary_text,
      sizeof(embedded_null_dictionary_text));
  EXPECT_TRUE(embedded_null_dictionary.Init());
  VCDiffStreamingEncoder embedded_null_encoder(&embedded_null_dictionary,
      VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
      /* look_for_target_matches = */ true);
  EXPECT_TRUE(embedded_null_encoder.StartEncoding(delta()));
  EXPECT_TRUE(embedded_null_encoder.EncodeChunk(embedded_null_target,
                                                sizeof(embedded_null_target),
                                                delta()));
  EXPECT_TRUE(embedded_null_encoder.FinishEncoding(delta()));
  decoder_.StartDecoding(embedded_null_dictionary_text,
                         sizeof(embedded_null_dictionary_text));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
                                   delta_size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_EQ(sizeof(embedded_null_target), result_target_.size());
  EXPECT_EQ(string(embedded_null_target,
                   sizeof(embedded_null_target)),
            result_target_);
}

// Binary data test part 2: An embedded CR or LF should be handled like
// any other byte of data.  No text-processing of the data should occur.
TEST_F(VCDiffEncoderTest, DictionaryHasEmbeddedNewlines) {
  const char embedded_null_dictionary_text[] =
      { 0x0C, 0xFF, 0xFE, 0x0C, 0x00, 0x0A, 0xFE, 0xFF, 0x00, 0x0A };
  const char embedded_null_target[] =
      { 0x0C, 0x00, 0x0A, 0xFE, 0x03, 0x00, 0x0A, 0x00 };
  CHECK_EQ(10, sizeof(embedded_null_dictionary_text));
  CHECK_EQ(8, sizeof(embedded_null_target));
  HashedDictionary embedded_null_dictionary(embedded_null_dictionary_text,
      sizeof(embedded_null_dictionary_text));
  EXPECT_TRUE(embedded_null_dictionary.Init());
  VCDiffStreamingEncoder embedded_null_encoder(&embedded_null_dictionary,
      VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
      /* look_for_target_matches = */ true);
  EXPECT_TRUE(embedded_null_encoder.StartEncoding(delta()));
  EXPECT_TRUE(embedded_null_encoder.EncodeChunk(embedded_null_target,
                                                sizeof(embedded_null_target),
                                                delta()));
  EXPECT_TRUE(embedded_null_encoder.FinishEncoding(delta()));
  decoder_.StartDecoding(embedded_null_dictionary_text,
                         sizeof(embedded_null_dictionary_text));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
                                   delta_size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  EXPECT_EQ(sizeof(embedded_null_target), result_target_.size());
  EXPECT_EQ(string(embedded_null_target,
                   sizeof(embedded_null_target)),
            result_target_);
}

TEST_F(VCDiffEncoderTest, UsingWideCharacters) {
  const wchar_t wchar_dictionary_text[] =
      L"\"Just the place for a Snark!\" the Bellman cried,\n"
      L"As he landed his crew with care;\n"
      L"Supporting each man on the top of the tide\n"
      L"By a finger entwined in his hair.\n";

  const wchar_t wchar_target[] =
      L"\"Just the place for a Snark! I have said it twice:\n"
      L"That alone should encourage the crew.\n"
      L"Just the place for a Snark! I have said it thrice:\n"
      L"What I tell you three times is true.\"\n";

  HashedDictionary wchar_dictionary((const char*) wchar_dictionary_text,
                                    sizeof(wchar_dictionary_text));
  EXPECT_TRUE(wchar_dictionary.Init());
  VCDiffStreamingEncoder wchar_encoder(&wchar_dictionary,
                                       VCD_FORMAT_INTERLEAVED
                                           | VCD_FORMAT_CHECKSUM,
                                       /* look_for_target_matches = */ false);
  EXPECT_TRUE(wchar_encoder.StartEncoding(delta()));
  EXPECT_TRUE(wchar_encoder.EncodeChunk((const char*) wchar_target,
                                        sizeof(wchar_target),
                                        delta()));
  EXPECT_TRUE(wchar_encoder.FinishEncoding(delta()));
  decoder_.StartDecoding((const char*) wchar_dictionary_text,
                         sizeof(wchar_dictionary_text));
  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
                                   delta_size(),
                                   &result_target_));
  EXPECT_TRUE(decoder_.FinishDecoding());
  const wchar_t* result_as_wchar = (const wchar_t*) result_target_.data();
  EXPECT_EQ(wcslen(wchar_target), wcslen(result_as_wchar));
  EXPECT_EQ(0, wcscmp(wchar_target, result_as_wchar));
}

#if defined(HAVE_MPROTECT) && \
   (defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN))
// Bug 1220602: Make sure the encoder doesn't read past the end of the input
// buffer.
TEST_F(VCDiffEncoderTest, ShouldNotReadPastEndOfBuffer) {
  const size_t target_size = strlen(kTarget);

  // Allocate two memory pages.
  const int page_size = getpagesize();
  void* two_pages = NULL;
#ifdef HAVE_POSIX_MEMALIGN
  posix_memalign(&two_pages, page_size, 2 * page_size);
#else  // !HAVE_POSIX_MEMALIGN
  two_pages = memalign(page_size, 2 * page_size);
#endif  // HAVE_POSIX_MEMALIGN
  char* const first_page = reinterpret_cast<char*>(two_pages);
  char* const second_page = first_page + page_size;

  // Place the target string at the end of the first page.
  char* const target_with_guard = second_page - target_size;
  memcpy(target_with_guard, kTarget, target_size);

  // Make the second page unreadable.
  mprotect(second_page, page_size, PROT_NONE);

  // Now perform the encode operation, which will cause a segmentation fault
  // if it reads past the end of the buffer.
  EXPECT_TRUE(encoder_.StartEncoding(delta()));
  EXPECT_TRUE(encoder_.EncodeChunk(target_with_guard, target_size, delta()));
  EXPECT_TRUE(encoder_.FinishEncoding(delta()));

  // Undo the mprotect.
  mprotect(second_page, page_size, PROT_READ|PROT_WRITE);
  free(two_pages);
}

TEST_F(VCDiffEncoderTest, ShouldNotReadPastBeginningOfBuffer) {
  const size_t target_size = strlen(kTarget);

  // Allocate two memory pages.
  const int page_size = getpagesize();
  void* two_pages = NULL;
#ifdef HAVE_POSIX_MEMALIGN
  posix_memalign(&two_pages, page_size, 2 * page_size);
#else  // !HAVE_POSIX_MEMALIGN
  two_pages = memalign(page_size, 2 * page_size);
#endif  // HAVE_POSIX_MEMALIGN
  char* const first_page = reinterpret_cast<char*>(two_pages);
  char* const second_page = first_page + page_size;

  // Make the first page unreadable.
  mprotect(first_page, page_size, PROT_NONE);

  // Place the target string at the beginning of the second page.
  char* const target_with_guard = second_page;
  memcpy(target_with_guard, kTarget, target_size);

  // Now perform the encode operation, which will cause a segmentation fault
  // if it reads past the beginning of the buffer.
  EXPECT_TRUE(encoder_.StartEncoding(delta()));
  EXPECT_TRUE(encoder_.EncodeChunk(target_with_guard, target_size, delta()));
  EXPECT_TRUE(encoder_.FinishEncoding(delta()));

  // Undo the mprotect.
  mprotect(first_page, page_size, PROT_READ|PROT_WRITE);
  free(two_pages);
}
#endif  // HAVE_MPROTECT && (HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN)

class VCDiffHTML1Test : public VerifyEncodedBytesTest {
 protected:
  static const char kDictionary[];
  static const char kTarget[];
  static const char kRedundantTarget[];

  VCDiffHTML1Test();
  virtual ~VCDiffHTML1Test() { }

  void SimpleEncode();
  void StreamingEncode();

  HashedDictionary hashed_dictionary_;
  VCDiffStreamingEncoder encoder_;
  VCDiffStreamingDecoder decoder_;
  VCDiffEncoder simple_encoder_;
  VCDiffDecoder simple_decoder_;

  string result_target_;
};

const char VCDiffHTML1Test::kDictionary[] =
    "<html><font color=red>This part from the dict</font><br>";

const char VCDiffHTML1Test::kTarget[] =
    "<html><font color=red>This part from the dict</font><br>\n"
    "And this part is not...</html>";

const char VCDiffHTML1Test::kRedundantTarget[] =
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";  // 256

VCDiffHTML1Test::VCDiffHTML1Test()
    : hashed_dictionary_(kDictionary, sizeof(kDictionary)),
      encoder_(&hashed_dictionary_,
               VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
               /* look_for_target_matches = */ true),
      simple_encoder_(kDictionary, sizeof(kDictionary)) {
  EXPECT_TRUE(hashed_dictionary_.Init());
}

void VCDiffHTML1Test::SimpleEncode() {
  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kTarget, result_target_);
}

void VCDiffHTML1Test::StreamingEncode() {
  EXPECT_TRUE(encoder_.StartEncoding(delta()));
  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
  EXPECT_TRUE(encoder_.FinishEncoding(delta()));
}

TEST_F(VCDiffHTML1Test, CheckOutputOfSimpleEncoder) {
  SimpleEncode();
  // These values do not depend on the block size used for encoding
  ExpectByte(0xD6);  // 'V' | 0x80
  ExpectByte(0xC3);  // 'C' | 0x80
  ExpectByte(0xC4);  // 'D' | 0x80
  ExpectByte(0x00);  // Simple encoder never uses interleaved format
  ExpectByte(0x00);  // Hdr_Indicator
  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
  ExpectByte(sizeof(kDictionary));  // Dictionary length
  ExpectByte(0x00);  // Source segment position: start of dictionary
  if (BlockHash::kBlockSize < 16) {
    // A medium block size will catch the "his part " match.
    ExpectByte(0x22);  // Length of the delta encoding
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectByte(0x16);  // Length of the data section
    ExpectByte(0x05);  // Length of the instructions section
    ExpectByte(0x02);  // Length of the address section
    // Data section
    ExpectString("\nAnd t");      // Data for 1st ADD
    ExpectString("is not...</html>");  // Data for 2nd ADD
    // Instructions section
    ExpectByte(0x73);  // COPY size 0 mode VCD_SAME(0)
    ExpectByte(0x38);  // COPY size (56)
    ExpectByte(0x07);  // ADD size 6
    ExpectByte(0x19);  // COPY size 9 mode VCD_SELF
    ExpectByte(0x11);  // ADD size 16
    // Address section
    ExpectByte(0x00);  // COPY address (0) mode VCD_SAME(0)
    ExpectByte(0x17);  // COPY address (23) mode VCD_SELF
  } else if (BlockHash::kBlockSize <= 56) {
    // Any block size up to 56 will catch the matching prefix string.
    ExpectByte(0x29);  // Length of the delta encoding
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectByte(0x1F);  // Length of the data section
    ExpectByte(0x04);  // Length of the instructions section
    ExpectByte(0x01);  // Length of the address section
    ExpectString("\nAnd this part is not...</html>");  // Data for ADD
    // Instructions section
    ExpectByte(0x73);  // COPY size 0 mode VCD_SAME(0)
    ExpectByte(0x38);  // COPY size (56)
    ExpectByte(0x01);  // ADD size 0
    ExpectByte(0x1F);  // Size of ADD (31)
    // Address section
    ExpectByte(0x00);  // COPY address (0) mode VCD_SAME(0)
  } else {
    // The matching string is 56 characters long, and the block size is
    // 64 or greater, so no match should be found.
    ExpectSize(strlen(kTarget) + 7);  // Delta encoding len
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectSize(strlen(kTarget));  // Length of the data section
    ExpectByte(0x02);  // Length of the instructions section
    ExpectByte(0x00);  // Length of the address section
    // Data section
    ExpectString(kTarget);
    ExpectByte(0x01);  // ADD size 0
    ExpectSize(strlen(kTarget));
  }
  ExpectNoMoreBytes();
}

TEST_F(VCDiffHTML1Test, SimpleEncoderPerformsTargetMatching) {
  EXPECT_TRUE(simple_encoder_.Encode(kRedundantTarget,
                                     strlen(kRedundantTarget),
                                     delta()));
  EXPECT_GE(strlen(kRedundantTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kRedundantTarget, result_target_);
  // These values do not depend on the block size used for encoding
  ExpectByte(0xD6);  // 'V' | 0x80
  ExpectByte(0xC3);  // 'C' | 0x80
  ExpectByte(0xC4);  // 'D' | 0x80
  ExpectByte(0x00);  // Simple encoder never uses interleaved format
  ExpectByte(0x00);  // Hdr_Indicator
  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
  ExpectByte(sizeof(kDictionary));  // Dictionary length
  ExpectByte(0x00);  // Source segment position: start of dictionary
  ExpectByte(0x0C);  // Length of the delta encoding
  ExpectSize(strlen(kRedundantTarget));  // Size of the target window
  ExpectByte(0x00);  // Delta_indicator (no compression)
  ExpectByte(0x01);  // Length of the data section
  ExpectByte(0x04);  // Length of the instructions section
  ExpectByte(0x01);  // Length of the address section
  // Data section
  ExpectString("A");      // Data for ADD
  // Instructions section
  ExpectByte(0x02);  // ADD size 1
  ExpectByte(0x23);  // COPY size 0 mode VCD_HERE
  ExpectSize(strlen(kRedundantTarget) - 1);  // COPY size 255
  // Address section
  ExpectByte(0x01);  // COPY address (1) mode VCD_HERE
  ExpectNoMoreBytes();
}

TEST_F(VCDiffHTML1Test, SimpleEncoderWithoutTargetMatching) {
  simple_encoder_.SetTargetMatching(false);
  EXPECT_TRUE(simple_encoder_.Encode(kRedundantTarget,
                                     strlen(kRedundantTarget),
                                     delta()));
  EXPECT_GE(strlen(kRedundantTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kRedundantTarget, result_target_);
  // These values do not depend on the block size used for encoding
  ExpectByte(0xD6);  // 'V' | 0x80
  ExpectByte(0xC3);  // 'C' | 0x80
  ExpectByte(0xC4);  // 'D' | 0x80
  ExpectByte(0x00);  // Simple encoder never uses interleaved format
  ExpectByte(0x00);  // Hdr_Indicator
  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
  ExpectByte(sizeof(kDictionary));  // Dictionary length
  ExpectByte(0x00);  // Source segment position: start of dictionary
  ExpectSize(strlen(kRedundantTarget) + 0x0A);  // Length of the delta encoding
  ExpectSize(strlen(kRedundantTarget));  // Size of the target window
  ExpectByte(0x00);  // Delta_indicator (no compression)
  ExpectSize(strlen(kRedundantTarget));  // Length of the data section
  ExpectByte(0x03);  // Length of the instructions section
  ExpectByte(0x00);  // Length of the address section
  // Data section
  ExpectString(kRedundantTarget);      // Data for ADD
  // Instructions section
  ExpectByte(0x01);  // ADD size 0
  ExpectSize(strlen(kRedundantTarget));  // ADD size
  // Address section empty
  ExpectNoMoreBytes();
}

class VCDiffHTML2Test : public VerifyEncodedBytesTest {
 protected:
  static const char kDictionary[];
  static const char kTarget[];

  VCDiffHTML2Test();
  virtual ~VCDiffHTML2Test() { }

  void SimpleEncode();
  void StreamingEncode();

  HashedDictionary hashed_dictionary_;
  VCDiffStreamingEncoder encoder_;
  VCDiffStreamingDecoder decoder_;
  VCDiffEncoder simple_encoder_;
  VCDiffDecoder simple_decoder_;

  string result_target_;
};

const char VCDiffHTML2Test::kDictionary[] = "10\nThis is a test";

const char VCDiffHTML2Test::kTarget[] = "This is a test!!!\n";

VCDiffHTML2Test::VCDiffHTML2Test()
    : hashed_dictionary_(kDictionary, sizeof(kDictionary)),
      encoder_(&hashed_dictionary_,
               VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
               /* look_for_target_matches = */ true),
      simple_encoder_(kDictionary, sizeof(kDictionary)) {
  EXPECT_TRUE(hashed_dictionary_.Init());
}

void VCDiffHTML2Test::SimpleEncode() {
  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kTarget, result_target_);
}

void VCDiffHTML2Test::StreamingEncode() {
  EXPECT_TRUE(encoder_.StartEncoding(delta()));
  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
            delta_size());
  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
                                     sizeof(kDictionary),
                                     delta_as_const(),
                                     &result_target_));
  EXPECT_EQ(kTarget, result_target_);
}

TEST_F(VCDiffHTML2Test, VerifyOutputOfSimpleEncoder) {
  SimpleEncode();
  // These values do not depend on the block size used for encoding
  ExpectByte(0xD6);  // 'V' | 0x80
  ExpectByte(0xC3);  // 'C' | 0x80
  ExpectByte(0xC4);  // 'D' | 0x80
  ExpectByte(0x00);  // Simple encoder never uses interleaved format
  ExpectByte(0x00);  // Hdr_Indicator
  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
  ExpectByte(sizeof(kDictionary));  // Dictionary length
  ExpectByte(0x00);  // Source segment position: start of dictionary
  if (BlockHash::kBlockSize <= 8) {
    ExpectByte(12);  // Length of the delta encoding
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectByte(0x04);  // Length of the data section
    ExpectByte(0x02);  // Length of the instructions section
    ExpectByte(0x01);  // Length of the address section
    ExpectByte('!');
    ExpectByte('!');
    ExpectByte('!');
    ExpectByte('\n');
    ExpectByte(0x1E);  // COPY size 14 mode VCD_SELF
    ExpectByte(0x05);  // ADD size 4
    ExpectByte(0x03);  // COPY address (3) mode VCD_SELF
  } else {
    // Larger block sizes will not catch any matches.
    ExpectSize(strlen(kTarget) + 7);  // Delta encoding len
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectSize(strlen(kTarget));  // Length of the data section
    ExpectByte(0x02);  // Length of the instructions section
    ExpectByte(0x00);  // Length of the address section
    // Data section
    ExpectString(kTarget);
    ExpectByte(0x01);  // ADD size 0
    ExpectSize(strlen(kTarget));
  }
  ExpectNoMoreBytes();
}

TEST_F(VCDiffHTML2Test, VerifyOutputWithChecksum) {
  StreamingEncode();
  const VCDChecksum html2_checksum = ComputeAdler32(kTarget, strlen(kTarget));
  CHECK_EQ(5, VarintBE<int64_t>::Length(html2_checksum));
  // These values do not depend on the block size used for encoding
  ExpectByte(0xD6);  // 'V' | 0x80
  ExpectByte(0xC3);  // 'C' | 0x80
  ExpectByte(0xC4);  // 'D' | 0x80
  ExpectByte('S');  // Format extensions
  ExpectByte(0x00);  // Hdr_Indicator
  ExpectByte(VCD_SOURCE | VCD_CHECKSUM);  // Win_Indicator
  ExpectByte(sizeof(kDictionary));  // Dictionary length
  ExpectByte(0x00);  // Source segment position: start of dictionary
  if (BlockHash::kBlockSize <= 8) {
    ExpectByte(17);  // Length of the delta encoding
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectByte(0x00);  // Length of the data section
    ExpectByte(0x07);  // Length of the instructions section
    ExpectByte(0x00);  // Length of the address section
    ExpectChecksum(html2_checksum);
    ExpectByte(0x1E);  // COPY size 14 mode VCD_SELF
    ExpectByte(0x03);  // COPY address (3) mode VCD_SELF
    ExpectByte(0x05);  // ADD size 4
    ExpectByte('!');
    ExpectByte('!');
    ExpectByte('!');
    ExpectByte('\n');
  } else {
    // Larger block sizes will not catch any matches.
    ExpectSize(strlen(kTarget) + 12);  // Delta encoding len
    ExpectSize(strlen(kTarget));  // Size of the target window
    ExpectByte(0x00);  // Delta_indicator (no compression)
    ExpectByte(0x00);  // Length of the data section
    ExpectSize(0x02 + strlen(kTarget));  // Interleaved
    ExpectByte(0x00);  // Length of the address section
    ExpectChecksum(html2_checksum);
    // Data section
    ExpectByte(0x01);  // ADD size 0
    ExpectSize(strlen(kTarget));
    ExpectString(kTarget);
  }
  ExpectNoMoreBytes();
}

}  // anonymous namespace
}  // namespace open_vcdiff


text:
package dagger.functional.membersinject;

class ChildOfStringArray extends MembersInjectGenericParent<String[]> {

}

redpajama_set_name: RedPajamaGithub


text:
module RedHillConsulting::Core::ActiveRecord::ConnectionAdapters
  module Sqlite3Adapter
    def add_foreign_key(table_name, column_names, references_table_name, references_column_names, options = {})
    end

    def remove_foreign_key(table_name, foreign_key_name)
    end
  end
end


text:
#include "public/web/WebHeap.h"

#include "platform/heap/Handle.h"

namespace blink {

WebHeap::SafePointScope::SafePointScope()
{
    RELEASE_ASSERT(!ThreadState::current()->isAtSafePoint());
    ThreadState::current()->enterSafePoint(BlinkGC::HeapPointersOnStack, this);
}

WebHeap::SafePointScope::~SafePointScope()
{
    ThreadState::current()->leaveSafePoint();
}

void WebHeap::collectGarbageForTesting()
{
    Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::ForcedGC);
}

void WebHeap::collectAllGarbageForTesting()
{
    Heap::collectAllGarbage();
}

} // namespace blink


text:
QueueObserver の AutoScaling 設定を行うスクリプト

## Description
最新の TripleI/Core AMI イメージから ID を取得して、QueueObserver 用の AutoScalingGroup 設定を更新します。

## Usage

```
$ bin/qoasc
```

## License

[MIT](https://github.com/triple-i/QueueObserverAutoScalingConfigs/blob/master/LICENSE)

## Author

[triple-i](https://github.com/triple-i)


text:
package org.mlbdash.client.gdx.inning;

import name.pehl.piriti.xml.client.XmlReader;

import org.mlbdash.shared.gdx.inning.Pitch;

public interface PitchReader extends XmlReader<Pitch> {

}


text:
define(function () {
    'use strict';

    var TabManager = Backbone.Model.extend({
        defaults: function () {
            return {
                streamusForegroundUrl: 'chrome-extension://' + chrome.runtime.id + '/foreground.html',
                keyboardShortcutsUrl: 'chrome://extensions/configureCommands',
                youTubeUrlPatterns: ['*://*.youtube.com/watch?*', '*://*.youtu.be/*'],
                beatportUrlPatterns: ['*://*.beatport.com/*']
            };
        },

        initialize: function () {
            this.listenTo(Streamus.channels.tab.commands, 'notify:youTube', this._notifyYouTube);
            this.listenTo(Streamus.channels.tab.commands, 'notify:beatport', this._notifyBeatport);
        },

        isStreamusTabActive: function (callback) {
            var queryInfo = {
                url: this.get('streamusForegroundUrl'),
                lastFocusedWindow: true
            };

            this._queryTabs(queryInfo, function (tabs) {
                callback(tabs.length > 0);
            });
        },

        isStreamusTabOpen: function (callback) {
            var queryInfo = {
                url: this.get('streamusForegroundUrl'),
            };

            this._queryTabs(queryInfo, function (tabs) {
                callback(tabs.length > 0);
            });
        },

        showStreamusTab: function () {
            this._showTab(this.get('streamusForegroundUrl'));
        },

        showKeyboardShortcutsTab: function() {
            this._showTab(this.get('keyboardShortcutsUrl'));
        },

        _notifyYouTube: function (data) {
            this.messageYouTubeTabs(data);
        },

        _notifyBeatport: function (data) {
            this.messageBeatportTabs(data);
        },

        _showTab: function (urlPattern, url) {
            var queryInfo = {
                url: urlPattern
            };

            this._queryTabs(queryInfo, function (tabDetailsList) {
                if (tabDetailsList.length > 0) {
                    var anyTabHighlighted = _.some(tabDetailsList, function (tabDetails) {
                        return tabDetails.highlighted;
                    });

                    if (!anyTabHighlighted) {
                        //  Just use the first tab if none are highlighted -- all tabs which match the URL pattern are the same.
                        var firstTabDetails = tabDetailsList[0];

                        var highlightInfo = {
                            windowId: firstTabDetails.windowId,
                            tabs: firstTabDetails.index
                        };

                        this._highlightTabs(highlightInfo);
                    }
                } else {
                    chrome.tabs.create({
                        //  If a specific URL is provided then use it, otherwise assume the URL pattern is the URL.
                        url: url || urlPattern
                    });
                }
            }.bind(this));
        },

        //  This is sufficient to message all tabs as well as popped-out windows which aren't tabs.
        messageYouTubeTabs: function (message) {
            _.each(this.get('youTubeUrlPatterns'), function (youTubeUrlPattern) {
                var queryInfo = {
                    url: youTubeUrlPattern
                };

                this._queryTabs(queryInfo, function (tabs) {
                    _.each(tabs, function (tab) {
                        chrome.tabs.sendMessage(tab.id, message);
                    });
                });
            }, this);
        },

        messageBeatportTabs: function (message) {
            _.each(this.get('beatportUrlPatterns'), function (beatportUrlPattern) {
                var queryInfo = {
                    url: beatportUrlPattern
                };

                this._queryTabs(queryInfo, function (tabs) {
                    _.each(tabs, function (tab) {
                        chrome.tabs.sendMessage(tab.id, message);
                    });
                });
            }, this);
        },

        _queryTabs: function (queryInfo, callback) {
            chrome.tabs.query(queryInfo, callback);
        },

        _highlightTabs: function (highlightInfo) {
            //  TODO: The callback will be optional once Google resolves https://code.google.com/p/chromium/issues/detail?id=417564
            chrome.tabs.highlight(highlightInfo, _.noop);
        }
    });

    return TabManager;
});


text:
package com.cisco.axl.api._8;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

/**
 *
Java class for RCalledPartyTransformationPattern complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="RCalledPartyTransformationPattern">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence minOccurs="0">
 *         <element name="pattern" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="usage" type="{http://www.cisco.com/AXL/API/8.0}XPatternUsage" minOccurs="0"/>
 *         <element name="routePartitionName" type="{http://www.cisco.com/AXL/API/8.0}XFkType" minOccurs="0"/>
 *         <element name="calledPartyTransformationMask" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="dialPlanName" type="{http://www.cisco.com/AXL/API/8.0}XFkType" minOccurs="0"/>
 *         <element name="digitDiscardInstructionName" type="{http://www.cisco.com/AXL/API/8.0}XFkType" minOccurs="0"/>
 *         <element name="patternUrgency" type="{http://www.cisco.com/AXL/API/8.0}boolean" minOccurs="0"/>
 *         <element name="routeFilterName" type="{http://www.cisco.com/AXL/API/8.0}XFkType" minOccurs="0"/>
 *         <element name="calledPartyPrefixDigits" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="calledPartyNumberingPlan" type="{http://www.cisco.com/AXL/API/8.0}XNumberingPlan" minOccurs="0"/>
 *         <element name="calledPartyNumberType" type="{http://www.cisco.com/AXL/API/8.0}XPriOfNumber" minOccurs="0"/>
 *       </sequence>
 *       <attribute name="uuid" type="{http://www.cisco.com/AXL/API/8.0}XUUID" />
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RCalledPartyTransformationPattern", propOrder = {
    "pattern",
    "description",
    "usage",
    "routePartitionName",
    "calledPartyTransformationMask",
    "dialPlanName",
    "digitDiscardInstructionName",
    "patternUrgency",
    "routeFilterName",
    "calledPartyPrefixDigits",
    "calledPartyNumberingPlan",
    "calledPartyNumberType"
})
public class RCalledPartyTransformationPattern {

    protected String pattern;
    protected String description;
    protected String usage;
    protected XFkType routePartitionName;
    protected String calledPartyTransformationMask;
    protected XFkType dialPlanName;
    protected XFkType digitDiscardInstructionName;
    protected String patternUrgency;
    protected XFkType routeFilterName;
    protected String calledPartyPrefixDigits;
    protected String calledPartyNumberingPlan;
    protected String calledPartyNumberType;
    @XmlAttribute
    protected String uuid;

    /**
     * Gets the value of the pattern property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getPattern() {
        return pattern;
    }

    /**
     * Sets the value of the pattern property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setPattern(String value) {
        this.pattern = value;
    }

    /**
     * Gets the value of the description property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getDescription() {
        return description;
    }

    /**
     * Sets the value of the description property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setDescription(String value) {
        this.description = value;
    }

    /**
     * Gets the value of the usage property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getUsage() {
        return usage;
    }

    /**
     * Sets the value of the usage property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setUsage(String value) {
        this.usage = value;
    }

    /**
     * Gets the value of the routePartitionName property.
     *
     * @return
     *     possible object is
     *     {@link XFkType }
     *
     */
    public XFkType getRoutePartitionName() {
        return routePartitionName;
    }

    /**
     * Sets the value of the routePartitionName property.
     *
     * @param value
     *     allowed object is
     *     {@link XFkType }
     *
     */
    public void setRoutePartitionName(XFkType value) {
        this.routePartitionName = value;
    }

    /**
     * Gets the value of the calledPartyTransformationMask property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getCalledPartyTransformationMask() {
        return calledPartyTransformationMask;
    }

    /**
     * Sets the value of the calledPartyTransformationMask property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setCalledPartyTransformationMask(String value) {
        this.calledPartyTransformationMask = value;
    }

    /**
     * Gets the value of the dialPlanName property.
     *
     * @return
     *     possible object is
     *     {@link XFkType }
     *
     */
    public XFkType getDialPlanName() {
        return dialPlanName;
    }

    /**
     * Sets the value of the dialPlanName property.
     *
     * @param value
     *     allowed object is
     *     {@link XFkType }
     *
     */
    public void setDialPlanName(XFkType value) {
        this.dialPlanName = value;
    }

    /**
     * Gets the value of the digitDiscardInstructionName property.
     *
     * @return
     *     possible object is
     *     {@link XFkType }
     *
     */
    public XFkType getDigitDiscardInstructionName() {
        return digitDiscardInstructionName;
    }

    /**
     * Sets the value of the digitDiscardInstructionName property.
     *
     * @param value
     *     allowed object is
     *     {@link XFkType }
     *
     */
    public void setDigitDiscardInstructionName(XFkType value) {
        this.digitDiscardInstructionName = value;
    }

    /**
     * Gets the value of the patternUrgency property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getPatternUrgency() {
        return patternUrgency;
    }

    /**
     * Sets the value of the patternUrgency property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setPatternUrgency(String value) {
        this.patternUrgency = value;
    }

    /**
     * Gets the value of the routeFilterName property.
     *
     * @return
     *     possible object is
     *     {@link XFkType }
     *
     */
    public XFkType getRouteFilterName() {
        return routeFilterName;
    }

    /**
     * Sets the value of the routeFilterName property.
     *
     * @param value
     *     allowed object is
     *     {@link XFkType }
     *
     */
    public void setRouteFilterName(XFkType value) {
        this.routeFilterName = value;
    }

    /**
     * Gets the value of the calledPartyPrefixDigits property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getCalledPartyPrefixDigits() {
        return calledPartyPrefixDigits;
    }

    /**
     * Sets the value of the calledPartyPrefixDigits property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setCalledPartyPrefixDigits(String value) {
        this.calledPartyPrefixDigits = value;
    }

    /**
     * Gets the value of the calledPartyNumberingPlan property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getCalledPartyNumberingPlan() {
        return calledPartyNumberingPlan;
    }

    /**
     * Sets the value of the calledPartyNumberingPlan property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setCalledPartyNumberingPlan(String value) {
        this.calledPartyNumberingPlan = value;
    }

    /**
     * Gets the value of the calledPartyNumberType property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getCalledPartyNumberType() {
        return calledPartyNumberType;
    }

    /**
     * Sets the value of the calledPartyNumberType property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setCalledPartyNumberType(String value) {
        this.calledPartyNumberType = value;
    }

    /**
     * Gets the value of the uuid property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getUuid() {
        return uuid;
    }

    /**
     * Sets the value of the uuid property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setUuid(String value) {
        this.uuid = value;
    }

}


text:
package org.pocketserver.api.entity.projectile;

import org.pocketserver.api.entity.Projectile;

/**
 * Represents a thrown egg, a {@link Projectile projectile}.
 *
 * @author Nick Robson
 */
public interface ThrownEgg extends Projectile {

}


text:
package sbt
package compiler

	import java.io.File
	import IO.withTemporaryDirectory
	import org.specs._

object CompileTest extends Specification
{
	"Analysis compiler" should {
		"compile basic sources" in {
			WithCompiler( "2.9.1" )(testCompileAnalysis)
			WithCompiler( "2.9.0-1" )(testCompileAnalysis)
			WithCompiler( "2.8.0" )(testCompileAnalysis)
			WithCompiler( "2.8.1" )(testCompileAnalysis)
		}
	}

	"Raw compiler" should {
		"Properly handle classpaths" in {
			testClasspath("2.9.1")
			testClasspath("2.9.0-1")
			testClasspath("2.8.1")
			testClasspath("2.8.0")
		}
	}

	private def testCompileAnalysis(compiler: AnalyzingCompiler, log: Logger)
	{
		WithFiles( new File("Test.scala") -> "object Test" ) { sources =>
			withTemporaryDirectory { temp =>
				val callback = new xsbti.TestCallback
				compiler(sources, Nil, temp, Nil, callback, 10, log)
				(callback.beganSources) must haveTheSameElementsAs(sources)
			}
		}
	}

	val UsingCompiler = "object Test { classOf[scala.tools.nsc.Global] }"

	private def shouldFail(act: => Unit) =
	{
		val success = try { act; true } catch { case t if expectedException(t) => false }
		if(success) error("Expected exception not thrown")
	}
	private def expectedException(t: Throwable) =
		t match
		{
			case e: Exception => true
			case t if isMissingRequirementError(t) => true
			case _ => false
		}
	private def shouldSucceed(act: => Unit) =
		try { act } catch { case c: xsbti.CompileFailed => error(c.toString) }

	private def isMissingRequirementError(t: Throwable) = t.getClass.getName == "scala.tools.nsc.MissingRequirementError"
	private def testClasspath(scalaVersion: String) =
		WithCompiler.launcher { (launch, log) =>
			def compiler(bootLibrary: Boolean, compilerOnClasspath: Boolean): RawCompiler =
				new RawCompiler(ScalaInstance(scalaVersion, launch), new ClasspathOptions(bootLibrary, compilerOnClasspath, true, true, bootLibrary), log)

			val callback = new xsbti.TestCallback

			val standard = compiler(true, true)
			val noCompiler = compiler(true, false)
			val fullExplicit = compiler(false, false)

			val fullBoot = "-bootclasspath" :: fullExplicit.compilerArguments.createBootClasspath :: Nil
			val withCompiler = noCompiler.scalaInstance.compilerJar :: Nil
			val withLibrary = noCompiler.scalaInstance.libraryJar :: Nil
			val withLibraryCompiler = withLibrary ++ withCompiler

			WithFiles( new File("Test.scala") -> "object Test", new File("Test2.scala") -> UsingCompiler ) { case Seq(plain, useCompiler) =>
				val plainSrcs = Seq[File](plain)
				val compSrcs = Seq[File](useCompiler)
				withTemporaryDirectory { out =>
					shouldSucceed( standard(plainSrcs, Nil,  out, Nil) )
					shouldSucceed( standard(compSrcs, Nil,  out, Nil) )

					shouldSucceed( noCompiler(plainSrcs, Nil,  out, Nil) )
					shouldFail( noCompiler(compSrcs, Nil,  out, Nil) )
					shouldSucceed( noCompiler(compSrcs, withCompiler, out, Nil) )

					shouldFail( fullExplicit(plainSrcs, Nil, out, Nil) )
					shouldFail( fullExplicit(compSrcs, Nil, out, Nil) )
					shouldSucceed( fullExplicit(plainSrcs, withLibrary, out, fullBoot) )
					shouldSucceed( fullExplicit(compSrcs, withLibraryCompiler, out, fullBoot) )
					true must beTrue
				}
			}
		}
}


text:
'use strict';

var extend                = require('util')._extend
  , cookies               = require('./lib/cookies')
  , helpers               = require('./lib/helpers')
  , isFunction            = helpers.isFunction
  , constructObject       = helpers.constructObject
  , filterForCallback     = helpers.filterForCallback
  , constructOptionsFrom  = helpers.constructOptionsFrom
  , paramsHaveRequestBody = helpers.paramsHaveRequestBody
  ;

// organize params for patch, post, put, head, del
function initParams(uri, options, callback) {
  callback = filterForCallback([options, callback])
  options = constructOptionsFrom(uri, options)

  return constructObject()
    .extend({callback: callback})
    .extend({options: options})
    .extend({uri: options.uri})
    .done()
}

function request (uri, options, callback) {
  if (typeof uri === 'undefined')
    throw new Error('undefined is not a valid uri or options object.')

  var params = initParams(uri, options, callback)
  options = params.options
  options.callback = params.callback
  options.uri = params.uri

  return new request.Request(options)
}

function requester(params) {
  if(typeof params.options._requester === 'function')
    return params.options._requester
  return request
}

request.get = function (uri, options, callback) {
  var params = initParams(uri, options, callback)
  params.options.method = 'GET'
  return requester(params)(params.uri || null, params.options, params.callback)
}

request.head = function (uri, options, callback) {
  var params = initParams(uri, options, callback)
  params.options.method = 'HEAD'

  if (paramsHaveRequestBody(params))
    throw new Error("HTTP HEAD requests MUST NOT include a request body.")

  return requester(params)(params.uri || null, params.options, params.callback)
}

request.post = function (uri, options, callback) {
  var params = initParams(uri, options, callback)
  params.options.method = 'POST'
  return requester(params)(params.uri || null, params.options, params.callback)
}

request.put = function (uri, options, callback) {
  var params = initParams(uri, options, callback)
  params.options.method = 'PUT'
  return requester(params)(params.uri || null, params.options, params.callback)
}

request.patch = function (uri, options, callback) {
  var params = initParams(uri, options, callback)
  params.options.method = 'PATCH'
  return requester(params)(params.uri || null, params.options, params.callback)
}

request.del = function (uri, options, callback) {
  var params = initParams(uri, options, callback)
  params.options.method = 'DELETE'
  return requester(params)(params.uri || null, params.options, params.callback)
}

request.jar = function () {
  return cookies.jar()
}

request.cookie = function (str) {
  return cookies.parse(str)
}

request.defaults = function (options, requester) {
  var self = this
  var wrap = function (method) {
    var headerlessOptions = function (options) {
      options = extend({}, options)
      delete options.headers
      return options
    }

    var getHeaders = function (params, options) {
      return constructObject()
        .extend(options.headers)
        .extend(params.options.headers)
        .done()
    }

    return function (uri, opts, callback) {
      var params = initParams(uri, opts, callback)
      params.options = extend(headerlessOptions(options), params.options)

      if (options.headers)
        params.options.headers = getHeaders(params, options)

      if (isFunction(requester)) {
        if (method === self) {
          method = requester
        } else {
          params.options._requester = requester
        }
      }

      return method(params.options, params.callback)
    }
  }

  var defaults      = wrap(self)
  defaults.get      = wrap(self.get)
  defaults.patch    = wrap(self.patch)
  defaults.post     = wrap(self.post)
  defaults.put      = wrap(self.put)
  defaults.head     = wrap(self.head)
  defaults.del      = wrap(self.del)
  defaults.cookie   = wrap(self.cookie)
  defaults.jar      = self.jar
  defaults.defaults = self.defaults
  return defaults
}

request.forever = function (agentOptions, optionsArg) {
  var options = constructObject()
  if (optionsArg) options.extend(optionsArg)
  if (agentOptions) options.agentOptions = agentOptions

  options.extend({forever: true})
  return request.defaults(options.done())
}

// Exports

module.exports = request
request.Request = require('./request')
request.debug = process.env.NODE_DEBUG && /\brequest\b/.test(process.env.NODE_DEBUG)
request.initParams = initParams


text:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="bc.css">

### DevDay Conference in Munich and WPF DoEvents

Let's talk about doing events, from two radically different perspectives, one great big external one and lots of teeny-weeny little internal ones.

I'll share some pictures from the European DevDay conference and snow in Munich today, then discuss a WPF issue that came up last week:

- [DevDay conference in Munich](#2)
- [WPF DoEvents](#3)
- [Addendum on WPF versus WinForms](#4)
- [Addendum on Not Using Revit API within WPF `DataContext`](#5)
- [WPF element id converter](#6)

#### DevDay Conference in Munich

Today we held the one and only European DevDay conference in Munich:

[Jaime Rosales Duque](http://adndevblog.typepad.com/aec/jaime-rosales.html) came all the way from New York to help, and
[Jim Quanci](http://dances-with-elephants.typepad.com/blog/about-the-author.html) even further, from San Francisco.

We have participants from all over Europe and even some from India.

The next few days are dedicated to an abbreviated [Cloud Accelerator](http://autodeskcloudaccelerator.com) here that I am looking forward to very much.

Meanwhile, here is Maciej Szlek's WPF issue and solution:

#### WPF DoEvents

Exactly two months back, we discussed [PickPoint with WPF and no threads attached](http://thebuildingcoder.typepad.com/blog/2015/11/pickpoint-with-wpf-and-no-threads.html).

Now another modeless WPF issue was raised and solved by [Maciej 'Max' Szlek](http://maciejszlek.pl):

**Question:** I'm creating a WPF addin that performs operations which will take much time.

During this time the add-in dialogue don't respond until the operation ends, even when calling the external event Raise method by view-model command.

Do you have some workaround to achieve dialogue responsively during performing API operations?

**Answer:** Yes, I have heard about similar issues in the past involving blocking of modeless WPF forms.

Unfortunately, I cannot find the relevant thread any longer.

The workarounds involved stuff like setting the window focus, e.g. using GetForegroundWindow and SetForegroundWindow, and allowing the WPF form to access the Windows message queue.

I think Revit was somehow blocking the message queue, for some reason.

I think the solution involved [calling the DoEvents method](http://stackoverflow.com/questions/5181777/use-of-application-doevents).

A couple of WPF issues came up in the forum in the past couple of years, e.g.:

- [Revit API preventing WPF window regeneration](http://forums.autodesk.com/t5/revit-API/revit-API-dll-preventing-wpf-window-regeneration/m-p/5545975)
- [WPF window loses control when Revit API displays an error](http://forums.autodesk.com/t5/revit-API/wpf-window-loses-control-when-revit-API-displays-an-error/m-p/5319853)
- [WPF tutorial using WPF in Winforms](http://tech.pro/tutorial/799/wpf-tutorial-using-wpf-in-winforms)

On the other hand, you can tell from these discussions that some people are successfully using WPF forms, and the development team are not aware of any issues with them.

I recommend [sticking with Windows Forms](http://forums.autodesk.com/t5/revit-API/winforms-or-wpf/m-p/5558289) if you have a choice.

Here is another recent article on [modeless WPF forms, PickPoint and multithreading](http://thebuildingcoder.typepad.com/blog/2015/11/pickpoint-with-wpf-and-no-threads.html), addressing other issues that also might be of interest to you,
an [older one on WPF](http://thebuildingcoder.typepad.com/blog/2012/10/ensure-wpf-add-in-remains-in-foreground.html#2), and
a [comment on triggering an event from Jon](http://thebuildingcoder.typepad.com/blog/2013/12/triggering-immediate-external-event-execute.html?cid=6a00e553e16897883301a3fd3c071c970b#comment-6a00e553e16897883301a3fd3c071c970b).

Later, one little addition; I searched for "[Revit API WPF DoEvents](https://duckduckgo.com/?q=revit+API+WPF+doevents)" and found this article
on [multithreading throwing exceptions in Revit 2015](http://thebuildingcoder.typepad.com/blog/2014/05/multithreading-throws-exceptions-in-revit-2015.html).

**Response:** I grabbed this [DoEvents implementation on StackOverflow](http://stackoverflow.com/a/11899439) to
"start work on a method that runs on the Dispatcher thread, and it needs to block without blocking the UI Thread... implement a DoEvents based on the Dispatcher itself".

I don't like it, it's not too elegant, it forces to
break [mvvm](https://de.wikipedia.org/wiki/Model_View_ViewModel) pattern, but it works.

If you would like to see my ugly non-refactored test code, clone
my [ExternalEventTests sample on BitBucket](https://bitbucket.org/kedziormsz/externaleventtests.git),
also [saved locally](zip/kedziormsz-externaleventtests-6c9eee0b346a.zip) here on The Building Coder.

I haven't tested it much yet but it seems to be stable.

You can run it from the add-in manager – lack of static references to IExternalApplication.

On the occasion it allows to check if raised external events are queued or running next to each other. They are queued which is gooood but I think safer would be adapting below solution to the one external event – we don't know how the API engine will change in the future... ;) [pattern for semi-asynchronous Idling API access](http://thebuildingcoder.typepad.com/blog/2010/11/pattern-for-semi-asynchronous-idling-API-access.html)...

Anyways thank you for your very accurate advice!

What would be in your circle of interest is WpfCommand.

WpfWindow contains a WPF implementation of the DoEvents method (in the way mentioned before) which is injected to ViewModel to minimize dependencies.

ViewModel contains 3 commands.

The first picks doors (it use part of my little cross API version framework) – simply to check how modeless WPF window would behave during hiding, picking and showing again.

The second and third flip doors – both have their own external event with different handler implementation. ViewModel's setStatus method calls injected DoEvents method.

If you have some more questions let me know.

Oh, and you can feel free to publish this solution on the blog of course, I don't have any problem with that ;)

**Answer:** When you mention picking and flipping doors, that reminds me of the Revit SDK ModelessDialog `ModelessForm_ExternalEvent` and `ModelessForm_IdlingEvent` samples.

Are you aware of those?

Is there any similarity, or is your sample completely unrelated to those?

**Response:** Yes, I'm aware of those, but my approach is quite different.

Congratulations to Max on solving this, and many thanks for sharing it here with us!

#### Addendum on WPF versus WinForms

Jeroen Van Vlierden adds an update:

> Just to let you know: I noticed that you mentioned my thread on
a [WPF window losing control when Revit API displays an error](http://forums.autodesk.com/t5/revit-API/wpf-window-loses-control-when-revit-API-displays-an-error/m-p/5319853) above.

> I can add to this that I managed to work around the issue by converting the wpf form to a user control and using this user control in a winforms window with a wpf element host.

> That works fine.

> It was however disappointing that I was forced to do this after I spent a lot of work on my application.

> Converting the application to winforms is no longer an option, so I will stick to this for now.

#### Addendum on Not Using Revit API within WPF `DataContext`

Hps Anave shares another nugget of WPF experience in
the [Revit API discussion forum](http://forums.autodesk.com/t5/revit-api/bd-p/160) thread
on [Revit API DLL preventing WPF window regeneration](http://forums.autodesk.com/t5/revit-api-forum/revit-api-dll-preventing-wpf-window-regeneration/m-p/6742531):

> Well, after a very long time integrating WPF in my own programs, my recommendation is NOT to use any Revit API class inside the view model class where you assign to the WPF window's `DataContext`.

> If ever you want to pass or get any information coming from an element or a parameter, it is better to extract its element Id's `IntegerValue`, and, when you are done with the WPF window, just create an `ElementId` from the integer value you acquired from the WPF window.

> There may be other solutions out there but this is the solution I have so far.

Many thanks to Hps for sharing this!

#### WPF Element Id Converter

In the same thread, Gonçalo Feio shared his WPF element id converter, saying, This works for me:

public class ElementIdConverter : IValueConverter
{
  public object Convert(
    object value,
    Type targetType,
    object parameter,
    CultureInfo culture )
  {
    if( value is R.ElementId )
    {
      return ( value as ElementId ).IntegerValue;
    }
    return -1;
  }

  public object ConvertBack(
    object value,
    Type targetType,
    object parameter,
    CultureInfo culture )
  {
    if( value is string )
    {
      int id;

      if( int.TryParse( value as string, out id ) )
      {
        return new ElementId( id );
      }
    }
    return ElementId.InvalidElementId;
  }
}

In this case, I expose a ElementId property in the view model.

You can also add validation to give some feedback to the end user.

Many thanks to Gonçalo for sharing this!

#### Hi


text:
using Cactus.Drivers;
using Cactus.PageLogic.GooglePages;
using NUnit.Framework;
using NUnit_retry;

namespace Cactus.TestCases.GoogleTests
{
    [TestFixture, Category("GoogleSample")]
    [Retry(Times = 5, RequiredPassCount = 1)]
    public class GenericTestCaseForGoogle : WebDriverTestBase
    {
        #region Local Test Constructors and Setup

        [TestFixtureSetUp]
        public void LocalSetupTests()
        {

        }

        [TestFixtureTearDown]
        public void LocalTearDownTests()
        {

        }

        [SetUp]
        public void LocalSetupTest()
        {
        }

        [TearDown]
        public void LocalTeardownTest()
        {

        }
        #endregion

        [Test, Timeout(60000)]
        public void QueryGoogle()
        {
            using (var page = new GoogleSearchPage())
            {
                page.OpenPage();
                page.Query.SetTextValue("elephant");
                page.Query.SendKeys("ENTER");
                page.Body.Assert.ShouldContainText("large mammals");
            }
            Support.ScreenShot();
        }
    }
}


text:
package TestFromYaml;
  use Moose;
  use YAML qw/LoadFile/;

  has file => (is => 'ro', isa => 'Str', required => 1);

  has _contents => (is => 'ro', isa => 'HashRef', lazy => 1, default => sub { LoadFile(shift->file) });

  has todo_reason => (is => 'ro', isa => 'Str|Undef', lazy => 1, default => sub { shift->_contents->{ todo } });
  has is_todo => (is => 'ro', isa => 'Bool', lazy => 1, default => sub { defined shift->todo_reason });

  has service => (is => 'ro', isa => 'Str|Undef', lazy => 1, default => sub { shift->_contents->{ service } });
  has method  => (is => 'ro', isa => 'Str|Undef', lazy => 1, default => sub { shift->_contents->{ call } });

  has exception => (is => 'ro', isa => 'Str|Undef', lazy => 1, default => sub {
    my $self = shift;
    exists $self->_contents->{ exception } and $self->_contents->{ exception } == 1
  });

  has tests => (is => 'ro', isa => 'ArrayRef|Undef', lazy => 1, default => sub {
    my $self = shift;
    return [] if (not exists $self->_contents->{ tests } or $self->_contents->{ tests } eq '');
    return $self->_contents->{ tests };
  });
  has has_tests => (is => 'ro', isa => 'Bool', lazy => 1, default => sub { defined shift->tests });

1;


text:
'use strict';

var docxtemplater = require('docxtemplater');
var util = require('util');

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks

  grunt.registerMultiTask('docxtemplater', 'Use docxtemplater in a grunt task.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      data: {}
    });

    // Iterate over all specified file groups.
    this.files.forEach(function(f) {
      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      });

      src.forEach(function(file){

        var content = grunt.file.read(file, {encoding: 'binary'});

        var doc = new docxtemplater(content);
        doc.setData(options.data);
        doc.render();

        var buf = doc.getZip().generate({type: 'nodebuffer'});
        grunt.file.write(f.dest, buf, {encoding: 'binary'});

        grunt.log.writeln('File "' + f.dest + '" created.');

      });

    });

  });

};


text:
package stripe

import (
	"encoding/json"
)

// CustomerParams is the set of parameters that can be used when creating or updating a customer.
// For more details see https://stripe.com/docs/api#create_customer and https://stripe.com/docs/api#update_customer.
type CustomerParams struct {
	Params         `form:"*"`
	Balance        int64                    `form:"account_balance"`
	BalanceZero    bool                     `form:"account_balance,zero"`
	BusinessVatID  string                   `form:"business_vat_id"`
	Coupon         string                   `form:"coupon"`
	CouponEmpty    bool                     `form:"coupon,empty"`
	DefaultSource  string                   `form:"default_source"`
	Desc           string                   `form:"description"`
	Email          string                   `form:"email"`
	Plan           string                   `form:"plan"`
	Quantity       uint64                   `form:"quantity"`
	Shipping       *CustomerShippingDetails `form:"shipping"`
	Source         *SourceParams            `form:"*"` // SourceParams has custom encoding so brought to top level with "*"
	TaxPercent     float64                  `form:"tax_percent"`
	TaxPercentZero bool                     `form:"tax_percent,zero"`
	Token          string                   `form:"-"` // This doesn't seem to be used?
	TrialEnd       int64                    `form:"trial_end"`
}

// SetSource adds valid sources to a CustomerParams object,
// returning an error for unsupported sources.
func (cp *CustomerParams) SetSource(sp interface{}) error {
	source, err := SourceParamsFor(sp)
	cp.Source = source
	return err
}

// CustomerListParams is the set of parameters that can be used when listing customers.
// For more details see https://stripe.com/docs/api#list_customers.
type CustomerListParams struct {
	ListParams   `form:"*"`
	Created      int64             `form:"created"`
	CreatedRange *RangeQueryParams `form:"created"`
}

// Customer is the resource representing a Stripe customer.
// For more details see https://stripe.com/docs/api#customers.
type Customer struct {
	Balance       int64                    `json:"account_balance"`
	BusinessVatID string                   `json:"business_vat_id"`
	Currency      Currency                 `json:"currency"`
	Created       int64                    `json:"created"`
	DefaultSource *PaymentSource           `json:"default_source"`
	Deleted       bool                     `json:"deleted"`
	Delinquent    bool                     `json:"delinquent"`
	Desc          string                   `json:"description"`
	Discount      *Discount                `json:"discount"`
	Email         string                   `json:"email"`
	ID            string                   `json:"id"`
	Live          bool                     `json:"livemode"`
	Meta          map[string]string        `json:"metadata"`
	Shipping      *CustomerShippingDetails `json:"shipping"`
	Sources       *SourceList              `json:"sources"`
	Subs          *SubList                 `json:"subscriptions"`
}

// CustomerList is a list of customers as retrieved from a list endpoint.
type CustomerList struct {
	ListMeta
	Values []*Customer `json:"data"`
}

// CustomerShippingDetails is the structure containing shipping information.
type CustomerShippingDetails struct {
	Address Address `json:"address" form:"address"`
	Name    string  `json:"name" form:"name"`
	Phone   string  `json:"phone" form:"phone"`
}

// UnmarshalJSON handles deserialization of a Customer.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (c *Customer) UnmarshalJSON(data []byte) error {
	type customer Customer
	var cc customer
	err := json.Unmarshal(data, &cc)
	if err == nil {
		*c = Customer(cc)
	} else {
		// the id is surrounded by "\" characters, so strip them
		c.ID = string(data[1 : len(data)-1])
	}

	return nil
}


text:
<?php

namespace OpenBadges\Client;

class Client
{
  private $base_url;

  public function __construct($base_url = BACKEND_BASE_URL)
  {
    $this->base_url = $base_url;
  }
}


text:
import logging
import telegram
from telegram.error import NetworkError, Unauthorized
from time import sleep

update_id = None

def main():
    global update_id
    # Telegram Bot Authorization Token
    bot = telegram.Bot('277679081:AAGk3IXlId9PKUn3n_5wrfrUIR_mgsUVCeE')

    # get the first pending update_id, this is so we can skip over it in case
    # we get an "Unauthorized" exception.
    try:
        update_id = bot.getUpdates()[0].update_id
    except IndexError:
        update_id = None

    logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    while True:
        try:
            echo(bot)
        except NetworkError:
            sleep(1)
        except Unauthorized:
            # The user has removed or blocked the bot.
            update_id += 1

def echo(bot):
    global update_id
    # Request updates after the last update_id
    for update in bot.getUpdates(offset=update_id, timeout=10):
        # chat_id is required to reply to any message
        chat_id = update.message.chat_id
        update_id = update.update_id + 1

        if update.message:  # your bot can receive updates without messages
            # Reply to the message
            update.message.reply_text(update.message.text)

if __name__ == '__main__':
    main()


text:
'use strict'

const test = require('tape')
const base64encode = require('@wmakeev/base64encode')

const Moysklad = require('..')

const BEARER_AUTH = 'Bearer token'
const BASIC_AUTH = 'Basic ' + base64encode('login:password')

const MOYSKLAD_LOGIN = process.env.MOYSKLAD_LOGIN
const MOYSKLAD_PASSWORD = process.env.MOYSKLAD_PASSWORD

const clearEnv = () => {
  delete process.env.MOYSKLAD_LOGIN
  delete process.env.MOYSKLAD_PASSWORD
  delete process.env.MOYSKLAD_TOKEN
  delete global.MOYSKLAD_LOGIN
  delete global.MOYSKLAD_PASSWORD
  delete global.MOYSKLAD_TOKEN
  delete global.window
}

const restoreEnv = () => {
  process.env.MOYSKLAD_LOGIN = MOYSKLAD_LOGIN
  process.env.MOYSKLAD_PASSWORD = MOYSKLAD_PASSWORD
  delete process.env.MOYSKLAD_TOKEN
  delete global.MOYSKLAD_LOGIN
  delete global.MOYSKLAD_PASSWORD
  delete global.MOYSKLAD_TOKEN
  delete global.window
}

test('Moysklad#getAuthHeader (no credentials)', t => {
  clearEnv()
  try {
    const msEmpty = Moysklad({ password: 'foo' })
    t.equal(
      msEmpty.getAuthHeader(),
      undefined,
      'should return undefined Basic auth without credentials'
    )
  } finally {
    restoreEnv()
  }

  t.end()
})

test('Moysklad#getAuthHeader (options)', t => {
  const msBasic = Moysklad({ login: 'login', password: 'password' })
  t.equal(
    msBasic.getAuthHeader(),
    BASIC_AUTH,
    'should return Basic auth with login option'
  )

  t.throws(
    () => {
      const msWoPass = Moysklad({ login: 'login' })
      msWoPass.getAuthHeader()
    },
    /пароль/,
    'should throw Error on empty password'
  )

  const msToken = Moysklad({
    token: 'token',
    login: 'login',
    password: 'password'
  })
  t.equal(
    msToken.getAuthHeader(),
    BEARER_AUTH,
    'should return Bearer auth with token option'
  )

  t.end()
})

test('Moysklad#getAuthHeader (env)', t => {
  clearEnv()
  try {
    process.env.MOYSKLAD_LOGIN = 'login'
    process.env.MOYSKLAD_PASSWORD = 'password'

    const msBasic = Moysklad()
    t.equal(
      msBasic.getAuthHeader(),
      BASIC_AUTH,
      'should return Basic auth with env options'
    )

    delete process.env.MOYSKLAD_PASSWORD
    t.throws(
      () => {
        const msWoPass = Moysklad()
        msWoPass.getAuthHeader()
      },
      /пароль/,
      'should throw Error on empty MOYSKLAD_PASSWORD env'
    )

    process.env.MOYSKLAD_TOKEN = 'token'
    const msToken = Moysklad()
    t.equal(
      msToken.getAuthHeader(),
      BEARER_AUTH,
      'should return Bearer auth with MOYSKLAD_TOKEN env'
    )
  } finally {
    restoreEnv()
  }

  t.end()
})

test('Moysklad#getAuthHeader (global)', t => {
  clearEnv()
  try {
    global.MOYSKLAD_LOGIN = 'login'
    global.MOYSKLAD_PASSWORD = 'password'

    const msBasic = Moysklad()
    t.equal(
      msBasic.getAuthHeader(),
      BASIC_AUTH,
      'should return Basic auth with global options'
    )

    delete global.MOYSKLAD_PASSWORD
    t.throws(
      () => {
        const msWoPass = Moysklad()
        msWoPass.getAuthHeader()
      },
      /пароль/,
      'should throw Error on empty MOYSKLAD_PASSWORD global'
    )

    delete global.MOYSKLAD_LOGIN
    global.MOYSKLAD_TOKEN = 'token'
    const msToken = Moysklad()
    t.equal(
      msToken.getAuthHeader(),
      BEARER_AUTH,
      'should return Bearer auth with MOYSKLAD_TOKEN global'
    )
  } finally {
    restoreEnv()
  }

  t.end()
})

test('Moysklad#getAuthHeader (window)', t => {
  clearEnv()
  global.window = {}

  try {
    global.window.MOYSKLAD_LOGIN = 'login'
    global.window.MOYSKLAD_PASSWORD = 'password'

    const msBasic = Moysklad()
    t.equal(
      msBasic.getAuthHeader(),
      BASIC_AUTH,
      'should return Basic auth with global options'
    )

    delete global.window.MOYSKLAD_PASSWORD
    t.throws(
      () => {
        const msWoPass = Moysklad()
        msWoPass.getAuthHeader()
      },
      /пароль/,
      'should throw Error on empty MOYSKLAD_PASSWORD global'
    )

    delete global.window.MOYSKLAD_LOGIN
    global.window.MOYSKLAD_TOKEN = 'token'
    const msToken = Moysklad()
    t.equal(
      msToken.getAuthHeader(),
      BEARER_AUTH,
      'should return Bearer auth with MOYSKLAD_TOKEN global'
    )
  } finally {
    restoreEnv()
  }

  t.end()
})


text:
package org.xmlcml.norma.editor;

import java.io.InputStream;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.xmlcml.xml.XMLUtil;

import nu.xom.Comment;
import nu.xom.Element;
import nu.xom.Node;
import nu.xom.ProcessingInstruction;
import nu.xom.Text;

/**
 * error detectors and corrector for potentially garbled strings
 *
 * see https://github.com/ContentMine/phylotree/issues/20
 *
 * simple pattern (detectOnly)
 *
 *
 *
 *   <pattern level="0">
    <!--  this regex enforces the ID patterns strictly.
    It will only fail when charcters are garbled to the same type, e.g.
    M->N , i->l, 3->8
    These are undetectable at this stage
     -->
    <space count="*"/>
    <!--  genus started with an uppercase letter followed by either several lowercase letters
    or on/two lowercase letters followed by period (abbreviation) -->
    <field name="genus" pattern="(?:\u2018?)[A-Z](?:[a-z]{2,}|[a-z]?\.)">
    </field>
    <space/>
    <!-- species should be only 2 or more lowercase characters -->
    <field name="species" pattern="[a-z]{2,}(?:\u2019?)">
    </field>
    <space/>
    <field name="strain" pattern="[^\s\(]+">
    </field>
    <space/>
    <!-- ID has an alpha and numeric part EU840723 or AJ307974 or NC_002967 -->
    <!-- require but strip left bracket -->
    <field name="id0" pattern="(?:\()[A-Z]{1,2}|NC_">
    <!--  and right bracket -->
    <field name="id1" pattern="[0-9]{5,6}(?:\)">
    </field>
    <space count="*"/>
  </pattern>

and

<pattern level="1">
    <!-- this regex allows for common garbles (detected as an error in 0)
    and error correction by "safe" correction. The correction will generate a conformant
    filed, but it may not be "correct". Each substitution has an error and can be logged.  -->
    <space count="*"/>
    <field name="genus" pattern="(?:\u2018?)[A-Z](?:[a-z]{2,}|[a-z02S/]?\.)">
      <substitution name="zero2little_o_or_big_o" original="0" edited="[oO]"/>
      <substitution name="two2little_z_or_big_z" original="2" edited="[zZ]"/>
      <substitution name="big_s2little_s" original="S" edited="s"/>
      <substitution name="slash2little_l_or_big_i" original="/" edited="[lI]"/>
      <!-- edit more as we find them -->
    </field>
    <space/>
    <field name="species" pattern="[a-z/]+(?:\u2019?)">
      <substitution name="s_slash_c2lower_sic" original="s/c" edited="sic"/>
      <substitution name="c_slash_l2lower_cil" original="d/" edited="cil"/>
      <substitution name="k_slash_n2lower_kin" original="k/n" edited="kin"/>
      <substitution name="r_slash_o2lower_rio" original="r/o" edited="rio"/>
      <substitution name="zero2little_o" original="0" edited="o"/>
      <substitution name="big_s2little_s" original="S" edited="s"/>
      <substitution name="slash2lower_l" original="/" edited="l"/>
    </field>
    <space/>
    <field name="strain" pattern="[^\s\(]+">
    </field>
    <space/>
    <field name="id0" pattern="(?:\()[A-Z123580]{1,2}|NC_">
      <!-- big letters may be garbled to numbers -->
      <substitution name="zero2big_o" original="0" edited="O"/>
      <substitution name="one2big_i" original="1" edited="I"/>
      <substitution name="two2big_z" original="2" edited="Z"/>
      <substitution name="three2big_b" original="3" edited="B"/>
      <substitution name="five2big_s" original="5" edited="S"/>
      <substitution name="eight2big_b" original="8" edited="B"/>
    </field>
    <field name="id1" pattern="[0-9BIOSZ]{5,6}(?:\)">
      <!--  numbers may be garbled to big letters -->
      <substitution name="big_o2zero" original="O" edited="0"/>
      <substitution name="big_b2eight" original="B" edited="eight"/>
      <substitution name="big_i2one" original="I" edited="one"/>
      <substitution name="big_s2five" original="S" edited="5"/>
      <substitution name="big_z2two" original="Z" edited="2"/>
    </field>
    <space count="*"/>
  </pattern>
 * @author pm286
 *
 */

public abstract class AbstractEditorElement extends Element {

	public static final Logger LOG = Logger.getLogger(AbstractEditorElement.class);
	static {
		LOG.setLevel(Level.DEBUG);
	}

	protected AbstractEditorElement(String tag) {
		super(tag);
	}

	public static AbstractEditorElement createEditorElement(InputStream is) {
		Element element = XMLUtil.parseQuietlyToDocument(is).getRootElement();
		AbstractEditorElement editorElement = AbstractEditorElement.createEditorElement(element);
		return editorElement;
	}

	protected SubstitutionEditor getSubstitutionEditor() {
		SubstitutionEditor editor = null;
		Node parent = this.getParent();
		if (parent instanceof AbstractEditorElement) {
			editor = ((AbstractEditorElement)parent).getSubstitutionEditor();
		}
		return editor;
	}

	/**
	 * Copy constructor from non-subclassed elements
	 */
	public static AbstractEditorElement createEditorElement(Element element) {
		AbstractEditorElement newElement = null;
		String tag = element.getLocalName();
		if (tag == null || tag.equals("")) {
			throw new RuntimeException("no tag");
		} else if (tag.equals(CombineElement.TAG)) {
			newElement = new CombineElement();
		} else if (tag.equals(ConstantElement.TAG)) {
			newElement = new ConstantElement();
		} else if (tag.equals(EditorElement.TAG)) {
			newElement = new EditorElement();
		} else if (tag.equals(FieldElement.TAG)) {
			newElement = new FieldElement();
		} else if (tag.equals(PatternElement.TAG)) {
			newElement = new PatternElement();
		} else if (tag.equals(PatternListElement.TAG)) {
			newElement = new PatternListElement();
		} else if (tag.equals(SpaceElement.TAG)) {
			newElement = new SpaceElement();
		} else if (tag.equals(SubstitutionElement.TAG)) {
			newElement = new SubstitutionElement();
		} else {
			throw new RuntimeException("unsupported editor element: "+tag);
		}
		if (newElement != null) {
	        XMLUtil.copyAttributes(element, newElement);
	        createSubclassedChildren(element, newElement);
		}
        return newElement;

	}
	protected static void createSubclassedChildren(Element oldElement, AbstractEditorElement newElement) {
		if (oldElement != null) {
			for (int i = 0; i < oldElement.getChildCount(); i++) {
				Node node = oldElement.getChild(i);
				Node newNode = null;
				if (node instanceof Text) {
					String value = node.getValue();
					newNode = new Text(value);
				} else if (node instanceof Comment) {
					newNode = new Comment(node.getValue());
				} else if (node instanceof ProcessingInstruction) {
					newNode = new ProcessingInstruction((ProcessingInstruction) node);
				} else if (node instanceof Element) {
					newNode = createEditorElement((Element) node);
				} else {
					throw new RuntimeException("Cannot create new node: "+node.getClass());
				}
				newElement.appendChild(newNode);
			}
		}
	}

}


text:
package echosign.api.clientv20.dto19;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
Java class for ArrayOfSignerFormFieldLocation complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="ArrayOfSignerFormFieldLocation">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="SignerFormFieldLocation" type="{http://dto19.api.echosign}SignerFormFieldLocation" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ArrayOfSignerFormFieldLocation", propOrder = {
    "signerFormFieldLocation"
})
public class ArrayOfSignerFormFieldLocation {

    @XmlElement(name = "SignerFormFieldLocation", nillable = true)
    protected List<SignerFormFieldLocation> signerFormFieldLocation;

    /**
     * Gets the value of the signerFormFieldLocation property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the signerFormFieldLocation property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getSignerFormFieldLocation().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link SignerFormFieldLocation }
     *
     *
     */
    public List<SignerFormFieldLocation> getSignerFormFieldLocation() {
        if (signerFormFieldLocation == null) {
            signerFormFieldLocation = new ArrayList<SignerFormFieldLocation>();
        }
        return this.signerFormFieldLocation;
    }

}