/*
   * Gets a specific tag tuple from the database as specified by the tags ID.
   */
  public RESTTagV1 getTagById(final int id) {
    try {
      if (entityCache.containsKeyValue(RESTTagV1.class, id)) {
        return entityCache.get(RESTTagV1.class, id);
      } else {
        /*
         * We need to expand the Categories collection in most cases so
         * expand it anyway
         */
        final ExpandDataTrunk expand = new ExpandDataTrunk();
        expand.setBranches(
            CollectionUtilities.toArrayList(
                new ExpandDataTrunk(new ExpandDataDetails("categories")),
                new ExpandDataTrunk(new ExpandDataDetails("properties"))));

        final String expandString = mapper.writeValueAsString(expand);
        // final String expandEncodedString = URLEncoder.encode(expandString, "UTF-8");

        final RESTTagV1 tag = client.getJSONTag(id, expandString);
        entityCache.add(tag);
        return tag;
      }
    } catch (Exception e) {
      log.error(ExceptionUtilities.getStackTrace(e));
    }
    return null;
  }
 /*
  * Gets a List of TopicSourceUrl tuples for a specified its TopicID
  * relationship through TopicToTopicSourceUrl.
  */
 public List<RESTTopicSourceUrlV1> getSourceUrlsByTopicId(final int topicId) {
   final RESTTopicV1 topic;
   if (entityCache.containsKeyValue(RESTTopicV1.class, topicId)) {
     topic = entityCache.get(RESTTopicV1.class, topicId);
   } else {
     topic = getTopicById(topicId, null);
   }
   return topic == null ? null : topic.getSourceUrls_OTM().getItems();
 }
 /*
  * Gets a specific User tuple from the database as specified by the tags ID.
  */
 public RESTUserV1 getUserById(final int id) {
   try {
     if (entityCache.containsKeyValue(RESTUserV1.class, id)) {
       return entityCache.get(RESTUserV1.class, id);
     } else {
       final RESTUserV1 user = client.getJSONUser(id, null);
       entityCache.add(user);
       return user;
     }
   } catch (Exception e) {
     log.error(ExceptionUtilities.getStackTrace(e));
   }
   return null;
 }
 /*
  * Gets a specific category tuple from the database as specified by the
  * categories ID.
  */
 public RESTCategoryV1 getCategoryById(final int id) {
   try {
     if (entityCache.containsKeyValue(RESTCategoryV1.class, id)) {
       return entityCache.get(RESTCategoryV1.class, id);
     } else {
       final RESTCategoryV1 category = client.getJSONCategory(id, null);
       entityCache.add(category);
       return category;
     }
   } catch (Exception e) {
     log.debug(e.getMessage());
     e.printStackTrace();
   }
   return null;
 }
  /*
   * Gets a specific tag tuple from the database as specified by the tags ID.
   */
  public RESTTopicV1 getTopicById(
      final int id, final Integer rev, final boolean expandTranslations) {
    try {
      final RESTTopicV1 topic;
      if (entityCache.containsKeyValue(RESTTopicV1.class, id, rev)) {
        topic = entityCache.get(RESTTopicV1.class, id, rev);
      } else {
        /* We need to expand the all the items in the topic collection */
        final ExpandDataTrunk expand = new ExpandDataTrunk();
        final ExpandDataTrunk expandTags = new ExpandDataTrunk(new ExpandDataDetails("tags"));
        final ExpandDataTrunk expandTopicTranslations =
            new ExpandDataTrunk(new ExpandDataDetails(RESTTopicV1.TRANSLATEDTOPICS_NAME));
        expandTags.setBranches(
            CollectionUtilities.toArrayList(
                new ExpandDataTrunk(new ExpandDataDetails("categories")),
                new ExpandDataTrunk(new ExpandDataDetails("properties"))));
        expand.setBranches(
            CollectionUtilities.toArrayList(
                expandTags,
                new ExpandDataTrunk(new ExpandDataDetails("sourceUrls")),
                new ExpandDataTrunk(new ExpandDataDetails("properties")),
                new ExpandDataTrunk(new ExpandDataDetails("outgoingRelationships")),
                new ExpandDataTrunk(new ExpandDataDetails("incomingRelationships"))));

        if (expandTranslations) {
          expand.getBranches().add(expandTopicTranslations);
        }

        final String expandString = mapper.writeValueAsString(expand);
        // final String expandEncodedString = URLEncoder.encode(expandString, "UTF-8");
        if (rev == null) {
          topic = client.getJSONTopic(id, expandString);
          entityCache.add(topic);
        } else {
          topic = client.getJSONTopicRevision(id, rev, expandString);
          entityCache.add(topic, true);
        }
      }
      return topic;
    } catch (Exception e) {
      log.error(ExceptionUtilities.getStackTrace(e));
    }
    return null;
  }
  /*
   * Gets a collection of translated topics based on the list of topic ids
   * passed.
   */
  public RESTTranslatedTopicCollectionV1 getTranslatedTopicsByZanataIds(
      final List<Integer> ids, final String locale) {
    if (ids.isEmpty()) return null;

    try {
      final RESTTranslatedTopicCollectionV1 topics = new RESTTranslatedTopicCollectionV1();
      final StringBuffer urlVars = new StringBuffer("query;latestTranslations=true;zanataIds=");
      final String encodedComma = URLEncoder.encode(",", "UTF-8");

      for (Integer id : ids) {
        if (!entityCache.containsKeyValue(RESTTranslatedTopicV1.class, id)) {
          urlVars.append(id + encodedComma);
        } else {
          topics.addItem(entityCache.get(RESTTranslatedTopicV1.class, id));
        }
      }

      String query = urlVars.toString();

      if (query.length() != "query;latestTranslations=true;zanataIds=".length()) {
        query = query.substring(0, query.length() - encodedComma.length());

        /* Add the locale to the query if one was passed */
        if (locale != null && !locale.isEmpty()) query += ";locale1=" + locale + "1";

        PathSegment path = new PathSegmentImpl(query, false);

        /*
         * We need to expand the all the items in the translatedtopic
         * collection
         */
        final ExpandDataTrunk expand = new ExpandDataTrunk();

        final ExpandDataTrunk translatedTopicsExpand =
            new ExpandDataTrunk(new ExpandDataDetails("translatedtopics"));
        final ExpandDataTrunk topicExpandTranslatedTopics =
            new ExpandDataTrunk(new ExpandDataDetails(RESTTopicV1.TRANSLATEDTOPICS_NAME));
        final ExpandDataTrunk tags = new ExpandDataTrunk(new ExpandDataDetails("tags"));
        final ExpandDataTrunk properties =
            new ExpandDataTrunk(new ExpandDataDetails(RESTBaseTopicV1.PROPERTIES_NAME));
        final ExpandDataTrunk categories = new ExpandDataTrunk(new ExpandDataDetails("categories"));
        final ExpandDataTrunk parentTags = new ExpandDataTrunk(new ExpandDataDetails("parenttags"));
        final ExpandDataTrunk outgoingRelationships =
            new ExpandDataTrunk(
                new ExpandDataDetails(RESTTranslatedTopicV1.ALL_LATEST_OUTGOING_NAME));
        final ExpandDataTrunk topicsExpand =
            new ExpandDataTrunk(new ExpandDataDetails(RESTTranslatedTopicV1.TOPIC_NAME));

        /* We need to expand the categories collection on the topic tags */
        tags.setBranches(CollectionUtilities.toArrayList(categories, parentTags, properties));
        outgoingRelationships.setBranches(
            CollectionUtilities.toArrayList(tags, properties, topicsExpand));

        topicsExpand.setBranches(CollectionUtilities.toArrayList(topicExpandTranslatedTopics));

        translatedTopicsExpand.setBranches(
            CollectionUtilities.toArrayList(tags, outgoingRelationships, properties, topicsExpand));

        expand.setBranches(CollectionUtilities.toArrayList(translatedTopicsExpand));

        final String expandString = mapper.writeValueAsString(expand);
        // final String expandEncodedString = URLEncoder.encode(expandString, "UTF-8");

        final RESTTranslatedTopicCollectionV1 downloadedTopics =
            client.getJSONTranslatedTopicsWithQuery(path, expandString);
        entityCache.add(downloadedTopics);

        /* Transfer the downloaded data to the current topic list */
        if (downloadedTopics != null && downloadedTopics.getItems() != null) {
          for (final RESTTranslatedTopicV1 item : downloadedTopics.getItems()) {
            entityCache.add(item, ComponentTranslatedTopicV1.returnZanataId(item), false);
            topics.addItem(item);
          }
        }
      }

      return topics;
    } catch (Exception e) {
      log.error(ExceptionUtilities.getStackTrace(e));
    }
    return null;
  }
  /*
   * Gets a collection of topics based on the list of ids passed.
   */
  public RESTTopicCollectionV1 getTopicsByIds(
      final List<Integer> ids, final boolean expandTranslations) {
    if (ids.isEmpty()) return null;

    try {
      final RESTTopicCollectionV1 topics = new RESTTopicCollectionV1();
      final StringBuffer urlVars = new StringBuffer("query;topicIds=");
      // final String encodedComma = URLEncoder.encode(",", "UTF-8");

      for (Integer id : ids) {
        if (!entityCache.containsKeyValue(RESTTopicV1.class, id)) {
          urlVars.append(id + ",");
        } else {
          topics.addItem(entityCache.get(RESTTopicV1.class, id));
        }
      }

      String query = urlVars.toString();

      /* Get the missing topics from the REST interface */
      if (query.length() != "query;topicIds=".length()) {
        query = query.substring(0, query.length() - 1);

        PathSegment path = new PathSegmentImpl(query, false);

        final ExpandDataDetails expandDetails = new ExpandDataDetails("topics");
        expandDetails.setShowSize(true);
        expandDetails.setEnd(0);
        final ExpandDataTrunk topicsExpandSize = new ExpandDataTrunk(expandDetails);
        final ExpandDataTrunk expandSize = new ExpandDataTrunk();

        expandSize.setBranches(CollectionUtilities.toArrayList(topicsExpandSize));

        final String expandDetailsString = mapper.writeValueAsString(expandSize);
        final RESTTopicCollectionV1 downloadedTopicsSize =
            client.getJSONTopicsWithQuery(path, expandDetailsString);

        /* Load the topics in groups to save memory when unmarshalling */
        final int numTopics = downloadedTopicsSize.getSize();
        for (int i = 0; i <= numTopics; i = i + 100) {
          /* We need to expand the all the items in the topic collection */
          final ExpandDataTrunk expand = new ExpandDataTrunk();
          final ExpandDataDetails expandTopicDetails = new ExpandDataDetails("topics");
          expandTopicDetails.setStart(i);
          expandTopicDetails.setEnd(i + 100);
          final ExpandDataTrunk topicsExpand = new ExpandDataTrunk(expandTopicDetails);
          final ExpandDataTrunk tags = new ExpandDataTrunk(new ExpandDataDetails("tags"));
          final ExpandDataTrunk properties =
              new ExpandDataTrunk(new ExpandDataDetails(RESTBaseTopicV1.PROPERTIES_NAME));
          final ExpandDataTrunk categories =
              new ExpandDataTrunk(new ExpandDataDetails("categories"));
          final ExpandDataTrunk parentTags =
              new ExpandDataTrunk(new ExpandDataDetails("parenttags"));
          final ExpandDataTrunk outgoingRelationships =
              new ExpandDataTrunk(new ExpandDataDetails("outgoingRelationships"));
          final ExpandDataTrunk expandTranslatedTopics =
              new ExpandDataTrunk(new ExpandDataDetails(RESTTopicV1.TRANSLATEDTOPICS_NAME));

          /* We need to expand the categories collection on the topic tags */
          tags.setBranches(CollectionUtilities.toArrayList(categories, parentTags, properties));
          if (expandTranslations) {
            outgoingRelationships.setBranches(
                CollectionUtilities.toArrayList(tags, properties, expandTranslatedTopics));
            topicsExpand.setBranches(
                CollectionUtilities.toArrayList(
                    tags,
                    outgoingRelationships,
                    properties,
                    new ExpandDataTrunk(new ExpandDataDetails("sourceUrls")),
                    expandTranslatedTopics));
          } else {
            outgoingRelationships.setBranches(CollectionUtilities.toArrayList(tags, properties));
            topicsExpand.setBranches(
                CollectionUtilities.toArrayList(
                    tags,
                    outgoingRelationships,
                    properties,
                    new ExpandDataTrunk(new ExpandDataDetails("sourceUrls"))));
          }

          expand.setBranches(CollectionUtilities.toArrayList(topicsExpand));

          final String expandString = mapper.writeValueAsString(expand);
          // final String expandEncodedString = URLEncoder.encode(expandString, "UTF-8");

          final RESTTopicCollectionV1 downloadedTopics =
              client.getJSONTopicsWithQuery(path, expandString);
          entityCache.add(downloadedTopics);

          /* Transfer the downloaded data to the current topic list */
          if (downloadedTopics != null && downloadedTopics.getItems() != null) {
            for (final RESTTopicV1 item : downloadedTopics.getItems()) {
              topics.addItem(item);
            }
          }
        }
      }

      return topics;
    } catch (Exception e) {
      log.error(ExceptionUtilities.getStackTrace(e));
    }
    return null;
  }