I'm trying to work on the sample GAE / Android app. There is Place Entity.
In generated PlaceEndpoint class there is a method:
#ApiMethod(name = "listGame")
public CollectionResponse<Place> listPlace(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<Game> execute = null;
try {
mgr = getEntityManager();
Query query = mgr.createQuery("select from Place as Place");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<Game>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (Game obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<Game> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
As I understand cursor and limit all optional params.
However I can't figure out how to pass them using Placeednpoint class on the client side:
Placeendpoint.Builder builder = new Placeendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), null);
builder = CloudEndpointUtils.updateBuilder(builder);
Placeendpoint endpoint = builder.build();
try {
CollectionResponsePlace placesResponse = endpoint.listPlace().execute();
} catch (Exception e) {
e.printStackTrace();
Normally, when params are not nullable I would pass them in endpoint.listPlace() method. But when params are nullable, client side app doesn't see alternative constructor, that would accept params.
How am I supposed to pass them then?
For passing parameters from client side while sending a query request through cloud endpoints, you need to add provision for setting parameters. To send the required parameter from android , the class where you would define the REST Path and method type, should include an option to the set cursor and limit. For example for the String cursorstring :
#com.google.api.client.util.Key
private String cursorstring;
public String getCursorstring() {
return cursorstring;
}
public ListPlace setCursorstring(String cursorstring) {
this.cursorstring = cursorstring;
return this;
}
Finally while calling the endpoint method from your android code, you should pass a value using the setCursorstring, which will be something like:
CollectionResponsePlace placesResponse = endpoint.listPlace().setCursorstring("yourcursorstring").execute();
There is an additional way. You can simply set your nullable value 'cursor' it like this:
CollectionResponsePlace placesResponse =
endpoint.listPlace().set("cursor", "Your Cursorstring").execute();
Where you can
Faced the same issue but backend developed using Java.
The solution provided by Tony m worked like a charm.
Simply had to adapt how the method is called on Android and it worked.
Related
I am looking for the way how to chain multiple but same API requests with different parameters. So far my method looks like this:
#Override
public Observable<List<Entity>> getResult(Integer from, Integer to, Integer limit) {
MyService myService = restClient.getMyService();
if (null != from && null != to) {
Observable<List<Response>> responseObservable = myService.get(from, limit);
for (int i = from + 1; i <= to; i++) {
responseObservable = Observable.concat(responseObservable, myService.get(i, limit));
}
return responseObservable.map(mapResponseToEntity);
} else {
int fromParameter = null == from ? DEFAULT_FROM : from;
return myService.get(fromParameter, limit).map(mapResponseToEntity);
}
}
I expected that concat method combines Oservables data into one stream and returns combined Observable but I am getting only the last one calls result. However, in logcat I can see that correct number of calls to API was made.
Try using Observable.merge() and Observable.toList() as follows:
List<Observable<Response>> observables = new ArrayList();
// add observables to the list here...
Subscription subscription = Observable.merge(observables)
.toList()
.single()
.subscribe(...); // subscribe to List<Response>
This question already has answers here:
How to remove duplicates from a list?
(15 answers)
Closed 8 years ago.
I want to remove duplicates from ArrayList of type Alerts where Alerts is a class.
Class Alerts -
public class Alerts implements Parcelable {
String date = null;
String alertType = null;
String discription = null;
public Alerts() {
}
public Alerts(String date, String alertType, String discription) {
super();
this.date = date;
this.alertType = alertType;
this.discription = discription;
}
}
Here is how I added the elements -
ArrayList<Alerts> alert = new ArrayList<Alerts>();
Alerts obAlerts = new Alerts();
obAlerts = new Alerts();
obAlerts.date = Date1.toString();
obAlerts.alertType = "Alert Type 1";
obAlerts.discription = "Some Text";
alert.add(obAlerts);
obAlerts = new Alerts();
obAlerts.date = Date2.toString();
obAlerts.alertType = "Alert Type 1";
obAlerts.discription = "Some Text";
alert.add(obAlerts);
What I want to remove from them-
I want all alerts which have unique obAlerts.date and obAlerts.alertType. In other words, remove duplicate obAlerts.date and obAlerts.alertType alerts.
I tried this -
Alerts temp1, temp2;
String macTemp1, macTemp2, macDate1, macDate2;
for(int i=0;i<alert.size();i++)
{
temp1 = alert.get(i);
macTemp1=temp1.alertType.trim();
macDate1 = temp1.date.trim();
for(int j=i+1;j<alert.size();j++)
{
temp2 = alert.get(j);
macTemp2=temp2.alertType.trim();
macDate2 = temp2.date.trim();
if (macTemp2.equals(macTemp1) && macDate1.equals(macDate2))
{
alert.remove(temp2);
}
}
}
I also tried-
HashSet<Alerts> hs = new HashSet<Alerts>();
hs.addAll(obAlerts);
obAlerts.clear();
obAlerts.addAll(hs);
You need to specify yourself how the class decides equality by overriding a pair of methods:
public class Alert {
String date;
String alertType;
#Override
public boolean equals(Object o) {
if (this == 0) {
return true;
}
if ((o == null) || (!(o instanceof Alert)))
return false;
}
Alert alert = (Alert) o;
return this.date.equals(alert.date)
&& this.alertType.equals(alert.alertType);
}
#Override
public int hashCode() {
int dateHash;
int typeHash;
if (date == null) {
dateHash = super.hashCode();
} else {
dateHash = this.date.hashCode();
}
if (alertType == null) {
typeHash = super.hashCode();
} else {
typeHash = this.alertType.hashCode();
}
return dateHash + typeHash;
}
}
You can then loop through your ArrayList and add elements if they aren't already there as Collections.contains() makes use of these methods.
public List<Alert> getUniqueList(List<Alert> alertList) {
List<Alert> uniqueAlerts = new ArrayList<Alert>();
for (Alert alert : alertList) {
if (!uniqueAlerts.contains(alert)) {
uniqueAlerts.add(alert);
}
}
return uniqueAlerts;
}
However, after saying all that, you may want to revisit your design to use a Set or one of its family that doesn't allow duplicate elements. Depends on your project. Here's a comparison of Collections types
You could use a Set<>. By nature, Sets do no include duplicates. You just need to make sure that you have a proper hashCode() and equals() methods.
In your Alerts class, override the hashCode and equals methods to be dependent on the values of the fields you want to be primary keys. Afterwards, you can use a HashSet to store already seen instances while iterating over the ArrayList. When you find an instance which is not in the HashSet, add it to the HashSet, else remove it from the ArrayList. To make your life easier, you could switch to a HashSet altogether and be done with duplicates per se.
Beware that for overriding hashCode and equals, some constraints apply.
This thread has some helpful pointers on how to write good hashCode functions. An important lesson is that simply adding together all dependent fields' hashcodes is not sufficient because then swapping values between fields will lead to identical hashCodes which might not be desirable (compare swapping first name and last name). Instead, some sort of shifting-operation is usually done before adding the next atomic hash, eg. multiplying with a prime.
First store your datas in array then split at as one by one string,, till the length of that data execute arry and compare with acyual data by if condition and retun it,,
HashSet<String> hs = new HashSet<String>();
for(int i=0;i<alert.size();i++)
{
hs.add(alert.get(i).date + ","+ alert.get(i).alertType;
}
alert.clear();
String alertAll[] = null;
for (String s : hs) {
alertAll = s.split(",");
obAlerts = new Alerts();
obAlerts.date = alertAll[0];
obAlerts.alertType = alertAll[1];
alert.add(obAlerts);
}
Ive tried a thousand things. As of right now the only way for me to query anything is to get the entire list and look through it that way! which takes way to much time. How can I query something in google app engine, for example pull only the entities that have > 100 votes for example.
Tried to user cursor but not sure how it works. I know it can use a cursor but how do I set it up with google app engine since my database isnt in my app per say??
Ive tried... but this dose not work at all..
Cursor cursor = ("select * from Votes WHERE Votes >" + 250 , null);
quotes endpoint.listquotes().setCursor(cursor).execute();
and
String query = ("select * from Votes WHERE Votes >= 40");
quotes endpoint.listquotes().setCursor(query).execute();
Im following the tic-tac-toe example https://github.com/GoogleCloudPlatform/appengine-endpoints-tictactoe-java and https://developers.google.com/eclipse/docs/endpoints-addentities In the example I just switched notes for quotes.
Heres my current code for example on how im getting the entities.
protected CollectionResponseQuotes doInBackground(Context... contexts) {
Quotesendpoint.Builder endpointBuilder = new Quotesendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) { }
});
Quotesendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
try {
quotes = endpoint.listquotes().execute();
for (Quotes quote : quotes.getItems()) {
if (quote.getVotes() > 3) {
quoteList.add(quote);
}
}
Here is the code that Google generated in the app engine for me when I created the endpoint. It looks like it will query somehow but I cant figure it out. They are two different projects.
#Api(name = "quotesendpoint", namespace = #ApiNamespace(ownerDomain = "projectquotes.com" ownerName = "projectquotes.com", packagePath = ""))
public class quotesEndpoint {
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* #return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listquotes")
public CollectionResponse<quotes> listquotes(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<quotes> execute = null;
try {
mgr = getEntityManager();
Query query = mgr.createQuery("select from quotes as quotes");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<quotes>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (quotes obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<quotes> builder().setItems(execute)
.setNextPageToken(cursorString).build();
In Google App Engine you need to set up a servlet to query the database for you and then return the results in JSON, see here for more information:
https://developers.google.com/appengine/docs/java/datastore/queries
https://github.com/octo-online/robospice
https://developers.google.com/appengine/docs/java/#Requests_and_Servlets
https://code.google.com/p/google-gson/
You would end up querying using http:// your-url/query? + query string
EDIT:
Preview!
This is a Preview release of Google Cloud Endpoints. As a result, the
API is subject to change and the service itself is currently not
covered by any SLA or deprecation policy. These characteristics will
be evaluated as the API and service moves towards General
Availability, but developers should take this into consideration when
using the Preview release of Google Cloud Endpoints.
Most likely the cursor function is still in development. But I'm also unsure why you would want to use Cursors, as Collections are so much easier to work with... Wouldn't you prefer to do what's below then the awful code above? :)
ScoreCollection scores = service.scores().list().execute();
Update your list method to take in a filter attribute
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listZeppaUserInfo")
public CollectionResponse<ZeppaUserInfo> listZeppaUserInfo(
#Nullable #Named("filter") String filterString,
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
PersistenceManager mgr = null;
Cursor cursor = null;
List<ZeppaUserInfo> execute = null;
try {
mgr = getPersistenceManager();
Query query = mgr.newQuery(ZeppaUserInfo.class);
if (isWebSafe(cursorString)) {
cursor = Cursor.fromWebSafeString(cursorString);
HashMap<String, Object> extensionMap = new HashMap<String, Object>();
extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
query.setExtensions(extensionMap);
} else if (isWebSafe(filterString)){
// query has a filter
query.setFilter(filterString);
}
if (limit != null) {
query.setRange(0, limit);
}
execute = (List<ZeppaUserInfo>) query.execute();
cursor = JDOCursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and
// accomodate
// for lazy fetch.
for (ZeppaUserInfo obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<ZeppaUserInfo> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
I have a SQLite table (on Android) that has numerous fields, but certain fields are repeated/denormalized. I would like to select a distinct set of this data and use them as actual objects.
Example
books table
title summary author
Little Johnny A funny kid Johnny Himself
Big Johnny A funny adult Johnny Himself
I would like to extract one author from this list ("Johnny Himself") and would expect I should be able to do this with ORMLite instead of manually with Java.
I would like to select a distinct set of this data and use them as actual objects.
ORMLite supports a distinct() method on the QueryBuilder that should do what you want. So your code would look something like:
List<Book> results = booksDao.queryBuilder()
.distinct().selectColumns("author").query();
In this case, the resulting Book objects would only have the author field set and not the id field or anything else. If you just wanted the author names instead of objects then you could do:
GenericRawResults<String[]> rawResults =
booksDao.queryRaw("SELECT DISTINCT author FROM books");
for (String[] resultColumns : rawResults) {
String author = resultColumns[0];
...
}
This is my application code
public class DbHelper<T> {
private Class<T> c;
private DatabaseHelper db;
public DbHelper(Class<T> c) {
this.c = c;
db = DatabaseHelper.getInstance();
}
This is a good idea
public List<T> queryForBuilderDistinct(int offset, int limit, String ColumnsName,
String orderName, boolean isAsc) {
try {
Dao<T, Integer> dao = db.getDao(c);
QueryBuilder<T, Integer> queryBuilder = dao.queryBuilder();
if (offset != 0) {
queryBuilder.offset((long) offset);
}
if (limit != 0) {
queryBuilder.limit((long) limit);
}
if (orderName != null) {
queryBuilder.orderBy(orderName, isAsc);
}
queryBuilder.distinct().selectColumns(ColumnsName);
return dao.query(queryBuilder.prepare());
} catch (SQLException e) {
LogUtil.e(TAG, "queryForBuilderDistinct", e);
}
return new ArrayList<T>();
}
I have created complied statement given below. Now my question is how to get resultset of the query.
Here is my code:
DataBaseHelper dbHelper=new DataBaseHelper(context);
dbHelper.createDataBase();
dbHelper.openDataBase();
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement st=db.compileStatement("select taskid from task where taskdate=?");
st.bindString(1,"2011/09/05");
st.execute();
This works without any error. But I want the result set of the given query. Please help..
The result set isn't available, at least for now, in sqlite. It all depends on exactly what information you want from the ResultSet or ResultSetMetaData, etc, but there are other means of obtaining almost the same information.
You can get detailed information about the columns in a table with the following, used as if it were a SELECT, and the information about the columns will be presented:
pragma table_info(myTable) ;
See http://www.sqlite.org/pragma.html#pragma_table_info for more information.
If you want the information concerning a specific SELECT, you can get information from the resulting Cursor. See http://developer.android.com/reference/android/database/Cursor.html
For example, if you want the type of data for a column, you can use the getType() method in the newer versions of Android, or use a series of "get" functions to determine at least what type is readable, with this horrible code:
Cursor curs = db.rawQuery(sqlStr, null);
int numberOfColumns = curs.getColumnCount();
String []colNames = new String[numberOfColumns];
String []colTypes = new String[numberOfColumns];
for(int iCol=1; iCol<=numberOfColumns; iCol++) {
colNames[iCol-1] = curs.getColumnName(iCol-1);
colTypes[iCol-1] = null; //curs.getType(iCol);
}
while(curs.moveToNext()) {
// this code assumes that the first row has the same data types
// as the rest of the rows
for(int iCol=1; iCol<=numberOfColumns; iCol++) {
String colName = colNames[iCol-1];
String colType = colTypes[iCol-1];
if(colType==null) {
// determine column type
try {
curs.getString(iCol-1);
colType = colTypes[iCol-1] = "text";
} catch (Exception ignore) {
try {
curs.getLong(iCol-1);
colType = colTypes[iCol-1] = "integer";
} catch (Exception ignore1) {
try {
curs.getFloat(iCol-1);
colType = colTypes[iCol-1] = "real";
} catch (Exception ignore2) {
try {
curs.getBlob(iCol-1);
colType = colTypes[iCol-1] = "blob";
} catch (Exception ignore3) {
colType = colTypes[iCol-1] = "other";
}
}
}
}
}
if("text".equals(colType)) {
... curs.getString(iCol-1);
} else
if("real".equals(colType)) {
... curs.getDouble(iCol-1);
} else
if("integer".equals(colType)) {
... curs.getInt(iCol-1);
} else { // unknown type
... colType+"-"+curs.getString(iCol-1);
}
}
}
Other information is available in a similar manner, depending on your need.