How is it possible to get a stackoverflowerror using scala parsers in Android?
I was using this code:
val parseEApply: Parser[EApply] =
("EApply" ~> "(" ~> parseExpression) ~ ("," ~> parseListExpression <~ ")") ^^ {
case e ~ l => EApply(e, l)
}
By rewriting it using different parenthesis, I got rid of the error. Can someone explain me why ?
EApply is an expression that can contain other expressions, and a list of expressions.
val parseEApply: Parser[EApply] =
"EApply(" ~> parseExpression ~ ("," ~> parseListExpression <~ ")") ^^ {
case e ~ l => EApply(e, l)
}
So why there might be a recursion error in the first and not in the second?
I was able to partially solve the problem by regrouping parsers in pairs. So instead of:
val parseExpression = p1 | p2 | p3 | p4 | p5 | p6 | p7 | p8
I wrote it with parentheses
val parseExpression = ((p1 | p2) | (p3 | p4)) | ((p5 | p6) | (p7 | p8))
And it worked without complaints.
Related
I partially want to concat a string inside a for loop (inside a while loop). However, when it's concatenating inside the for loop, it's overwriting the past concatenating.
I am quite new to programming, so I don't get why it's working fine outside a for loop and overwriting itself inside of it.
String uitslagtxt;
uitslagtxt = "Datum" + "|" + "Teamnamen" + "|" + "Uitslag" + "|" + "(Ruststand)"+"\n";
for (int i=0; i<1; i++){
uitslagtxt = uitslagtxt.concat(row[1]+"|" +row[2]+"|"+row[3]+"|"+row[4].replace("\"","")+"\n");
out.println("uitslagtxt in for loop: " + uitslagtxt);
}
So instead of giving 4 lines for example (which are all visible in the out.println check, see below),
Datum | Teamnamen | Uitslag | (Ruststand)
1 jun. 2017 | Thuis - Uit | 2 - 2 | (2 - 0)
uitslagtxt in for loop: Datum | Teamnamen | Uitslag | (Ruststand)
1 jun. 2017 | Thuis - Uit | 1 - 1 | (1 - 0)
uitslagtxt in for loop: Datum | Teamnamen | Uitslag | (Ruststand)
1 jun. 2017 | Thuis - Uit | 3 - 3 | (3 - 0)
it's only writing 2. How come?
Datum | Teamnamen | Uitslag | (Ruststand)
1 jun. 2017 | Thuis - Uit | 3 - 3 | (3 - 0)
It's overwriting the string because it is inside a while loop.
You declare the string inside while block, so every time it is repeated the variable is declared again.
Move the string declaration and initialization before starting the while loop.
String uitslagtxt;
uitslagtxt = "Datum" + "|" + "Teamnamen" + "|" + "Uitslag" + "|" + "(Ruststand)"+"\n";
while (condition) {
// your code
}
I am trying to use the and "&&" operator in xml using Android databinding,
android:visibility="#{(bean.currentSpaceId == bean.selectedSpaceId **&&** bean.currentSpaceId > 0)? View.VISIBLE: View.GONE}"
but I got the compilation error:
Error:Execution failed for task ':app:dataBindingProcessLayoutsDevDebug'.
org.xml.sax.SAXParseException; systemId: file:/Users/path/app/build/intermediates/res/merged/dev/debug/layout/fragment_space.xml; lineNumber: 106; columnNumber: 89; The entity name must immediately follow the '&' in the entity reference.
and red highlight error in android studio "unescaped & or non terminated character".
So how should I fix this?
Edit:
found the answer, these character needs to be escaped:
'&' --> '&'
'<' --> '<'
'>' --> '>'
&& should be rendered as &&.
The official data binding guide has examples of comparison operators where these XML entities are used, for example
android:visibility="#{age < 13 ? View.GONE : View.VISIBLE}"
Edit
The example expressions I mentioned in the answer disappeared from the English version of the docs since this answer was written. They do survive in some outdated non-English versions of the docs such as the Spanish version.
Either way, the original answer is still valid, because the use of XML entities in XML is standard in XML and has nothing to do with Android itself.
List of HTML entities
You can not use & or some other HTML entity in XML. So you have to use escaping character.
android:text="#{(1==1 && 2>0) ? `true` : `false`}"
HTML Character entities often used in Android:
+--------+----------------------------+--+--+--+
| Symbol | Equivalent HTML Entity | | | |
+--------+----------------------------+--+--+--+
| > | > | | | |
+--------+----------------------------+--+--+--+
| < | < | | | |
+--------+----------------------------+--+--+--+
| " | ", “ or ” | | | |
+--------+----------------------------+--+--+--+
| ' | ', ‘ or ’ | | | |
+--------+----------------------------+--+--+--+
| } | } | | | |
+--------+----------------------------+--+--+--+
| & | & | | | |
+--------+----------------------------+--+--+--+
| space | | | | |
+--------+----------------------------+--+--+--+
Here is a complete list of HTML entities.
Escaping && in the layout mark-up is a very poor solution. It is better to create a method on the (view)model object:
android:visibility="#{user.adult ? View.VISIBLE : View.GONE}"
public boolean isAdult() {
return age >= 18;
}
The best solution that I could come up with for this problem was introducing a new Bindable method.
Before:
item_recyclerview.xml:
<EditText
...
android:enabled="#{myViewModel.myDataModelClass.lastAddedItem && !myViewModel.myDataModelClass.editTextDisabled}"
/>
MyDataModelClass: (which is being held in my viewmodel)
...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
#Bindable
public boolean isLastAddedItem() {
return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
this.lastAddeditem = lastAddedItem;
notifyPropertyChanged(BR.lastAddedItem);
}
#Bindable
public boolean isEditTextDisabled() {
return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
this.editTextDisabled = editTextDisabled;
notifyPropertyChanged(BR.editTextDisabled);
}
After:
item_recyclerview.xml:
<EditText
...
android:enabled="#{myViewModel.myDataModelClass.enableEditing}"
/>
MyDataModelClass: (which is being held in my viewmodel)
...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
#Bindable
public boolean isLastAddedItem() {
return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
this.lastAddeditem = lastAddedItem;
notifyPropertyChanged(BR.lastAddedItem);
notifyPropertyChanged(BR.isEnableEditing);
}
#Bindable
public boolean isEditTextDisabled() {
return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
this.editTextDisabled = editTextDisabled;
notifyPropertyChanged(BR.editTextDisabled);
notifyPropertyChanged(BR.isEnableEditing);
}
#Bindable
public boolean isEnableEditing() {
return isLastAddedItem() && !isEditTextDisabled();
}
Try 'compareTo' method in the XML like
android:visibility=${viewModel.intValue.compareTo(0) == -1 ? View.GONE : View.VISIBLE}"
suppose I write some very simple tests in an android app working on simulator (marshmallow, OSX 64 bits) whith logcat output:
Log.i("test","long int = "+17301768L);
Log.i("test","long int = "+(1<<3 | 1<<8 | 1<<19 | 1<<24));
Log.i("test","long int = "+ 8607236360L);
Log.i("test","long int = "+(1<<3 | 1<<8 | 1<<19 | 1<<24 | 1<<33));
…logcat prints:
long int = 17301768
long int = 17301768
long int = 8607236360
long int = 17301770
Obviously, last line is not correct : it should be the same as the third line.
Why ?
And how can I make it working as expected ?
By default all numbers in Java are of type int. Therefore the numbers you create using the binary operations are int values, too:
(1<<3 | 1<<8 | 1<<19 | 1<<24 | 1<<33)
1<<33 = 2
1L<<33 = 8589934592
int values are limited to 31 bits + 1 bit for indicating positive/negative value.
Therefore setting the 34th bit does not change anything.
To make it work you have to explicitly use long values for all bits that does not fit into an int. You can do that by adding "L" for long to the number.
System.out.println((1<<3 | 1<<8 | 1<<19 | 1<<24 | 1L <<33)); // 8607236360
I have 3 tables, USER, ENTRY (for entered products, not necessary to create a PRODUCT table), and USER_COLLECTION, which is a table inbetween USER and ENTRY, because an entry can have multiple users.
Basically:
User = USERID | USER_NAME
Entry = ENTRYID | ENTRY_NAME | ENTRYPRICE | ENTRY_DATE
Collection = COLLECTIONID | ENTRYID | USERID
I have a table with users that persist throughout the project. They can create entries (which is usually some kind of product with a price) and they can link multiple users to a certain entry (which can be selected from a list, hence the users persist throughout the project).
So for instance, my tables look like this:
User
--------------------------
user_id | user_name
--------------------------
1 | 'FOO'
2 | 'BAR'
3 | 'FOOBAR'
ENTRY
-----------------------------------------------------------------------
entryid | entry_name | entry_price | entry_date
-----------------------------------------------------------------------
0 | 'Banana' | 2.50 | 12/12/2012
COLLECTION
---------------------------------------
collectionid | entryid | userid
----------------------------------------
0 | 1 | 1
1 | 1 | 2
2 | 1 | 3
I have a Banana, with a price of 2.50 and 3 users linked to it, Foo, Bar and Foobar.
Now, I want to use this in my app and get the data; except I don't know where to start. I tried selecting the entry data, using that id to loop through the collection data, but that would mean I have two cursors open and it wouldn't work. Tried creating a join but I couldn't really make a good one, mainly because:
JOIN
---------------------------------------
collectionid | entryname | username
----------------------------------------
0 | Banana | FOO
1 | Banana | BAR
2 | Banana | FOOBAR
I can't iterate through this, because I would create multiple of the same entry objects in my Android code...
Hope I'm being clear on this.
if (cursor2.moveToFirst()) {
do {
Item i = new Item(<GET STUFF FROM CURSOR>);
i.addUser(new Person(<GET STUFF FROM CURSOR>)));
Log.d("TAG", i.getUsersPaying().size() + "");
} while (cursor2.moveToNext());
}
If I use this, I create mulitple instances of Item i. They'll all be Banana, whilst I should only have 1 item Banana, with multiple users added to it.
First, you might want to consider returning the IDs from your tables in your join query. Things would be a little easier if you returned the entryid column.
Just make a Map<Integer, Item> to store items that you have seen already in your loop. As you examine each cursor, check the map to see if you already have an instance. If you don't, just make a new one and insert it.
Let's assume your query results are:
JOIN
----------------------------------------------------
collectionid | entryname | entryname | username
----------------------------------------------------
0 | 1 | Banana | FOO
1 | 1 | Banana | BAR
2 | 1 | Banana | FOOBAR
2 | 2 | Apple | FOOBAR
You can modify your code as follows:
Map<Integer, Item> items = new HashMap<Integer, Item>();
if (cursor2.moveToFirst()) {
do {
int itemId = cursor2.getInt(1);
Item i;
if (items.containsKey(itemId))
i = items.get(itemId);
else
{
i = new Item(<GET STUFF FROM CURSOR>);
items.put(itemId, i);
}
i.addUser(new Person(<GET STUFF FROM CURSOR>)));
Log.d("TAG", i.getUsersPaying().size() + "");
} while (cursor2.moveToNext());
}
You need to maintain a dictionnary of your entities which are already loaded in memory. For instance in a background fragment which would be retained.
Basically you would do:
Item i = cacheFragment.createOrGetEntry( cursor.getLong( ENTRY_ID_COLUMN_INDEX ) );
Person p = cacheFragment.createOrGetPerson( cursor.getLong( PERSON_ID_COLUMN_INDEX ) );
Of course, your query must also return the IDs of all the rows you need (entryId and personId). But a join query is the way to do it efficiently, so keep what you did about that and just add the two missing ID columns.
a createOrGetPerson method would look like:
public Person createOrGetPerson(long id) {
Entry<Long, Person> p = personDictionnary.get( id ); // can be a HashMap or even better, a SparseArray
if (p==null) {
p = new Person(id);
personDictionnary.put(p); // Remember it for next time
}
return p;
}
You should also have a look at data persistence frameworks or ORM frameworks which are made to deal with this kind of problem (e.g. Hibernate, even though I don't know if that is working with Android).
I am building an android application which queries a database for a bus number, and bus departure time.
The tables are thus -
Table 1: Route - _id, routenumber
Table 2: Routetimedetails - _id, routetime, routeid
My current query is this
select routenumber, route._id, routetime from route, routetimedata where route._id = 2 and routeid = route._id
and the result shows up like this
>
routenumber | route._id | routetime
-------------------------------------
BIAS10 | 2 | 0945
BIAS10 | 2 | 1810
BIAS10 | 2 | 1945
BIAS10 | 2 | 0710
is there a way in sqlite3 to show the result in a single column like this -
BIAS10 | 2 | 0710, 0945, 1810, 1945
Thanks
Mukul
I find that the Group_Concat() function does this easily
select routenumber, route._id, Group_concat(routetime) from route, routetimedata where route._id = 2 and routeid = route._id