javacc skip comments but need to keep useful comments - java

I need to use javaCC to parse a data file like:
//This is comment to skip
//This is also comment to skip
//student Table
Begin:
header:( 1 //name
2 //age ) { "John" 21 } { "Jack" "22" }
#End
//The following is teacher table, this line is also comment to skip
//Teacher Table
Begin:
header:( 1 //name
2 //age 3 //class ) { "Eric" 31 "English" } { "Jasph" "32" "History" }
#End
Here I need to fetch data from "student" and "teacher" tables, there are also some other tables formatted like above. Data exported from "student" table is:
Table Name: student
name age
John 21
Jack 22
That is I need to skip comments like: "//This is also comment to skip", but need to keep the tokens like: "//student Table", "//Teacher Table", "//name", "//age" etc. How to write such SKIP expression? Thanks.

Slightly late, but you might be looking at it wrong.
Surely in your case, // isn't really a comment, it is part of the syntax you are parsing. It just happens that sometimes the bit following // is irrelevant.
I would parse the comments and decide which ones to discard in your Java code.

Related

Spring data mongodb sort by a substring of a String field if it contains a specific character

I would like to make a query to the database to return a list of data, ordered by name.
Some names fields contains a code like this : [code] name.
so i want to sort data only by name and neglect the code if it exist.
Exemple of data :
[CODE1] John
Xavi
Arnold
[CODE 2] Ben
the order must be => Arnold, Ben, John, Xavi.
It is possible?
my code now :
query.with(Sort.by(Sort.Direction.DESC, "name")).with(pageable);

FOREACH in cypher - neo4j

I am very new to CYPHER QUERY LANGUAGE AND i am working on relationships between nodes.
I have a CSV file of table containing multiple columns and 1000 rows.
Template of my table is :
cdrType ANUMBER BNUMBER DUARTION
2 123 456 10
2 890 456 5
2 123 666 2
2 123 709 7
2 345 789 20
I have used these commands to create nodes and property keys.
LOAD CSV WITH HEADERS FROM "file:///2.csv" AS ROW
CREATE (:ANUMBER {aNumber:ROW.aNumber} ),
CREATE (:BNUMBER {bNumber:ROW.bNumber} )
Now I need to create relation between all rows in the table and I think FOREACH loop is best in my case. I created this query but it gives me an error. Query is :
MATCH (a:ANUMBER),(b:BNUMBER)
FOREACH(i in RANGE(0, length(ANUMBER)) |
CREATE UNIQUE (ANUMBER[i])-[s:CALLED]->(BNUMBER[i]))
and the error is :
Invalid input '[': expected an identifier character, whitespace,
NodeLabel, a property map, ')' or a relationship pattern (line 3,
column 29 (offset: 100)) " CREATE UNIQUE
(a:ANUMBER[i])-[s:CALLED]->(b:BNUMBER[i]))"
I need relation for every row. like in my case. 123 - called -> 456 , 890 - called -> 456. So I need visual representation of this calling data that which number called which one. For this I need to create relation between all rows.
any one have idea how to solve this ?
What about :
LOAD CSV WITH HEADERS FROM "file:///2.csv" AS ROW
CREATE (a:ANUMBER {aNumber:ROW.aNumber} )
CREATE (b:BNUMBER {bNumber:ROW.bNumber} )
MERGE (a)-[:CALLED]->(b);
It's not more complex than that i.m.o.
Hope this helps !
Regards,
Tom

How to count distinct values of a reference collection in mongo

Having a list of books that points to a list of authors, I want to display a tree, having in each node the author name and the number of books he wrote. Initially, I have embedded the authors[] array directly into books collection, and this worked like a charm, using the magic of aggregation framework. However, later on, I realise that it would be nice to have some additional information attached to each author (e.g. it's picture, biographical data, birth date, etc). For the first solution, this is bad because:
it duplicates the data (not a big deal, and yes, I know that mongo's purpose is to encapsulate full objects, but let's ignore that for now);
whenever an additional property is created or updated on the old records won't benefit from this change, unless I specifically query for some unique old property and update all the book authors with the new/updated values.
The next thing was to use the second collection, called authors, and each books document is referencing a list of author ids, like this:
{
"_id" : ObjectId("58ed2a254374473fced950c1"),
"authors" : [
"58ed2a254d74s73fced950c1",
"58ed2a234374473fce3950c1"
],
"title" : "Book title"
....
}
For getting the author details, I have two options:
make an additional query to get the data from the author collection;
use DBRefs.
Questions:
Using DBRefs automatically loads the authors data into the book object, similar to what JPA #MannyToOne does for instance?
Is it possible to get the number of written books for each author, without having to query for each author's book count? When the authors were embedded, I was able to aggregate the distinct author name's and also the number of book documents that he was present on. Is such query possible between two collections?
What would be your recommendation for implementing this behaviour? (I am using Spring Data)
You can try the below query in the spring mongo application.
UnwindOperation unwindAuthorIds = Aggregation.unwind("authorsIds", true);
LookupOperation lookupAuthor = Aggregation.lookup("authors_collection", "authorsIds", "_id", "ref");
UnwindOperation unwindRefs = Aggregation.unwind("ref", true);
GroupOperation groupByAuthor = Aggregation.group("ref.authorName").count().as("count");
Aggregation aggregation = Aggregation.newAggregation(unwindAuthorIds, lookupAuthor, unwindRefs, groupByAuthor);
List<BasicDBObject> results = mongoOperations.aggregate(aggregation, "book_collection", BasicDBObject.class).getMappedResults();
Following #Veeram's suggestion, I was able to write this query:
db.book_collection.aggregate([
{
$unwind: "$authorsIds"
},
{
$lookup: {
from: "authors_collection",
localField: "authorsIds",
foreignField: "_id",
as: "ref"
}
},
{$group: {_id: "$ref.authorName", count: {$sum: 1}}}
])
which returns something like this:
{
"_id" : [
"Paulo Coelho"
],
"count" : 1
}
/* 2 */
{
"_id" : [
"Jules Verne"
],
"count" : 2
}
This is exactly what I needed, and it sounds about right. I only need to do an additional query now to get the books with no author set.

How to use distinct/aggregate to get all fields that match several queries

I just learned how to use distinct.
What I do is create a BasicDBObject, put as query parameter to distinct what I want to be equal, and as field parameter what I want returned.
Now I want to do something similar, but with several queries. That meaning, I want the query to match several keys of the document (id and date have to be the same as the input I get), and return what sessions match that in the collection.
I tried doing something similar to find, but for distinct, where you add with append() or put() more fields to the query parameter.
This syntax does not seem to work and I found no one using similar code, so I guess it's not possible.
I've found the aggregate() method, but it seems to be used to match several FIELDS, not queries. Explanation with code:
array.put(coll.distinct(field, query));
I want that query parameter to have several keys, so that all fields match my input, and I find unique values of field that match both (or as many) keys in query.
Thanks in advance!
Edit:
Basics: MongoDB 3.2.2
Data manipulation:
"Session" : "value1", "car" : "carNumber", "date" : "20130321"
I have a very large collection with a number of documents that have, among other keys, this ones. I want, given a car and a number, get every UNIQUE session value, and return it as a json (for which, so far, I put the values into an array, and transform into json).
driver/framework specific question: I do not know to query this in mongodb shell. I know to use distinct, but not aggregators.
There are multiple parts in your question. I would like to answer the last part which is highlighted in bold. The solution is written in Java as the thread is tagged as Java.
The below code would give you the distinct session values for a car and car number. You can change the filter accordingly for your requirement.
The below code satisfies the basic distinct concept for your requirement. I assume that you can add code to result set into JSON (you can use Jackson or Gson libs for generating JSON).
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
public class MongoReadDistinct {
public static void main(String[] args) {
MongoClient client = new MongoClient();
MongoDatabase database = client.getDatabase("cars");
MongoCursor<String> mongoCursorIds = database
.getCollection("sessions").distinct("Session",
Filters.and(Filters.eq("car", "Nisson_Note"), Filters.eq("carnumber", 123)), String.class)
.iterator();
while (mongoCursorIds.hasNext()) {
System.out.println(mongoCursorIds.next());
//You can convert the result to JSON
}
}
}
Sample Data:-
/* 1 */
{
"_id" : ObjectId("576a6860d317ab85059c76d4"),
"Session" : "value1",
"car" : "Nisson_Note",
"carnumber" : 123,
"date" : "20130321"
}
/* 2 */
{
"_id" : ObjectId("576a6896d317ab85059c76d5"),
"Session" : "value2",
"car" : "Nisson_Note",
"carnumber" : 123,
"date" : "20130321"
}
/* 3 */
{
"_id" : ObjectId("576a68b4d317ab85059c76d6"),
"Session" : "value2",
"car" : "Nisson_Note",
"carnumber" : 123,
"date" : "20140321"
}
Output:-
value1
value2
Well, to answer my own question, it is actually possible to have several queries in distinct method, it can be done both in mongodb shell and in java driver (unfortunately I did not get the other answer to work, not that is wrong, I just didn't manage).
So for mongodb shell (I include it because I didn't know to do this, either, which was part of the problem):
db.colectionLocalCC.distinct("Session", {date: "20130303", Car: "55"})
And for mongodb:
BasicDBObject query = new BasicDBObject();
query.put("date", date);
query.put("car",car);
String fields = "Session";
array.put(coll.distinct(fields, query));

updating an excel file with apache metamodel

I'm trying to incorporate Apache MetaModel into a project and keep running into a weird problem. I update an Excel spreadsheet row in code. The code finds the right row, deletes it, then appends the row (with my update) to the bottom of the spreadsheet. I'd like the update to happen in-place, with the same data staying in the same row. I thought it was something I was doing wrong, then set up a stupid simple project to duplicate the behavior. Unfortunately, the problem remains.
Here's the xlsx file:
Name Address City State Zip
Bob 123 Main St. Norman OK 11111
Fred 989 Elm Street Chicago IL 22222
Mary 555 First Street San Francisco CA 33333
Now, I want to update Bob's Zip to "None".
package MMTest;
import java.io.File;
import org.apache.metamodel.UpdateableDataContext;
import org.apache.metamodel.excel.ExcelDataContext;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.schema.Schema;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.update.Update;
public class MMTest {
public static void main(String[] args) {
UpdateableDataContext excel = new ExcelDataContext(new File("C:/test/test.xlsx"));
Schema schema = excel.getDefaultSchema();
Table[] tables = schema.getTables();
assert tables.length == 1;
Table table = schema.getTables()[0];
Column Name = table.getColumnByName("Name");
Column Zip = table.getColumnByName("Zip");
excel.executeUpdate(new Update(table).where(Name).eq("Bob").value(Zip, "None"));
}
}
Pretty simple right? Nope.
This is the result:
Name Address City State Zip
<blank line>
Fred 989 Elm Street Chicago IL 22222
Mary 555 First Street San Francisco CA 33333
Bob 123 Main St. Norman OK None
Am I missing something simple? The documentation is pretty sparse, but I've read everything the internet has to offer on this package. I appreciate your time.
Late to the party, but I've recently bumped into this issue and haven't spotted an answer elsewhere yet. The actual deleting takes place in ExcelDeleteBuilder.java
If you aren't concerned about maintaining row order, you could change
for (Row row : rowsToDelete) {
sheet.removeRow(row);
}
to
for (Row row : rowsToDelete) {
int rowNum = row.getRowNum() + 1;
sheet.removeRow(row);
sheet.shiftRows(rowNum, sheet.getLastRowNum(), -1);
}
See Apache POI docs for a better understanding of shiftRows().
As Adi pointed out, you'll still end up with the "updated" row being moved to the bottom, but in my use case the empty row is successfully removed.
N.B. I'm working from Apache Metamodel 4.5.4
You are not missing anything. The ExcelDataContext is not providing it's own update behavior. It is defaulting to use apache meta-model's default store agnostic implementation for updating the data. That implementation of UpdateCallback uses DeleteAndInsertCallback which is causing the behavior you are observing. It picks the row to be updated, updates it with a new value in memory, deletes the original row and inserts the updated row(which ends up in the bottom which is ExcelDataContext behavior).
You can open an issue at https://issues.apache.org/jira/browse/METAMODEL
Attach your sample code and data.
Best would be a failing unit test in
https://git-wip-us.apache.org/repos/asf/metamodel.git

Categories