/**
* Copyright (c) 2002-2013 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.noser.neo4j.android.dbinspector.implementation;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import org.neo4j.android.client.GraphDatabase;
import org.neo4j.android.client.Neo4jServiceException;
import org.neo4j.android.client.NodeIterator;
import org.neo4j.android.common.ParcelableNode;
import org.neo4j.android.common.ParcelableRelationship;
import roboguice.activity.RoboActivity;
import roboguice.inject.ContentView;
import roboguice.inject.InjectExtra;
import roboguice.inject.InjectView;
import roboguice.util.Ln;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.inject.Inject;
import com.noser.neo4j.android.dbinspector.R;
import com.noser.neo4j.android.dbinspector.base.DBInspectorConstants;
import com.noser.neo4j.android.dbinspector.interfaces.IDBManager;
@ContentView(R.layout.relationship_activity)
public class RelationshipActivity extends RoboActivity {
@Inject
private Context context;
@Inject
private IDBManager dbManager;
@InjectView(R.id.relationshipsLayout)
private LinearLayout relationshipsLayout;
@InjectExtra(value = DBInspectorConstants.INTENTEXTRA_CENTER_NODEID)
private long centerNodeId;
@InjectExtra(value = DBInspectorConstants.INTENTEXTRA_PEER_NODEID)
private long peerNodeId;
@InjectView(R.id.relationshipCreateButton)
private ImageButton relationshipCreateButton;
@Inject
private LayoutInflater inflater;
private int buttonMinimumHeight;
private int buttonMinimumWidth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
buttonMinimumHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
DBInspectorConstants.BUTTON_MINIMUM_HEIGHT, getResources().getDisplayMetrics());
buttonMinimumWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
DBInspectorConstants.BUTTON_MINIMUM_WIDTH, getResources().getDisplayMetrics());
setTitle(getResources().getString(R.string.database_title) + " " + dbManager.getCurrentNeo4jDatabaseName());
relationshipCreateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
askCreateRelationship();
}
});
}
@Override
protected void onResume() {
super.onResume();
updateRelationshipsList();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((requestCode == DBInspectorConstants.DEFAULT_REQUESTCODE) && (resultCode == RESULT_OK)) {
if (data.getExtras().containsKey(DBInspectorConstants.INTENTEXTRA_NODE_DELETED)) {
finish();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void updateRelationshipsList() {
try {
relationshipsLayout.removeAllViews();
GraphDatabase database = dbManager.getCurrentNeo4jDatabase();
database.beginTx();
try {
ParcelableNode centerNode = database.getNodeById(centerNodeId);
List<ParcelableRelationship> relationshipsFromCenterNode = new ArrayList<ParcelableRelationship>();
List<ParcelableRelationship> relationshipsToCenterNode = new ArrayList<ParcelableRelationship>();
for (ParcelableRelationship relationship : centerNode.getRelationships()) {
if ((centerNodeId == relationship.getStartNodeId()) && (peerNodeId == relationship.getEndNodeId())) {
relationshipsFromCenterNode.add(relationship);
}
if ((centerNodeId != peerNodeId) && (peerNodeId == relationship.getStartNodeId())
&& (centerNodeId == relationship.getEndNodeId())) {
relationshipsToCenterNode.add(relationship);
}
}
Button nodeCenterButton = (Button) findViewById(R.id.nodeCenterButton);
nodeCenterButton.setText("" + centerNodeId);
nodeCenterButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNodePropertyActivity(centerNodeId);
}
});
Button nodePeerButton = (Button) findViewById(R.id.nodePeerButton);
if (centerNodeId == peerNodeId) {
nodePeerButton.setVisibility(View.INVISIBLE);
} else {
nodePeerButton.setText("" + peerNodeId);
nodePeerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNodePropertyActivity(peerNodeId);
}
});
}
for (ParcelableRelationship relationship : relationshipsFromCenterNode) {
addRelationshipsListItem(relationship, true);
}
for (ParcelableRelationship relationship : relationshipsToCenterNode) {
addRelationshipsListItem(relationship, false);
}
} finally {
database.txFinish();
}
} catch (Exception e) {
Ln.e(e, "database exception");
showErrorDialog();
}
}
private void addRelationshipsListItem(final ParcelableRelationship relationship, boolean forward) {
Button relationshipButton = new Button(context);
relationshipButton.setMinimumHeight(buttonMinimumHeight);
relationshipButton.setMinimumWidth(buttonMinimumWidth);
String text;
if (centerNodeId != peerNodeId) {
if (forward) {
text = getResources().getString(R.string.node_relationships_forward_button);
} else {
text = getResources().getString(R.string.node_relationships_backward_button);
}
} else {
text = getResources().getString(R.string.node_relationships_both_button);
}
relationshipButton.setText(text + "\n" + relationship.getId() + "\n" + relationship.getName());
relationshipButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showRelationshipPropertyActivity(relationship.getId());
}
});
relationshipsLayout.addView(relationshipButton);
}
private void showErrorDialog() {
AlertDialog dialog = new AlertDialog.Builder(context).create();
dialog.setTitle(R.string.error_title);
dialog.setMessage(getResources().getText(R.string.database_error));
dialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
private void showNodePropertyActivity(long nodeId) {
Intent intent = new Intent(getApplicationContext(), NodePropertiesActivity.class);
intent.putExtra(DBInspectorConstants.INTENTEXTRA_NODEID, nodeId);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivityForResult(intent, DBInspectorConstants.DEFAULT_REQUESTCODE);
}
private void showRelationshipPropertyActivity(long relationshipId) {
Intent intent = new Intent(getApplicationContext(), RelationshipPropertiesActivity.class);
intent.putExtra(DBInspectorConstants.INTENTEXTRA_RELATIONSHIPID, relationshipId);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(intent);
}
private void askCreateRelationship() {
List<Long> nodeIds;
try {
nodeIds = getAllNodeIds();
} catch (Exception e) {
Ln.e(e, "database exception");
showErrorDialog();
return;
}
View relationshipCreateView = inflater.inflate(R.layout.relationship_create, null);
final TextView relationshipCreateStartNodeIdText = (TextView) relationshipCreateView
.findViewById(R.id.relationshipCreateStartNodeIdText);
Formatter formatter = new Formatter();
formatter.format(getResources().getString(R.string.relationship_create_startnode), centerNodeId);
relationshipCreateStartNodeIdText.setText(formatter.toString());
formatter.close();
final EditText relationshipCreateNameText = (EditText) relationshipCreateView.findViewById(R.id.relationshipCreateNameText);
final Spinner relationshipCreateEndnodeIdSpinner = (Spinner) relationshipCreateView
.findViewById(R.id.relationshipCreateEndnodeIdSpinner);
ArrayAdapter<Long> spinnerAdapter = new ArrayAdapter<Long>(context, android.R.layout.simple_spinner_item, nodeIds);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
relationshipCreateEndnodeIdSpinner.setAdapter(spinnerAdapter);
AlertDialog dialog = new AlertDialog.Builder(this).create();
dialog.setTitle(R.string.relationship_create_title);
dialog.setView(relationshipCreateView);
dialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String name = relationshipCreateNameText.getText().toString();
long endNodeId = (Long) relationshipCreateEndnodeIdSpinner.getSelectedItem();
try {
createRelationship(name, endNodeId);
} catch (Exception e) {
Ln.e(e, "could not create relationship");
showErrorDialog();
}
updateRelationshipsList();
}
});
dialog.setButton2(getResources().getString(android.R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
private List<Long> getAllNodeIds() throws RemoteException, Neo4jServiceException {
GraphDatabase database = dbManager.getCurrentNeo4jDatabase();
database.beginTx();
try {
NodeIterator iterator = database.getAllNodes();
List<Long> nodeIds = new ArrayList<Long>();
while (iterator.hasNext()) {
ParcelableNode node = iterator.next();
nodeIds.add(node.getId());
}
return nodeIds;
} finally {
database.txFinish();
}
}
private void createRelationship(String name, long endNodeId) throws RemoteException, Neo4jServiceException {
GraphDatabase database = dbManager.getCurrentNeo4jDatabase();
database.beginTx();
try {
ParcelableRelationship relationship = new ParcelableRelationship();
relationship.setStartNodeId(centerNodeId);
relationship.setEndNodeId(endNodeId);
relationship.setName(name);
long relationshipId = database.createRelationship(relationship);
database.txSuccess();
Ln.i("created relationship '" + relationship + "' with id '" + relationshipId + "'");
} finally {
database.txFinish();
}
}
}