com.hunch.api.HunchNextQuestion.java Source code

Java tutorial

Introduction

Here is the source code for com.hunch.api.HunchNextQuestion.java

Source

/*
 * Copyright 2009, 2010 Tyler Levine
 * 
 * This file is part of Hunch for Android.
 *
 * Hunch for Android is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Hunch for Android is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Hunch for Android.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.hunch.api;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.hunch.Const;

/**
 * This class is a representation of the JSON object returned by the
 * nextQuestion call of the HunchAPI.
 * 
 * @author Tyler Levine
 * @since Dec 8, 2009
 * 
 */
public class HunchNextQuestion extends HunchObject {

    private static Builder b;

    public interface Callback {
        public void callComplete(HunchNextQuestion h);
    }

    /*
     * The various varieties of this object returned by the API.
     * 
     * Different varieties have different capabilities. Runtime checking
     * of variety should help reduce possible NPE's
     */
    public enum Variety {
        DEFAULT, RESULTS
    }

    static class Builder extends HunchObject.Builder {

        private JSONObject val;
        private HunchQuestion buildNextQuestion;
        private String buildPrevQAState, buildRankedResultResponses;
        private IHunchTopic buildTopic;

        private Builder() {
        }

        @Override
        Builder init(JSONObject jsonVal) {
            val = jsonVal;
            return this;
        }

        Builder setNextQuestion(HunchQuestion nextQuestion) {
            buildNextQuestion = nextQuestion;
            return this;
        }

        Builder setPrevQAState(String prevQAState) {
            buildPrevQAState = prevQAState;
            return this;
        }

        Builder setRankedResultResponses(String rankedResultResponses) {
            buildRankedResultResponses = rankedResultResponses;
            return this;
        }

        Builder setTopic(IHunchTopic topic) {
            buildTopic = topic;
            return this;
        }

        /*
         * (non-Javadoc)
         * 
         * @see com.hunch.api.HunchObject.Builder#build()
         */
        @Override
        HunchNextQuestion build() {
            if (val == null) {
                throw new IllegalStateException(
                        "Not all required fields set before building HunchNextQuestion! (JSON value null)");
            } else if (buildNextQuestion == null) {
                throw new IllegalStateException(
                        "Not all required fields set before building HunchNextQuestion! (nextQuestion null)");
            } else if (buildTopic == null) {
                throw new IllegalStateException(
                        "Not all required fields set before building HunchNextQuestion! (buildTopic null)");
            }

            /*
             * if ( buildPrevQAState == null ) buildPrevQAState = "";
             * 
             * if ( buildRankedResultResponses == null )
             * buildRankedResultResponses = "";
             */

            HunchNextQuestion ret = new HunchNextQuestion(val, buildNextQuestion, buildTopic, buildPrevQAState,
                    buildRankedResultResponses, Variety.DEFAULT, false);

            reset();

            return ret;
        }

        HunchNextQuestion buildForResults() {
            if (val == null) {
                throw new IllegalStateException(
                        "Not all required fields set before building HunchNextQuestion! (JSON value null)");
            } else if (buildRankedResultResponses == null) {
                throw new IllegalStateException(
                        "Not all required fields set before building HunchNextQuestion! (RankedResults value null)");
            }

            HunchNextQuestion ret = new HunchNextQuestion(val, null, null, null, buildRankedResultResponses,
                    Variety.RESULTS, true);

            reset();

            return ret;
        }

        /*
         * (non-Javadoc)
         * 
         * @see com.hunch.api.HunchObject.Builder#reset()
         */
        @Override
        void reset() {
            val = null;
            buildNextQuestion = null;
            buildPrevQAState = null;
            buildRankedResultResponses = null;
            buildTopic = null;
        }

    }

    private final JSONObject json;
    private final HunchQuestion nextQuestion;
    private final IHunchTopic topic;
    private final String prevQAState, rankedResultResponses;
    private final Variety variety;
    private final Boolean isResultsOnly;

    private HunchNextQuestion(JSONObject json, HunchQuestion nextQuestion, IHunchTopic topic, String prevQAState,
            String rankedResultResponses, Variety v, Boolean isResultsOnly) {
        this.json = json;
        this.nextQuestion = nextQuestion;
        this.topic = topic;
        this.prevQAState = prevQAState;
        this.rankedResultResponses = rankedResultResponses;
        this.variety = v;
        this.isResultsOnly = isResultsOnly;
    }

    public HunchQuestion getNextQuestion() {
        assert nextQuestion != null;

        return nextQuestion;
    }

    public IHunchTopic getTopic() {
        assert topic != null;

        return topic;
    }

    /**
     * Gets the previous question and answer state for this question.
     * 
     * Returns null if this is the first question.
     * 
     * @return the QA State of the previous question
     */
    public String getPrevQAState() {
        //assert prevQAState != null;

        return prevQAState;
    }

    public String getRankedResultResponses() {
        assert rankedResultResponses != null;

        return rankedResultResponses;
    }

    public Variety getVariety() {
        assert variety != null;

        return variety;
    }

    public boolean isResult() {
        assert isResultsOnly != null;

        return isResultsOnly; // unboxes the Boolean on return.
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.hunch.api.HunchObject#getJSON()
     */
    @Override
    public JSONObject getJSON() {
        assert json != null;

        return json;
    }

    public static HunchNextQuestion.Builder getBuilder() {
        if (b == null)
            b = new HunchNextQuestion.Builder();

        return b;
    }

    public static HunchNextQuestion buildFromJSON(final JSONObject response) {
        final HunchNextQuestion.Builder nqBuilder = getBuilder();

        if (response.has("rankedResultResponses") && response.length() == 1) {
            // this is the last question in the topic
            // it contains only the list of results to be passed
            // to rankedResponses
            try {

                nqBuilder.init(response).setRankedResultResponses(response.getString("rankedResultResponses"));
            } catch (JSONException e) {
                throw new RuntimeException("Couldn't build HunchNextQuestion!", e);
            }

            return nqBuilder.buildForResults();
        }

        final HunchQuestion.Builder qBuilder = HunchQuestion.getBuilder();
        final HunchTopic.Builder tBuilder = HunchTopic.getBuilder();
        final HunchResponse.Builder respBuilder = HunchResponse.getBuilder();
        final HunchCategory.Builder catBuilder = HunchCategory.getBuilder();

        try {
            final JSONObject jsonNextQuestion = response.getJSONObject("nextQuestion");

            List<HunchResponse> responses = new ArrayList<HunchResponse>();

            JSONArray jsonResponses = jsonNextQuestion.getJSONArray("responses");

            for (int i = 0; i < jsonResponses.length(); i++) {
                JSONObject jsonResponse = jsonResponses.getJSONObject(i);

                /*
                 *    image url can be not set on some             
                 *  response objects returned by the Hunch API
                 *  --
                 *  in order to avoid jumping to the catch block
                 *  upon missing imageUrl, we need to handle it
                 *  in it's own try block
                 */

                String respImgUrl = null;
                try {
                    respImgUrl = jsonResponse.getString("imageUrl");
                } catch (JSONException e) {
                    Log.v(Const.TAG,
                            "got response object with no imageUrl " + "in HunchNextQuestion.buildFromJSON()");
                }

                /*
                 *    Same deal here, the responseID is not set for 
                 *  "skip this question" responses, handle it separately
                 */

                Integer respID = null;
                try {
                    respID = jsonResponse.getInt("responseId");
                } catch (JSONException e) {
                    //Log.d( Const.TAG, "couldn't find ID for HunchResponse! (probably a " +
                    //      "\"skip this question\" response)" );
                }

                //Log.d( Const.TAG, "building hunchResponse...\n" + jsonResponse.toString( 4 ) );

                respBuilder.init(jsonResponse).setId(respID).setText(jsonResponse.getString("responseText"))
                        .setQAState(jsonResponse.getString("qaState")).setImageUrl(respImgUrl);

                HunchResponse resp = respBuilder.buildForNextQuestion();

                responses.add(resp);
            }

            //Log.d( Const.TAG, "building HunchQuestion...\n" + jsonNextQuestion.toString( 4 ) );

            /*
             * Again, imageUrl can be null sometimes when the
             * API returns a hunchQuestion as part of a
             * nextQuestion call, so we have to handle it 
             * in a separate try block 
             */
            String questionImageUrl = null;
            try {
                questionImageUrl = jsonNextQuestion.getString("imageUrl");
            } catch (JSONException e) {
                Log.v(Const.TAG, "got question object with no imageUrl " + "in HunchNextQuestion.buildFromJSON()");
            }

            // build the question
            qBuilder.init(jsonNextQuestion).setId(jsonNextQuestion.getInt("questionId"))
                    .setText(jsonNextQuestion.getString("questionText"))
                    .setQuestionNumber(jsonNextQuestion.getInt("questionNumber")).setImageUrl(questionImageUrl)
                    .setResponses(responses);

            final HunchQuestion nextQuestion = qBuilder.buildForNextQuestion();

            JSONObject jsonTopic = response.getJSONObject("topic");

            JSONObject jsonCategory = jsonTopic.getJSONObject("category");

            //Log.d( Const.TAG, "building HunchCategory...\n" + jsonCategory.toString( 4 ) );

            catBuilder.init(jsonCategory).setUrlName(jsonCategory.getString("categoryUrlName"))
                    .setName(jsonCategory.getString("categoryName"))
                    .setImageUrl(jsonCategory.getString("categoryImageUrl"));

            //Log.d( Const.TAG, "building HunchTopic...\n" + jsonTopic.toString( 4 ) );

            tBuilder.init(jsonTopic).setId(jsonTopic.getString("topicId"))
                    .setDecision(jsonTopic.getString("topicDecision")).setHunchUrl(jsonTopic.getString("hunchUrl"))
                    .setImageUrl(jsonTopic.getString("imageUrl")).setCategory(catBuilder.build());

            final IHunchTopic topic = tBuilder.buildForNextQuestion();

            /*
             * PrevQaState is left unset by the API on the first question.
             * Again, gotta handle it separately.
             */

            String prevQaState = null;
            try {
                prevQaState = response.getString("prevQaState");
            } catch (JSONException e) {
                Log.i(Const.TAG, "got nextQuestion object with no prevQaState "
                        + "in HunchNextQuestion.buildFromJSON() (probably first question)");
            }

            nqBuilder.init(response).setNextQuestion(nextQuestion).setTopic(topic).setPrevQAState(prevQaState)
                    .setRankedResultResponses(response.getString("rankedResultResponses"));

        } catch (JSONException e) {
            throw new RuntimeException("Couldn't build HunchNextQuestion!", e);
        }

        return nqBuilder.build();
    }

}