/** * Copyright 2012 Facebook * * 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.facebook.samples.booleanog; import android.app.AlertDialog; import android.content.Intent; import android.database.MatrixCursor; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.View; import android.view.ViewGroup; import android.widget.*; import com.facebook.*; import com.facebook.model.*; import com.facebook.widget.FriendPickerFragment; import com.facebook.widget.UserSettingsFragment; import com.facebook.widget.PickerFragment; import java.text.SimpleDateFormat; import java.util.*; public class LogicActivity extends FragmentActivity { private static final String TAG = "BooleanOpenGraphSample"; private static final String SAVE_ACTIVE_TAB = TAG + ".SAVE_ACTIVE_TAB"; private static final String SAVE_CONTENT_SELECTION = TAG + ".SAVE_CONTENT_SELECTION"; private static final String SAVE_LEFT_OPERAND_SELECTION = TAG + ".SAVE_LEFT_OPERAND_SELECTION"; private static final String SAVE_RIGHT_OPERAND_SELECTION = TAG + ".SAVE_RIGHT_OPERAND_SELECTION"; private static final String SAVE_RESULT_TEXT = TAG + ".SAVE_RESULT_TEXT"; private static final String SAVE_POST_RESULT_TEXT = TAG + ".SAVE_POST_RESULT_TEXT"; private static final String SAVE_PENDING = TAG + ".SAVE_PENDING"; private static final String SAVE_FRIEND_ACTIONS = TAG + ".SAVE_FRIEND_ACTIONS"; private static final String PENDING_POST_PATH = "PENDING_POST_PATH"; private static final String PENDING_POST_LEFT = "PENDING_POST_LEFT"; private static final String PENDING_POST_RIGHT = "PENDING_POST_RIGHT"; private static final String PENDING_POST_RESULT = "PENDING_POST_RESULT"; private static final String AND_ACTION = "fb_sample_boolean_og:and"; private static final String OR_ACTION = "fb_sample_boolean_og:or"; private static final String POST_AND_ACTION_PATH = "me/" + AND_ACTION; private static final String POST_OR_ACTION_PATH = "me/" + OR_ACTION; private static final String TRUE_GRAPH_OBJECT_URL = "http://samples.ogp.me/369360019783304"; private static final String FALSE_GRAPH_OBJECT_URL = "http://samples.ogp.me/369360256449947"; private static final String INSTALLED = "installed"; private static final List<String> PERMISSIONS = Arrays.asList("publish_actions"); private static volatile TruthValueGraphObject TRUE_GRAPH_OBJECT; private static volatile TruthValueGraphObject FALSE_GRAPH_OBJECT; private static volatile int TRUE_SPINNER_INDEX = -1; private static volatile int FALSE_SPINNER_INDEX = -1; // Main layout private Button logicButton; private Button friendsButton; private Button settingsButton; private Button contentButton; private String activeTab; // Logic group private ViewGroup logicGroup; private Spinner leftSpinner; private Spinner rightSpinner; private Button andButton; private Button orButton; private TextView resultText; private TextView postResultText; private Bundle pendingPost; // Friends group private ViewGroup friendsGroup; private FriendPickerFragment friendPickerFragment; private RequestAsyncTask pendingRequest; private SimpleCursorAdapter friendActivityAdapter; private ProgressBar friendActivityProgressBar; private ArrayList<ActionRow> friendActionList; // Login group private ViewGroup settingsGroup; private UserSettingsFragment userSettingsFragment; // Content group private ViewGroup contentGroup; private ImageView contentImage; private Spinner contentSpinner; private UiLifecycleHelper uiHelper; private Session.StatusCallback callback = new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { if (exception != null) { pendingPost = null; } else if (state == SessionState.OPENED) { friendPickerFragment.loadData(false); } else if (state == SessionState.OPENED_TOKEN_UPDATED) { sendPendingPost(); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); uiHelper = new UiLifecycleHelper(this, callback); uiHelper.onCreate(savedInstanceState); setContentView(R.layout.main); // Views logicButton = (Button) findViewById(R.id.logic_button); friendsButton = (Button) findViewById(R.id.friends_button); settingsButton = (Button) findViewById(R.id.settings_button); contentButton = (Button) findViewById(R.id.content_button); logicGroup = (ViewGroup) findViewById(R.id.logic_group); leftSpinner = (Spinner) findViewById(R.id.left_spinner); rightSpinner = (Spinner) findViewById(R.id.right_spinner); andButton = (Button) findViewById(R.id.and_button); orButton = (Button) findViewById(R.id.or_button); resultText = (TextView) findViewById(R.id.result_text); postResultText = (TextView) findViewById(R.id.post_result_text); friendsGroup = (ViewGroup) findViewById(R.id.friends_group); ListView friendActivityList = (ListView) findViewById(R.id.friend_activity_list); String[] mapColumnNames = {"date", "action"}; int[] mapViewIds = {R.id.friend_action_date, R.id.friend_action_data}; friendActivityAdapter = new SimpleCursorAdapter(this, R.layout.friend_activity_row, createEmptyCursor(), mapColumnNames, mapViewIds); friendActivityList.setAdapter(friendActivityAdapter); friendActivityProgressBar = (ProgressBar) findViewById(R.id.friend_activity_progress_bar); settingsGroup = (ViewGroup) findViewById(R.id.settings_group); contentGroup = (ViewGroup) findViewById(R.id.content_group); contentImage = (ImageView) findViewById(R.id.content_image); contentSpinner = (Spinner) findViewById(R.id.content_spinner); // Fragments FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); friendPickerFragment = (FriendPickerFragment) fragmentManager.findFragmentById(R.id.friend_picker_fragment); if (friendPickerFragment == null) { Bundle args = new Bundle(); args.putBoolean(FriendPickerFragment.SHOW_TITLE_BAR_BUNDLE_KEY, false); friendPickerFragment = new FriendPickerFragment(args); transaction.add(R.id.friend_picker_fragment, friendPickerFragment); } userSettingsFragment = (UserSettingsFragment) fragmentManager.findFragmentById(R.id.login_fragment); if (userSettingsFragment == null) { userSettingsFragment = new UserSettingsFragment(); transaction.add(R.id.login_fragment, userSettingsFragment); } transaction.commit(); // Spinners ArrayAdapter<CharSequence> truthAdapter = ArrayAdapter .createFromResource(this, R.array.truth_values, android.R.layout.simple_spinner_item); truthAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); leftSpinner.setAdapter(truthAdapter); rightSpinner.setAdapter(truthAdapter); contentSpinner.setAdapter(truthAdapter); leftSpinner.setSelection(0); rightSpinner.setSelection(0); // Navigation for (Button button : Arrays.asList(logicButton, friendsButton, settingsButton, contentButton)) { initializeNavigationButton(button); } // Logic initializeCalculationButton(andButton); initializeCalculationButton(orButton); // Friends friendPickerFragment.setOnErrorListener(new PickerFragment.OnErrorListener() { @Override public void onError(PickerFragment<?> fragment, FacebookException error) { LogicActivity.this.onError(error); } }); friendPickerFragment.setUserId("me"); friendPickerFragment.setMultiSelect(false); friendPickerFragment.setOnSelectionChangedListener(new PickerFragment.OnSelectionChangedListener() { @Override public void onSelectionChanged(PickerFragment<?> fragment) { LogicActivity.this.onFriendSelectionChanged(); } }); friendPickerFragment.setExtraFields(Arrays.asList(INSTALLED)); friendPickerFragment.setFilter(new PickerFragment.GraphObjectFilter<GraphUser>() { @Override public boolean includeItem(GraphUser graphObject) { Boolean installed = graphObject.cast(GraphUserWithInstalled.class).getInstalled(); return (installed != null) && installed.booleanValue(); } }); // Content contentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { LogicActivity.this.onContentSelectionChanged(); } @Override public void onNothingSelected(AdapterView<?> adapterView) { LogicActivity.this.onContentSelectionChanged(); } }); // Restore saved state Button startButton = logicButton; if (savedInstanceState != null) { leftSpinner.setSelection(savedInstanceState.getInt(SAVE_LEFT_OPERAND_SELECTION)); rightSpinner.setSelection(savedInstanceState.getInt(SAVE_RIGHT_OPERAND_SELECTION)); contentSpinner.setSelection(savedInstanceState.getInt(SAVE_CONTENT_SELECTION)); resultText.setText(savedInstanceState.getString(SAVE_RESULT_TEXT)); postResultText.setText(savedInstanceState.getString(SAVE_POST_RESULT_TEXT)); activeTab = savedInstanceState.getString(SAVE_ACTIVE_TAB); pendingPost = savedInstanceState.getBundle(SAVE_PENDING); friendActionList = savedInstanceState.getParcelableArrayList(SAVE_FRIEND_ACTIONS); if ((friendActionList != null) && (friendActionList.size() > 0)) { updateCursor(friendActionList); } if (getString(R.string.navigate_friends).equals(activeTab)) { startButton = friendsButton; } else if (getString(R.string.navigate_content).equals(activeTab)) { startButton = contentButton; } else if (getString(R.string.navigate_settings).equals(activeTab)) { startButton = settingsButton; } } if (!handleNativeLink()) { onNavigateButtonClick(startButton); } } // ----------------------------------------------------------------------------------- // Activity lifecycle @Override public void onStart() { super.onStart(); Session session = Session.getActiveSession(); if (session != null && session.isOpened()) { friendPickerFragment.loadData(false); } } @Override public void onResume() { super.onResume(); uiHelper.onResume(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); uiHelper.onSaveInstanceState(outState); outState.putInt(SAVE_LEFT_OPERAND_SELECTION, leftSpinner.getSelectedItemPosition()); outState.putInt(SAVE_RIGHT_OPERAND_SELECTION, rightSpinner.getSelectedItemPosition()); outState.putInt(SAVE_CONTENT_SELECTION, contentSpinner.getSelectedItemPosition()); outState.putString(SAVE_RESULT_TEXT, resultText.getText().toString()); outState.putString(SAVE_POST_RESULT_TEXT, postResultText.getText().toString()); outState.putString(SAVE_ACTIVE_TAB, activeTab); outState.putBundle(SAVE_PENDING, pendingPost); outState.putParcelableArrayList(SAVE_FRIEND_ACTIONS, friendActionList); } @Override public void onPause() { super.onPause(); uiHelper.onPause(); } @Override public void onDestroy() { super.onDestroy(); uiHelper.onDestroy(); friendPickerFragment.setOnErrorListener(null); friendPickerFragment.setOnSelectionChangedListener(null); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); uiHelper.onActivityResult(requestCode, resultCode, data); } // ----------------------------------------------------------------------------------- // Navigation private void initializeNavigationButton(Button button) { button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onNavigateButtonClick((Button) view); } }); } private void onNavigateButtonClick(Button source) { activeTab = source.getText().toString(); logicGroup.setVisibility(getGroupVisibility(source, logicButton)); friendsGroup.setVisibility(getGroupVisibility(source, friendsButton)); settingsGroup.setVisibility(getGroupVisibility(source, settingsButton)); contentGroup.setVisibility(getGroupVisibility(source, contentButton)); // Show an error if viewing friends and there is no logged in user. if (source == friendsButton) { Session session = Session.getActiveSession(); if ((session == null) || !session.isOpened()) { new AlertDialog.Builder(this) .setTitle(R.string.feature_requires_login_title) .setMessage(R.string.feature_requires_login_message) .setPositiveButton(R.string.ok_button, null) .show(); } } } private int getGroupVisibility(Button source, Button groupButton) { if (source == groupButton) { return View.VISIBLE; } else { return View.GONE; } } // ----------------------------------------------------------------------------------- // Logic group private void initializeCalculationButton(Button button) { button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onOperationButtonClick(view); } }); } private void onOperationButtonClick(View view) { if (view == andButton) { onAndButtonClick(); } else if (view == orButton) { onOrButtonClick(); } else { assert false; } } private void onAndButtonClick() { boolean leftOperand = getSpinnerBoolean(leftSpinner); boolean rightOperand = getSpinnerBoolean(rightSpinner); boolean result = leftOperand && rightOperand; resultText.setText(getLogicText(getString(R.string.and_operation), leftOperand, rightOperand, result)); postAction(POST_AND_ACTION_PATH, leftOperand, rightOperand, result); } private void onOrButtonClick() { boolean leftOperand = getSpinnerBoolean(leftSpinner); boolean rightOperand = getSpinnerBoolean(rightSpinner); boolean result = leftOperand || rightOperand; resultText.setText(getLogicText(getString(R.string.or_operation), leftOperand, rightOperand, result)); postAction(POST_OR_ACTION_PATH, leftOperand, rightOperand, result); } private String getLogicText(String op, boolean leftOperand, boolean rightOperand, boolean result) { String trueString = getString(R.string.true_value); String falseString = getString(R.string.false_value); String arg0String = leftOperand ? trueString : falseString; String arg1String = rightOperand ? trueString : falseString; String resultString = result ? trueString : falseString; return String.format("%s %s %s = %s", arg0String, op, arg1String, resultString); } private void postAction(final String actionPath, final boolean leftOperand, final boolean rightOperand, final boolean result) { Bundle post = new Bundle(); post.putString(PENDING_POST_PATH, actionPath); post.putBoolean(PENDING_POST_LEFT, leftOperand); post.putBoolean(PENDING_POST_RIGHT, rightOperand); post.putBoolean(PENDING_POST_RESULT, result); pendingPost = post; sendPendingPost(); } private void sendPendingPost() { if (pendingPost == null) { return; } Session session = Session.getActiveSession(); if ((session == null) || !session.isOpened()) { postResultText.setText("Not logged in, no post generated."); pendingPost = null; return; } List<String> permissions = session.getPermissions(); if (!permissions.containsAll(PERMISSIONS)) { Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(this, PERMISSIONS); session.requestNewPublishPermissions(newPermissionsRequest); return; } postResultText.setText("Posting action..."); // For demo purposes, result is just a boolean, but operands are Open Graph objects String actionPath = pendingPost.getString(PENDING_POST_PATH); boolean leftOperand = pendingPost.getBoolean(PENDING_POST_LEFT); boolean rightOperand = pendingPost.getBoolean(PENDING_POST_RIGHT); boolean result = pendingPost.getBoolean(PENDING_POST_RESULT); LogicAction action = GraphObject.Factory.create(LogicAction.class); action.setResult(result); action.setTruthvalue(getTruthValueObject(leftOperand)); action.setAnothertruthvalue(getTruthValueObject(rightOperand)); Request.Callback callback = new Request.Callback() { @Override public void onCompleted(Response response) { onPostActionResponse(response); } }; Request request = new Request(session, actionPath, null, HttpMethod.POST, callback); request.setGraphObject(action); RequestAsyncTask task = new RequestAsyncTask(request); task.execute(); } private void onPostActionResponse(Response response) { PostResponse postResponse = response.getGraphObjectAs(PostResponse.class); if (postResponse != null && postResponse.getId() != null) { postResultText.setText("Post id = " + postResponse.getId()); } else if (response.getError() != null) { postResultText.setText(response.getError().getErrorMessage()); } else { postResultText.setText(""); } } private TruthValueGraphObject getTruthValueObject(boolean value) { if (value) { if (TRUE_GRAPH_OBJECT == null) { TruthValueGraphObject object = GraphObject.Factory .create(TruthValueGraphObject.class); object.setUrl(TRUE_GRAPH_OBJECT_URL); TRUE_GRAPH_OBJECT = object; } return TRUE_GRAPH_OBJECT; } else { if (FALSE_GRAPH_OBJECT == null) { TruthValueGraphObject object = GraphObject.Factory .create(TruthValueGraphObject.class); object.setUrl(FALSE_GRAPH_OBJECT_URL); FALSE_GRAPH_OBJECT = object; } return FALSE_GRAPH_OBJECT; } } // ----------------------------------------------------------------------------------- // Friends group private void onFriendSelectionChanged() { GraphUser user = chooseOne(friendPickerFragment.getSelection()); if (user != null) { onChooseFriend(user.getId()); } else { friendActivityAdapter.changeCursor(createEmptyCursor()); } } private void onChooseFriend(String friendId) { friendActivityProgressBar.setVisibility(View.VISIBLE); String andPath = String.format("%s/%s", friendId, AND_ACTION); String orPath = String.format("%s/%s", friendId, OR_ACTION); Request getAnds = new Request(Session.getActiveSession(), andPath, null, HttpMethod.GET); Request getOrs = new Request(Session.getActiveSession(), orPath, null, HttpMethod.GET); RequestBatch batch = new RequestBatch(getAnds, getOrs); if (pendingRequest != null) { pendingRequest.cancel(true); } pendingRequest = new RequestAsyncTask(batch) { @Override protected void onPostExecute(List<Response> result) { if (pendingRequest == this) { pendingRequest = null; LogicActivity.this.onPostExecute(result); } } }; pendingRequest.execute(); } private void onPostExecute(List<Response> result) { friendActivityProgressBar.setVisibility(View.GONE); friendActionList = createActionRows(result); updateCursor(friendActionList); } private ArrayList<ActionRow> createActionRows(List<Response> result) { ArrayList<ActionRow> publishedItems = new ArrayList<ActionRow>(); for (Response response : result) { if (response.getError() != null) { continue; } GraphMultiResult list = response.getGraphObjectAs(GraphMultiResult.class); List<PublishedLogicAction> listData = list.getData().castToListOf(PublishedLogicAction.class); for (PublishedLogicAction action : listData) { publishedItems.add(createActionRow(action)); } } Collections.sort(publishedItems); return publishedItems; } private void updateCursor(Iterable<ActionRow> publishedItems) { MatrixCursor cursor = createEmptyCursor(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); int id = 0; for (ActionRow item : publishedItems) { Object[] row = new Object[3]; row[0] = id++; row[1] = dateFormat.format(item.publishDate); row[2] = item.actionText; cursor.addRow(row); } friendActivityAdapter.changeCursor(cursor); friendActivityAdapter.notifyDataSetChanged(); } private MatrixCursor createEmptyCursor() { String[] cursorColumns = {"_ID", "date", "action"}; return new MatrixCursor(cursorColumns); } private ActionRow createActionRow(PublishedLogicAction action) { String actionText = getActionText(action); Date publishDate = action.getPublishTime(); return new ActionRow(actionText, publishDate); } private String getActionText(PublishedLogicAction action) { LogicAction actionData = action.getData(); if (actionData == null) { return ""; } TruthValueGraphObject left = actionData.getTruthvalue(); TruthValueGraphObject right = actionData.getAnothertruthvalue(); Boolean actionResult = actionData.getResult(); String verb = action.getType(); if (AND_ACTION.equals(verb)) { verb = getString(R.string.and_operation); } else if (OR_ACTION.equals(verb)) { verb = getString(R.string.or_operation); } if ((left == null) || (right == null) || (actionResult == null) || (verb == null)) { return ""; } return String.format("%s %s %s = %s", left.getTitle(), verb, right.getTitle(), actionResult.toString()); } // ----------------------------------------------------------------------------------- // Content group private Boolean getDeepLinkContent(Uri deepLinkUri) { if (deepLinkUri != null) { String deepLink = deepLinkUri.toString(); if (deepLink.startsWith(TRUE_GRAPH_OBJECT_URL)) { return Boolean.TRUE; } else if (deepLink.startsWith(FALSE_GRAPH_OBJECT_URL)) { return Boolean.FALSE; } } return null; } private void onContentSelectionChanged() { Boolean spinnerBoolean = getSpinnerBoolean(contentSpinner); if (Boolean.TRUE.equals(spinnerBoolean)) { contentImage.setVisibility(View.VISIBLE); contentImage.setImageResource(R.drawable.true_content); } else if (Boolean.FALSE.equals(spinnerBoolean)) { contentImage.setVisibility(View.VISIBLE); contentImage.setImageResource(R.drawable.false_content); } else { contentImage.setImageResource(View.INVISIBLE); } } // ----------------------------------------------------------------------------------- // Utility methods private boolean handleNativeLink() { Session existingSession = Session.getActiveSession(); // If we have a valid existing session, we'll use it; if not, open one using the provided Intent // but do not cache the token (we don't want to use the same user identity the next time the // app is run). if (existingSession == null || !existingSession.isOpened()) { AccessToken accessToken = AccessToken.createFromNativeLinkingIntent(getIntent()); if (accessToken != null) { Session newSession = new Session.Builder(this).setTokenCachingStrategy(new NonCachingTokenCachingStrategy()) .build(); newSession.open(accessToken, null); Session.setActiveSession(newSession); } } // See if we have a deep link in addition. Boolean deepLinkContent = getDeepLinkContent(getIntent().getData()); if (deepLinkContent != null) { onNavigateButtonClick(contentButton); contentSpinner.setSelection(getSpinnerPosition(deepLinkContent)); return true; } return false; } private int getSpinnerPosition(Boolean value) { initializeSpinnerIndexes(); if (Boolean.TRUE.equals(value)) { return TRUE_SPINNER_INDEX; } else if (Boolean.FALSE.equals(value)) { return FALSE_SPINNER_INDEX; } else { return -1; } } private Boolean getSpinnerBoolean(Spinner spinner) { initializeSpinnerIndexes(); int position = spinner.getSelectedItemPosition(); if (position == TRUE_SPINNER_INDEX) { return Boolean.TRUE; } else if (position == FALSE_SPINNER_INDEX) { return Boolean.FALSE; } else { return null; } } private void initializeSpinnerIndexes() { if ((TRUE_SPINNER_INDEX < 0) || (FALSE_SPINNER_INDEX < 0)) { String[] truthArray = getResources().getStringArray(R.array.truth_values); List<String> truthList = Arrays.asList(truthArray); TRUE_SPINNER_INDEX = truthList.indexOf(getString(R.string.true_value)); FALSE_SPINNER_INDEX = truthList.indexOf(getString(R.string.false_value)); } } private void onError(Exception error) { showErrorMessage(error.getMessage()); } private void showErrorMessage(String message) { new AlertDialog.Builder(this) .setTitle(R.string.error_dialog_title) .setMessage(message) .setPositiveButton(R.string.ok_button, null) .show(); } private <T> T chooseOne(List<T> ts) { for (T t : ts) { return t; } return null; } // ----------------------------------------------------------------------------------- // Supporting types private interface GraphUserWithInstalled extends GraphUser { Boolean getInstalled(); } private static class ActionRow implements Comparable<ActionRow>, Parcelable { final String actionText; final Date publishDate; ActionRow(String actionText, Date publishDate) { this.actionText = actionText; this.publishDate = publishDate; } @Override public int compareTo(ActionRow other) { if (other == null) { return 1; } else { return publishDate.compareTo(other.publishDate); } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(actionText); parcel.writeLong(publishDate.getTime()); } @SuppressWarnings("unused") public final Creator<ActionRow> CREATOR = new Creator<ActionRow>() { @Override public ActionRow createFromParcel(Parcel parcel) { String actionText = parcel.readString(); Date publishDate = new Date(parcel.readLong()); return new ActionRow(actionText, publishDate); } @Override public ActionRow[] newArray(int size) { return new ActionRow[size]; } }; } /** * Used to create and consume TruthValue open graph objects. */ private interface TruthValueGraphObject extends GraphObject { void setUrl(String url); String getTitle(); } /** * Used to create and consume And an Or open graph actions */ private interface LogicAction extends OpenGraphAction { Boolean getResult(); void setResult(Boolean result); TruthValueGraphObject getTruthvalue(); void setTruthvalue(TruthValueGraphObject truthvalue); TruthValueGraphObject getAnothertruthvalue(); void setAnothertruthvalue(TruthValueGraphObject anothertruthvalue); } /** * Used to consume published And and Or open graph actions. */ private interface PublishedLogicAction extends OpenGraphAction { LogicAction getData(); String getType(); } /** * Used to inspect the response from posting an action */ private interface PostResponse extends GraphObject { String getId(); } }