Codebase list mozc / e648a44 sync / contact_list_util.cc
e648a44

Tree @e648a44 (Download .tar.gz)

contact_list_util.cc @e648a44raw · history · blame

// Copyright 2010-2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "sync/contact_list_util.h"

#include <string>

#include "base/util.h"
#include "dictionary/user_dictionary_storage.pb.h"
#include "dictionary/user_dictionary_util.h"
#include "third_party/jsoncpp/json.h"

namespace mozc {
namespace sync {

// The input string |contact_update| must be a json script, and is expected to
// have a structure like described below.
// { "feed" : { "entry" : {
//   [
//     "gd$name" : {
//       "gd$familyName" : { "$t" : "具卯", "yomi" : "ぐう" },
//       "gd$givenName" : { "$t" : "狗流", "yomi" : "ぐる" }
//     }
//   ],
//   [ ... (other members' information like above) ... ],
// }}}
// Please refer [1] and [2] for its details.
// [1] http://code.google.com/intl/ja/apis/gdata/docs/2.0/elements.html
// [2] http://code.google.com/intl/ja/apis/gdata/docs/json.html
bool ContactListUtil::ParseContacts(const string &contact_update,
    user_dictionary::UserDictionaryStorage::UserDictionary *user_dictionary,
    string *last_timestamp) {
  DCHECK(user_dictionary);
  DCHECK(last_timestamp);

  // convert Json script to Json class
  Json::Value root;
  Json::Reader reader;
  if (!reader.parse(contact_update, root)) {
    LOG(INFO) << "Parsing contact information failed.";
    return false;
  }

  if (!root.isMember("feed")) {
    LOG(INFO) << "contact_update has no feed member";
    return false;
  }
  if (!root["feed"].isMember("entry")) {
    LOG(INFO) << "contact_update has no entry member";
    return false;
  }

  Json::Value &members = root["feed"]["entry"];
  for (Json::Value::iterator it = members.begin(); it != members.end(); ++it) {
    if (!(*it).isMember("gd$name")) {
      continue;
    }
    Json::Value &name = (*it)["gd$name"];

    string kanji;
    string yomi;
    // Some users may set their full name in family name field or given name
    // field, so we check both fields to make full names.
    if (name.isMember("gd$familyName")) {
      Json::Value &family = name["gd$familyName"];
      if (family.isMember("$t")) {
        kanji += family["$t"].asString();
      }
      if (family.isMember("yomi")) {
        yomi += family["yomi"].asString();
      }
    }
    if (name.isMember("gd$givenName")) {
      Json::Value &given = name["gd$givenName"];
      if (given.isMember("$t")) {
        kanji += given["$t"].asString();
      }
      if (given.isMember("yomi")) {
        yomi += given["yomi"].asString();
      }
    }

    if (kanji.empty() || yomi.empty()) {
      continue;
    }

    // push <normalize(yomi), kanji> into dictionary;
    string normal_yomi;
    UserDictionaryUtil::NormalizeReading(yomi, &normal_yomi);
    user_dictionary::UserDictionaryStorage::UserDictionary::Entry *entry =
        user_dictionary->add_entries();
    DCHECK(entry);
    entry->set_key(normal_yomi);
    entry->set_value(kanji);
    // "人名"
    entry->set_pos("\xE4\xBA\xBA\xE5\x90\x8D");
  }

  *last_timestamp = root["feed"]["updated"]["$t"].asString();
  return true;
}

}  // namespace sync
}  // namespace mozc