Skip to content

Commit

Permalink
Rhizome Java API: list bundles
Browse files Browse the repository at this point in the history
  • Loading branch information
quixotique committed Jul 9, 2014
1 parent 6102328 commit db8ee79
Show file tree
Hide file tree
Showing 9 changed files with 656 additions and 1 deletion.
113 changes: 113 additions & 0 deletions java/org/servalproject/json/JSONTableScanner.java
@@ -0,0 +1,113 @@
/**
* Copyright (C) 2014 Serval Project Inc.
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software 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 source code 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 source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

package org.servalproject.json;

import java.lang.reflect.InvocationTargetException;
import java.io.IOException;
import java.util.Vector;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;

public class JSONTableScanner {

private static class Column {
public String label;
public Class type;
public JSONTokeniser.Narrow opts;
}

HashMap<String,Column> columnMap;
Column[] columns;

public JSONTableScanner()
{
columnMap = new HashMap<String,Column>();
}

public JSONTableScanner addColumn(String label, Class type)
{
return addColumn(label, type, JSONTokeniser.Narrow.NO_NULL);
}

public JSONTableScanner addColumn(String label, Class type, JSONTokeniser.Narrow opts)
{
assert !columnMap.containsKey(label);
Column col = new Column();
col.label = label;
col.type = type;
col.opts = opts;
columnMap.put(label, col);
return this;
}

public void consumeHeaderArray(JSONTokeniser json) throws IOException, JSONInputException
{
Vector<String> headers = new Vector<String>();
json.consumeArray(headers, String.class);
if (headers.size() < 1)
throw new JSONInputException("malformed JSON table, empty headers array");
columns = new Column[headers.size()];
HashSet<String> headerSet = new HashSet<String>(columnMap.size());
for (int i = 0; i < headers.size(); ++i) {
String header = headers.get(i);
if (columnMap.containsKey(header)) {
if (headerSet.contains(header))
throw new JSONInputException("malformed JSON table, duplicate column header: \"" + header + "\"");
headerSet.add(header);
columns[i] = columnMap.get(header);
}
}
for (String header: columnMap.keySet())
if (!headerSet.contains(header))
throw new JSONInputException("malformed JSON table, missing column header: \"" + header + "\"");
}

@SuppressWarnings("unchecked")
public Map<String,Object> consumeRowArray(JSONTokeniser json) throws IOException, JSONInputException
{
Object[] row = new Object[columns.length];
json.consumeArray(row, JSONTokeniser.Narrow.ALLOW_NULL);
HashMap<String,Object> rowMap = new HashMap<String,Object>(row.length);
for (int i = 0; i < row.length; ++i) {
Column col = columns[i];
if (col != null) {
Object value;
if (JSONTokeniser.supportsNarrowTo(col.type))
value = JSONTokeniser.narrow(row[i], col.type, col.opts);
else {
value = JSONTokeniser.narrow(row[i], col.opts);
try {
value = value == null ? null : col.type.getConstructor(value.getClass()).newInstance(value);
}
catch (InvocationTargetException e) {
throw new JSONInputException("invalid column value: " + col.label + "=\"" + value + "\"", e.getTargetException());
}
catch (Exception e) {
throw new JSONInputException("invalid column value: " + col.label + "=\"" + value + "\"", e);
}
}
rowMap.put(col.label, value);
}
}
return rowMap;
}
}
14 changes: 14 additions & 0 deletions java/org/servalproject/json/JSONTokeniser.java
Expand Up @@ -131,6 +131,20 @@ public enum Narrow {
ALLOW_NULL
};

public static boolean supportsNarrowTo(Class cls) {
return cls == Boolean.class
|| cls == Integer.class
|| cls == Long.class
|| cls == Float.class
|| cls == Double.class
|| cls == String.class;
}

public static Object narrow(Object tok, Narrow opts) throws UnexpectedException
{
return narrow(tok, Object.class, opts);
}

public static <T> T narrow(Object tok, Class<T> cls) throws UnexpectedException
{
return narrow(tok, cls, Narrow.NO_NULL);
Expand Down
9 changes: 9 additions & 0 deletions java/org/servalproject/servaldna/ServalDClient.java
Expand Up @@ -34,6 +34,8 @@
import org.servalproject.servaldna.SubscriberId;
import org.servalproject.servaldna.ServalDCommand;
import org.servalproject.servaldna.ServalDInterfaceException;
import org.servalproject.servaldna.rhizome.RhizomeCommon;
import org.servalproject.servaldna.rhizome.RhizomeBundleList;
import org.servalproject.servaldna.meshms.MeshMSCommon;
import org.servalproject.servaldna.meshms.MeshMSConversationList;
import org.servalproject.servaldna.meshms.MeshMSMessageList;
Expand All @@ -58,6 +60,13 @@ public ServalDClient(int httpPort, String restfulUsername, String restfulPasswor
this.restfulPassword = restfulPassword;
}

public RhizomeBundleList rhizomeListBundles() throws ServalDInterfaceException, IOException
{
RhizomeBundleList list = new RhizomeBundleList(this);
list.connect();
return list;
}

public MeshMSConversationList meshmsListConversations(SubscriberId sid) throws ServalDInterfaceException, IOException, MeshMSException
{
MeshMSConversationList list = new MeshMSConversationList(this, sid);
Expand Down
78 changes: 78 additions & 0 deletions java/org/servalproject/servaldna/rhizome/RhizomeBundle.java
@@ -0,0 +1,78 @@
/**
* Copyright (C) 2014 Serval Project Inc.
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software 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 source code 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 source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

package org.servalproject.servaldna.rhizome;

import org.servalproject.servaldna.BundleId;
import org.servalproject.servaldna.SubscriberId;
import org.servalproject.servaldna.FileHash;

public class RhizomeBundle {

public final int _rowNumber;
public final int _id;
public final String _token;
public final String service;
public final BundleId id;
public final long version;
public final long date;
public final long _inserttime;
public final SubscriberId _author;
public final int _fromhere;
public final long filesize;
public final FileHash filehash;
public final SubscriberId sender;
public final SubscriberId recipient;
public final String name;

protected RhizomeBundle(int rowNumber,
int _id,
String _token,
String service,
BundleId id,
long version,
long date,
long _inserttime,
SubscriberId _author,
int _fromhere,
long filesize,
FileHash filehash,
SubscriberId sender,
SubscriberId recipient,
String name)
{
this._rowNumber = rowNumber;
this._id = _id;
this._token = _token;
this.service = service;
this.id = id;
this.version = version;
this.date = date;
this._inserttime = _inserttime;
this._author = _author;
this._fromhere = _fromhere;
this.filesize = filesize;
this.filehash = filehash;
this.sender = sender;
this.recipient = recipient;
this.name = name;
}

}
137 changes: 137 additions & 0 deletions java/org/servalproject/servaldna/rhizome/RhizomeBundleList.java
@@ -0,0 +1,137 @@
/**
* Copyright (C) 2014 Serval Project Inc.
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software 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 source code 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 source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

package org.servalproject.servaldna.rhizome;

import org.servalproject.json.JSONInputException;
import org.servalproject.json.JSONTokeniser;
import org.servalproject.json.JSONTableScanner;
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
import org.servalproject.servaldna.ServalDInterfaceException;
import org.servalproject.servaldna.BundleId;
import org.servalproject.servaldna.SubscriberId;
import org.servalproject.servaldna.FileHash;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class RhizomeBundleList {

private ServalDHttpConnectionFactory httpConnector;
private HttpURLConnection httpConnection;
private JSONTokeniser json;
private JSONTableScanner table;
int rowCount;

public RhizomeBundleList(ServalDHttpConnectionFactory connector)
{
this.httpConnector = connector;
this.table = new JSONTableScanner()
.addColumn("_id", Integer.class)
.addColumn(".token", String.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("service", String.class)
.addColumn("id", BundleId.class)
.addColumn("version", Long.class)
.addColumn("date", Long.class)
.addColumn(".inserttime", Long.class)
.addColumn(".author", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn(".fromhere", Integer.class)
.addColumn("filesize", Long.class)
.addColumn("filehash", FileHash.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("sender", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("recipient", SubscriberId.class, JSONTokeniser.Narrow.ALLOW_NULL)
.addColumn("name", String.class);
}

public boolean isConnected()
{
return this.json != null;
}

public void connect() throws IOException, ServalDInterfaceException
{
try {
rowCount = 0;
httpConnection = httpConnector.newServalDHttpConnection("/restful/rhizome/bundlelist.json");
httpConnection.connect();
json = RhizomeCommon.receiveRestfulResponse(httpConnection, HttpURLConnection.HTTP_OK);
json.consume(JSONTokeniser.Token.START_OBJECT);
json.consume("header");
json.consume(JSONTokeniser.Token.COLON);
table.consumeHeaderArray(json);
json.consume(JSONTokeniser.Token.COMMA);
json.consume("rows");
json.consume(JSONTokeniser.Token.COLON);
json.consume(JSONTokeniser.Token.START_ARRAY);
}
catch (JSONInputException e) {
throw new ServalDInterfaceException(e);
}
}

public RhizomeBundle nextBundle() throws ServalDInterfaceException, IOException
{
try {
Object tok = json.nextToken();
if (tok == JSONTokeniser.Token.END_ARRAY) {
json.consume(JSONTokeniser.Token.END_OBJECT);
json.consume(JSONTokeniser.Token.EOF);
return null;
}
if (rowCount != 0)
JSONTokeniser.match(tok, JSONTokeniser.Token.COMMA);
else
json.pushToken(tok);
Map<String,Object> row = table.consumeRowArray(json);
return new RhizomeBundle(
rowCount++,
(int)row.get("_id"),
(String)row.get(".token"),
(String)row.get("service"),
(BundleId)row.get("id"),
(long)row.get("version"),
(long)row.get("date"),
(long)row.get(".inserttime"),
(SubscriberId)row.get(".author"),
(int)row.get(".fromhere"),
(long)row.get("filesize"),
(FileHash)row.get("filehash"),
(SubscriberId)row.get("sender"),
(SubscriberId)row.get("recipient"),
(String)row.get("name"));
}
catch (JSONInputException e) {
throw new ServalDInterfaceException(e);
}
}

public void close() throws IOException
{
httpConnection = null;
if (json != null) {
json.close();
json = null;
}
}

}

0 comments on commit db8ee79

Please sign in to comment.