com.appspot.socialinquirer.server.service.impl.StackExchangeServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.appspot.socialinquirer.server.service.impl.StackExchangeServiceImpl.java

Source

/*
 * Copyright 2012 Nabeel Mukhtar 
 * 
 * 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. 
 * 
 */
package com.appspot.socialinquirer.server.service.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.util.Version;

import com.appspot.socialinquirer.server.constant.ApplicationConstants;
import com.appspot.socialinquirer.server.service.StackExchangeService;
import com.appspot.socialinquirer.shared.dto.Answer;
import com.appspot.socialinquirer.shared.dto.Message;
import com.appspot.socialinquirer.shared.dto.Question;
import com.appspot.socialinquirer.shared.dto.Tag;
import com.appspot.socialinquirer.shared.dto.User;
import com.google.code.stackexchange.client.provider.CustomApiProvider;
import com.google.code.stackexchange.client.query.AnswerApiQuery;
import com.google.code.stackexchange.client.query.QuestionApiQuery;
import com.google.code.stackexchange.client.query.StackExchangeApiQueryFactory;
import com.google.code.stackexchange.client.query.TagApiQuery;
import com.google.code.stackexchange.client.query.UserApiQuery;
import com.google.code.stackexchange.schema.FilterOption;
import com.google.code.stackexchange.schema.Site;
import com.googleapis.ajax.schema.WebResult;
import com.googleapis.ajax.services.GoogleSearchQueryFactory;
import com.googleapis.ajax.services.WebSearchQuery;

/**
 * The Class StackExchangeServiceImpl.
 */
public class StackExchangeServiceImpl extends BaseService implements StackExchangeService {

    /** The STAC k_ exchang e_ ap i_ factory. */
    StackExchangeApiQueryFactory STACK_EXCHANGE_API_FACTORY = StackExchangeApiQueryFactory
            .newInstance(ApplicationConstants.STACK_EXCHANGE_CONSUMER_KEY);

    /** The Constant STACK_EXCHANGE_SITES. */
    private static final List<Site> STACK_EXCHANGE_SITES = new ArrayList<Site>();

    {
        STACK_EXCHANGE_SITES.addAll(STACK_EXCHANGE_API_FACTORY.newStackAuthApiQuery().list());
    }

    /** The access token. */
    private String accessToken;

    /**
     * Instantiates a new stack exchange service impl.
     *
     * @param accessToken the access token
     */
    public StackExchangeServiceImpl(String accessToken) {
        super("stack-exchange-service");
        this.accessToken = accessToken;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.appspot.researchcraft.server.service.NoteService#performMaintenance()
     */
    @Override
    public void performMaintenance() {
        // TODO Auto-generated method stub
        // delete templates older than 30 days if unused.
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getQuestions(java.util.List)
     */
    @Override
    public List<Question> getQuestions(List<Long> questionIds) {
        List<Question> retValue = new ArrayList<Question>();
        for (Iterator<Long> iterator = questionIds.iterator(); iterator.hasNext();) {
            Question question = (Question) memcache.get("question-" + iterator.next());
            if (question != null) {
                retValue.add(question);
                iterator.remove();
            }
        }
        if (!questionIds.isEmpty()) {
            QuestionApiQuery query = createQuestionApiQuery();
            query.withFilter("_ba").withQuestionIds(questionIds);
            List<com.google.code.stackexchange.schema.Question> list = query.list();
            for (com.google.code.stackexchange.schema.Question question : list) {
                retValue.add(mapQuestion(question));
            }
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getRelatedQuestions(java.util.List)
     */
    @Override
    public List<Question> getRelatedQuestions(List<Long> questionIds) {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withQuestionIds(questionIds);
        // TODO-NM: list related questions.
        List<com.google.code.stackexchange.schema.Question> list = query.list();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUnansweredQuestions()
     */
    @Override
    public List<Question> getUnansweredQuestions() {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        // TODO-NM: list related questions.
        List<com.google.code.stackexchange.schema.Question> list = query.listUnansweredQuestions();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#searchQuestions(java.lang.String)
     */
    @Override
    public List<Question> searchQuestions(String query) {
        GoogleSearchQueryFactory GOOGLE_API_FACTORY = GoogleSearchQueryFactory
                .newInstance(ApplicationConstants.GOOGLE_API_KEY);

        WebSearchQuery webQuery = GOOGLE_API_FACTORY.newWebSearchQuery();
        webQuery.setReferrer(ApplicationConstants.GOOGLE_API_REFERER);
        webQuery.withCustomeSearchEngineId(ApplicationConstants.GOOGLE_API_CSE);
        List<WebResult> webResponse = webQuery.withQuery(query).list();
        List<String> searchUrls = new ArrayList<String>();
        for (int i = 0; i < webResponse.size(); i++) {
            WebResult webResult = webResponse.get(i);
            searchUrls.add(webResult.getUnescapedUrl());
        }

        return getStackExchangeQuestions(searchUrls);
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#searchQuestions(java.util.List)
     */
    @Override
    public List<Question> searchQuestions(List<String> tags) {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withTags(tags);
        List<com.google.code.stackexchange.schema.Question> list = query.list();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getTags(java.util.List)
     */
    @Override
    public List<Tag> getTags(List<String> tags) {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        // TODO-NM: implement this method
        //      query.withTags(tags);
        List<com.google.code.stackexchange.schema.Tag> list = query.list();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getRelatedTags(java.util.List)
     */
    @Override
    public List<Tag> getRelatedTags(List<String> tags) {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        // TODO-NM: implement this method
        //      query.withTags(tags);
        List<com.google.code.stackexchange.schema.Tag> list = query.list();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getTopAskers(java.util.List)
     */
    @Override
    public List<User> getTopAskers(List<String> tags) {
        UserApiQuery query = createUserApiQuery();
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getTopAnswerers(java.util.List)
     */
    @Override
    public List<User> getTopAnswerers(List<String> tags) {
        UserApiQuery query = createUserApiQuery();
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getCurrentUser()
     */
    @Override
    public User getCurrentUser() {
        logger.log(Level.WARNING, "Access Token2:" + accessToken);
        UserApiQuery query = createUserApiQuery();
        return mapUser(query.currentUser());
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUsers(java.util.List)
     */
    @Override
    public List<User> getUsers(List<Long> userIds) {
        List<User> retValue = new ArrayList<User>();
        UserApiQuery query = createUserApiQuery();
        List<com.google.code.stackexchange.schema.User> list = query.list();
        for (com.google.code.stackexchange.schema.User user : list) {
            retValue.add(mapUser(user));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserAnswers(java.util.List)
     */
    @Override
    public List<Answer> getUserAnswers(List<Long> userIds) {
        List<Answer> retValue = new ArrayList<Answer>();
        AnswerApiQuery query = createAnswerApiQuery();
        query.withUserIds(userIds);
        List<com.google.code.stackexchange.schema.Answer> list = query.list();
        for (com.google.code.stackexchange.schema.Answer answer : list) {
            retValue.add(mapAnswer(answer));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserQuestions(java.util.List)
     */
    @Override
    public List<Question> getUserQuestions(List<Long> userIds) {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withUserIds(userIds);
        List<com.google.code.stackexchange.schema.Question> list = query.listQuestionsByUser();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserFavoriteQuestions(java.util.List)
     */
    @Override
    public List<Question> getUserFavoriteQuestions(List<Long> userIds) {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withUserIds(userIds);
        List<com.google.code.stackexchange.schema.Question> list = query.listFavoriteQuestions();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserUnansweredQuestions(java.util.List)
     */
    @Override
    public List<Question> getUserUnansweredQuestions(List<Long> userIds) {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withUserIds(userIds);
        // TODO-NM: discriminate
        List<com.google.code.stackexchange.schema.Question> list = query.listQuestionsByUser();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getActiveTags(java.util.List)
     */
    @Override
    public List<Tag> getActiveTags(List<Long> userIds) {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        query.withUserIds(userIds);
        List<com.google.code.stackexchange.schema.Tag> list = query.listByUser();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getAnswerTags(java.util.List)
     */
    @Override
    public List<Tag> getAnswerTags(List<Long> userIds) {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        query.withUserIds(userIds);
        // TODO-NM: discriminate
        List<com.google.code.stackexchange.schema.Tag> list = query.listByUser();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getQuestionTags(java.util.List)
     */
    @Override
    public List<Tag> getQuestionTags(List<Long> userIds) {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        query.withUserIds(userIds);
        // TODO-NM: discriminate
        List<com.google.code.stackexchange.schema.Tag> list = query.listByUser();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserAnswers()
     */
    @Override
    public List<Answer> getUserAnswers() {
        List<Answer> retValue = new ArrayList<Answer>();
        AnswerApiQuery query = createAnswerApiQuery();
        query.withMe();
        List<com.google.code.stackexchange.schema.Answer> list = query.list();
        for (com.google.code.stackexchange.schema.Answer answer : list) {
            retValue.add(mapAnswer(answer));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserQuestions()
     */
    @Override
    public List<Question> getUserQuestions() {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withMe();
        List<com.google.code.stackexchange.schema.Question> list = query.listQuestionsByUser();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserFavoriteQuestions()
     */
    @Override
    public List<Question> getUserFavoriteQuestions() {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withMe();
        List<com.google.code.stackexchange.schema.Question> list = query.listFavoriteQuestions();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserUnansweredQuestions()
     */
    @Override
    public List<Question> getUserUnansweredQuestions() {
        List<Question> retValue = new ArrayList<Question>();
        QuestionApiQuery query = createQuestionApiQuery();
        query.withMe();
        // TODO-NM: discriminate
        List<com.google.code.stackexchange.schema.Question> list = query.listQuestionsByUser();
        for (com.google.code.stackexchange.schema.Question question : list) {
            retValue.add(mapQuestion(question));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getActiveTags()
     */
    @Override
    public List<Tag> getActiveTags() {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        query.withMe();
        List<com.google.code.stackexchange.schema.Tag> list = query.listByUser();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getAnswerTags()
     */
    @Override
    public List<Tag> getAnswerTags() {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        query.withMe();
        // TODO-NM: discriminate
        List<com.google.code.stackexchange.schema.Tag> list = query.listByUser();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getQuestionTags()
     */
    @Override
    public List<Tag> getQuestionTags() {
        List<Tag> retValue = new ArrayList<Tag>();
        TagApiQuery query = createTagApiQuery();
        query.withMe();
        // TODO-NM: discriminate
        List<com.google.code.stackexchange.schema.Tag> list = query.listByUser();
        for (com.google.code.stackexchange.schema.Tag tag : list) {
            retValue.add(mapTag(tag));
        }
        return retValue;
    }

    /* (non-Javadoc)
     * @see com.appspot.socialinquirer.server.service.StackExchangeService#getUserMessages()
     */
    @Override
    public List<Message> getUserMessages() {
        // TODO Auto-generated method stub
        return new ArrayList<Message>();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.appspot.researchcraft.server.service.AnalysisService#showAnswer(java.lang.String)
     */
    @Override
    public Question showAnswer(String title, String text, List<String> tags) {
        try {
            GoogleSearchQueryFactory GOOGLE_API_FACTORY = GoogleSearchQueryFactory
                    .newInstance(ApplicationConstants.GOOGLE_API_KEY);

            WebSearchQuery webQuery = GOOGLE_API_FACTORY.newWebSearchQuery();
            webQuery.setReferrer(ApplicationConstants.GOOGLE_API_REFERER);
            webQuery.withCustomeSearchEngineId(ApplicationConstants.GOOGLE_API_CSE);
            List<WebResult> webResponse = webQuery.withQuery(title).list();
            List<String> searchUrls = new ArrayList<String>();
            for (int i = 0; i < webResponse.size(); i++) {
                WebResult webResult = webResponse.get(i);
                searchUrls.add(webResult.getUnescapedUrl());
            }

            List<Question> questions = getStackExchangeQuestions(searchUrls);
            //         questions.addAll(getYahooAnswersQuestions(searchUrls));

            Question selectQuestion = selectQuestion(questions, text, searchUrls, tags);
            return selectQuestion;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "An error occured while checking answer.", e);
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.appspot.researchcraft.server.service.AnalysisService#showRelatedQuestions(java.lang.String,
     *      java.lang.String, java.util.List)
     */
    @Override
    public List<Question> showRelatedQuestions(String title, String text, List<String> tags) {
        List<Question> blogs = new ArrayList<Question>();
        try {
            GoogleSearchQueryFactory GOOGLE_API_FACTORY = GoogleSearchQueryFactory
                    .newInstance(ApplicationConstants.GOOGLE_API_KEY);

            WebSearchQuery webQuery = GOOGLE_API_FACTORY.newWebSearchQuery();
            webQuery.setReferrer(ApplicationConstants.GOOGLE_API_REFERER);
            webQuery.withCustomeSearchEngineId(ApplicationConstants.GOOGLE_API_CSE);
            List<WebResult> webResponse = webQuery.withQuery(title).list();
            List<String> searchUrls = new ArrayList<String>();
            for (int i = 0; i < webResponse.size(); i++) {
                WebResult webResult = webResponse.get(i);
                searchUrls.add(webResult.getUnescapedUrl());
            }

            //         blogs.addAll(getYahooAnswersQuestions(searchUrls));
            blogs.addAll(getStackExchangeQuestions(searchUrls));
        } catch (Exception e) {
            logger.log(Level.SEVERE, "An error occured while checking related questions.", e);
        }
        return blogs;
    }

    //   /**
    //    * Gets the yahoo answers questions.
    //    * 
    //    * @param searchUrls
    //    *            the search urls
    //    * 
    //    * @return the yahoo answers questions
    //    */
    //   protected List<Question> getYahooAnswersQuestions(
    //         List<String> searchUrls) {
    //      List<Question> questions = new ArrayList<Question>();
    //      com.appspot.socialinquirer.server.model.Version version = getCurrentVersion();
    //      if (version.getYqlToken() != null && version.getYqlSecret() != null) {
    //         YqlClient client = null;
    //         try {
    //            List<String> yahooQuestions = new ArrayList<String>();
    //            for (int i = 0; i < searchUrls.size(); i++) {
    //               Matcher matcher = ApplicationConstants.YAHOO_ANSWERS_PATTERN
    //                     .matcher(searchUrls.get(i));
    //               if (matcher.find() && matcher.groupCount() == 2) {
    //                  yahooQuestions.add(matcher.group(2));
    //               }
    //            }
    //
    //            if (!yahooQuestions.isEmpty()) {
    //               final YqlClientFactory factory = YqlClientFactory.newInstance(
    //                     ApplicationConstants.YAHOO_CONSUMER_KEY,
    //                     ApplicationConstants.YAHOO_CONSUMER_SECRET,
    //                     version.getYqlToken().getValue(),
    //                     version.getYqlSecret().getValue());
    //               client = factory.createYqlClient();
    //               client.getApiConsumer().setOauthSessionHandle(version.getYqlSessionHandle().getValue());
    //               List<com.google.code.yahooanswers.schema.Question> results = client
    //                     .query(
    //                           new YqlClient.TypeToken<List<com.google.code.yahooanswers.schema.Question>>(
    //                                 "Question") {
    //                           }, getYahooAnswersQuesry(yahooQuestions));
    //               for (com.google.code.yahooanswers.schema.Question question : results) {
    //                  questions.add(mapQuestion(question));
    //               }
    //
    //            }
    //         } catch (YqlException e) {
    //            if (e.getStatusCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
    //               try {
    //                  client.refreshAuthentication();
    //                  version.setYqlToken(new Text(client.getApiConsumer().getAccessToken()));
    //                  version.setYqlSecret(new Text(client.getApiConsumer().getAccessTokenSecret()));
    //                  version.setYqlSessionHandle(new Text(client.getApiConsumer().getOauthSessionHandle()));
    //                  saveVersion(version);
    //               } catch (Exception e2) {
    //                  logger
    //                  .log(Level.SEVERE, "An error occurred while refreshing YQL token.",
    //                        e2);
    //               }
    //            } else {
    //               logger
    //                  .log(Level.SEVERE, "An error occurred while accessing YQL",
    //                        e);
    //            }
    //         } catch (Exception e) {
    //            logger
    //                  .log(Level.SEVERE, "An error occurred while accessing YQL",
    //                        e);
    //         }
    //      }
    //      return questions;
    //   }

    //   /**
    //    * Map question.
    //    * 
    //    * @param question
    //    *            the question
    //    * 
    //    * @return the com.appspot.researchcraft.shared.dto. question
    //    */
    //   private Question mapQuestion(
    //         com.google.code.yahooanswers.schema.Question question) {
    //      Question q = new Question();
    //      q.setTitle(question.getSubject());
    //      q.setContent(question.getContent());
    //      q.setAuthor(question.getUserNick());
    //      q.setPublishedDate(new Date(Long.valueOf(question.getTimestamp())));
    //      q.setUrl("http://answers.yahoo.com/question/index?qid="
    //            + question.getId());
    //      if (question.getAnswers() != null) {
    //         for (com.google.code.yahooanswers.schema.Answer answer : question
    //               .getAnswers().getAnswer()) {
    //            Answer a = new Answer();
    //            a.setTitle(question.getSubject());
    //            a.setContent(answer.getContent());
    //            a.setAuthor(answer.getUserNick());
    //            a
    //                  .setPublishedDate(new Date(Long.valueOf(answer
    //                        .getTimestamp())));
    //            q.getAnswers().add(a);
    //         }
    //      }
    //      return q;
    //   }

    //   /**
    //    * Gets the yahoo answers quesry.
    //    * 
    //    * @param yahooQuestions
    //    *            the yahoo questions
    //    * 
    //    * @return the yahoo answers quesry
    //    */
    //   private String getYahooAnswersQuesry(List<String> yahooQuestions) {
    //      StringBuilder builder = new StringBuilder();
    //      for (int i = 0; i < yahooQuestions.size(); i++) {
    //         builder.append("'" + yahooQuestions.get(i) + "'");
    //         if (i != yahooQuestions.size() - 1) {
    //            builder.append(",");
    //         }
    //      }
    //      return MessageFormat.format(ApplicationConstants.YAHOO_ANSWERS_YQL,
    //            builder.toString());
    //   }

    /**
    * Select question.
    *
    * @param questions the questions
    * @param content the content
    * @param searchUrls the search urls
    * @param tags the tags
    * @return the question
    */
    protected Question selectQuestion(List<Question> questions, String content, List<String> searchUrls,
            List<String> tags) {
        double similarity = 0;
        Question selectedQuestion = null;
        for (Question question : questions) {
            double tempSim = getSimilarity(content, question, searchUrls);
            if (tempSim > similarity && matchWithKeywords(tags, content)) {
                similarity = tempSim;
                selectedQuestion = question;
            }
        }
        return selectedQuestion;
    }

    /**
     * Match with keywords.
     *
     * @param keywords the keywords
     * @param userText the user text
     * @return true, if successful
     */
    public boolean matchWithKeywords(List<String> keywords, String userText) {
        MemoryIndex index = new MemoryIndex();
        index.addField("text", userText, createEnglishAnalyzer());
        QueryParser parser = new QueryParser("text", createEnglishAnalyzer());
        BooleanQuery query = new BooleanQuery();
        for (String keyword : keywords) {
            try {
                query.add(parser.parse(keyword), BooleanClause.Occur.SHOULD);
            } catch (ParseException e) {
            }
        }

        float score = index.search(query);

        return score > 0.0f;
    }

    /**
     * Gets the question id.
     *
     * @param url the url
     * @param site the site
     * @return the question id
     */
    protected long getQuestionId(String url, Site site) {
        Pattern sitePattern = Pattern.compile(
                MessageFormat.format(ApplicationConstants.STACK_EXCHANGE_API_URL_PATTERN, site.getSiteUrl()));
        Matcher matcher = sitePattern.matcher(url);
        if (matcher.find()) {
            return Long.valueOf(matcher.group(1));
        }

        // logger.warning("Could not extract question id from url:" + url);
        return 0L;
    }

    /**
     * Gets the similarity.
     *
     * @param content the content
     * @param question the question
     * @param searchUrls the search urls
     * @return the similarity
     */
    protected double getSimilarity(String content, Question question, List<String> searchUrls) {
        // currently just rely on google's algo.
        for (int i = 0; i < searchUrls.size(); i++) {
            if (searchUrls.get(i).startsWith(question.getUrl())) {
                return (searchUrls.size() - i);
            }
        }
        return 0;
    }

    /**
     * Gets the stack exchange questions.
     *
     * @param searchUrls the search urls
     * @return the stack exchange questions
     */
    protected List<Question> getStackExchangeQuestions(List<String> searchUrls) {
        Map<Site, List<Long>> questionIdsMap = new HashMap<Site, List<Long>>();
        for (int i = 0; i < searchUrls.size(); i++) {
            Site site = getQuestionSite(searchUrls.get(i));
            if (site != null) {
                List<Long> ids = questionIdsMap.get(site);
                if (ids == null) {
                    ids = new ArrayList<Long>();
                    questionIdsMap.put(site, ids);
                }
                long questionId = getQuestionId(searchUrls.get(i), site);
                ids.add(questionId);
            }
        }

        List<Question> questions = new ArrayList<Question>();

        for (Site site : questionIdsMap.keySet()) {
            List<Long> ids = questionIdsMap.get(site);
            QuestionApiQuery questionQuery = STACK_EXCHANGE_API_FACTORY.newQuestionApiQuery();
            questionQuery.setApiProvider(new CustomApiProvider(site.getApiEndpoint()));
            // questionQuery.withPaging(new Paging(1, 5));
            questionQuery.withFetchOptions(EnumSet.of(FilterOption.INCLUDE_ANSWERS, FilterOption.INCLUDE_BODY))
                    .withQuestionIds(ids);
            List<com.google.code.stackexchange.schema.Question> siteQuestions = questionQuery.list();
            for (com.google.code.stackexchange.schema.Question question : siteQuestions) {
                Question q = mapQuestion(question);
                q.setUrl(site.getSiteUrl() + "/questions/" + question.getQuestionId());
                questions.add(q);
            }
        }
        return questions;
    }

    /**
     * Gets the question site.
     *
     * @param url the url
     * @return the question site
     */
    protected Site getQuestionSite(String url) {
        for (Site site : STACK_EXCHANGE_SITES) {
            if (url.startsWith(site.getSiteUrl())) {
                return site;
            }
        }
        return null;
    }

    /**
     * Map question.
     *
     * @param question the question
     * @return the question
     */
    private Question mapQuestion(com.google.code.stackexchange.schema.Question question) {
        Question q = new Question();
        q.setKey(String.valueOf(question.getQuestionId()));
        q.setTitle(question.getTitle());
        q.setContent(question.getBody());
        if (question.getOwner() != null) {
            q.setAuthor(question.getOwner().getDisplayName() + ":" + question.getOwner().getUserId());
        }
        q.setPublishedDate(question.getCreationDate());
        for (com.google.code.stackexchange.schema.Answer answer : question.getAnswers()) {
            Answer a = new Answer();
            a.setTitle(answer.getTitle());
            a.setContent(answer.getBody());
            a.setAccepted(answer.isAccepted());
            if (answer.getOwner() != null) {
                a.setAuthor(answer.getOwner().getDisplayName() + ":" + answer.getOwner().getUserId());
            }
            a.setPublishedDate(answer.getCreationDate());
            q.getAnswers().add(a);
        }
        return q;
    }

    /**
     * Creates the english analyzer.
     *
     * @return the analyzer
     */
    private static Analyzer createEnglishAnalyzer() {
        return new StandardAnalyzer(Version.LUCENE_CURRENT);
        // return new StandardAnalyzer(Version.LUCENE_CURRENT) {
        // public TokenStream tokenStream(String fieldName, Reader reader) {
        // TokenStream result = super.tokenStream(fieldName, reader);
        // result = new SnowballFilter(result, "English");
        // return result;
        // }
        // };
    }

    /**
     * Map tag.
     *
     * @param tag the tag
     * @return the tag
     */
    private Tag mapTag(com.google.code.stackexchange.schema.Tag tag) {
        Tag retValue = new Tag();
        retValue.setTag(tag.getName());
        retValue.setFreqency((int) tag.getCount());
        return retValue;
    }

    /**
     * Map answer.
     *
     * @param answer the answer
     * @return the answer
     */
    private Answer mapAnswer(com.google.code.stackexchange.schema.Answer answer) {
        Answer a = new Answer();
        a.setTitle(answer.getTitle());
        a.setContent(answer.getBody());
        if (answer.getOwner() != null) {
            a.setAuthor(answer.getOwner().getDisplayName());
        }
        a.setAccepted(answer.isAccepted());
        a.setPublishedDate(answer.getCreationDate());
        return a;
    }

    /**
     * Map user.
     *
     * @param user the user
     * @return the user
     */
    private User mapUser(com.google.code.stackexchange.schema.User user) {
        User retValue = new User();
        retValue.setDisplayName(user.getDisplayName());
        retValue.setStackExchangeId(String.valueOf(user.getUserId()));
        retValue.setReputation((int) user.getReputation());
        retValue.setAge((int) user.getAge());
        retValue.setAcceptRate(user.getAcceptRate());
        return retValue;
    }

    /**
     * Creates the question api query.
     *
     * @return the question api query
     */
    private QuestionApiQuery createQuestionApiQuery() {
        final QuestionApiQuery query = STACK_EXCHANGE_API_FACTORY.newQuestionApiQuery();
        if (accessToken != null) {
            query.withAccessToken(accessToken);
        }
        return query;
    }

    /**
     * Creates the user api query.
     *
     * @return the user api query
     */
    private UserApiQuery createUserApiQuery() {
        final UserApiQuery query = STACK_EXCHANGE_API_FACTORY.newUserApiQuery();
        if (accessToken != null) {
            query.withAccessToken(accessToken);
        }
        return query;
    }

    /**
     * Creates the tag api query.
     *
     * @return the tag api query
     */
    private TagApiQuery createTagApiQuery() {
        final TagApiQuery query = STACK_EXCHANGE_API_FACTORY.newTagApiQuery();
        if (accessToken != null) {
            query.withAccessToken(accessToken);
        }
        return query;
    }

    /**
     * Creates the answer api query.
     *
     * @return the answer api query
     */
    private AnswerApiQuery createAnswerApiQuery() {
        final AnswerApiQuery query = STACK_EXCHANGE_API_FACTORY.newAnswerApiQuery();
        if (accessToken != null) {
            query.withAccessToken(accessToken);
        }
        return query;
    }

}