How do I “for … order by” in Saxon on Java - saxon

This is a follow on to this question.
I make the call:
XQueryCompiler compiler = processor.newXQueryCompiler();
// 21 of the following
xPath.declareNamespace(prefix, uri);
xPath.compile("for $n in '/def:System/def:Securities[def:AssetType != 50]' order by $n/'def:RiskLevel' return $n");
XQueryEvaluator selector = exe.load();
selector.setContextItem(xmlDocument);
// exception thrown on this:
selector.evaluate();
And I get:
net.sf.saxon.s9api.SaxonApiException: Required item type of first operand of '/' is node(); supplied value has item type xs:string
I'm guessing the '/def:System/def:Securities[def:AssetType != 50]' needs to be a node - how do I do that? And also, will making it a node then reduce it to one node rather than returning all nodes that match the query?
And this query can be complex as "node/node[#attr = '5]/node/not[node = 'dave']/node/#atr"
Update: With a query of "for $n in /def:System/def:Securities[def:AssetType != 50] order by $n/'def:RiskLevel, def:SecurityDesc' return $n" I get the same exception.

Those single quotes in the query are spurious. You're binding $n to the string '/def:System/def:Securities[def:AssetType != 50]', and the error is saying you can't use $n/xxx when $n is a string.

Related

Cosmos DB stored procedure: I can query the DB, but when I try to upsert I get a 'not same partition' error

I understand that stored procedures run in the scope of a single partition key.
It is also possible to do operations that change data, not just read it.
ID must be string, so I must roll my own autoincrementer for a separate property to use in documents.
I am trying to make a simple autoincrement number generator that runs in a single stored procedure.
I am partitioning data mimicking a file tree, using forward slashes to separate+concatenate significant bits that make my partition names. Like so:
/sometype/foo/bar/
/sometype/ids/
The first item is always the document type, and every document type will have a 'ids' sub-partition.
Instead of holding documents, the /sometype/ids/ partition will hold and reserve all numerical ids that have been created for this document type, for autoincrement purposes.
this satisfies uniqueness within a partition, stored procedure execution scope, and unique document count within a document type, which is good for my purposes.
I got stumped in a stored procedure where I want to get a specified id, or create it if it does not exist.
I can query my partition with the stored procedure, but the upsert throws an error, using the same partition key.
I designed my database with "pkey" as the name of the property that will holds my partition keys.
Here is the code:
//this stored procedure is always called from a partition of type /<sometype>/ids/ , where <sometype> os one of my document types.
//the /sometype/ids/ is a partition to reserve unique numerical ids, as Cosmos DB does not have a numerical increment out of the box, I am creating a facility for that.
//the actual documents of /sometype/ will be subpartitioned as well for performance.
function getId(opkey, n, id) {
// gets the requested number if available, or next one.
//opkey: string - a partition key of cosmos db of the object that is going to consume the generated ID, if known. must start with /<sometype>/ which is the same that is being used to call this SP
//n: integer - a numerical number for the autoincrement
//id = '' : string - a uuid of the document that is using this id, if known
if (opkey === undefined) throw new Error('opkey cannot be null. must be a string. must be a valid partition key on Cosmos DB.');
n = (n === undefined || n === null)?0:n;
id = (id === undefined || id === null)?'':id;
var collection = getContext().getCollection();
//make opkey parameter into an array
var split_pkey = opkey.split('/');
//recreate the pkey /<sometype>/ids/ because I can't find a reference to this string inside the context.
var idpkey = '/'+split_pkey[1]+'/ids/';
//first query as SQL
//get highest numerical value.
var q = 'SELECT TOP 1 * FROM c \
WHERE c.pkey = \''+idpkey+'\' ORDER BY c.n desc';
//helper function to create uuids. can I ditch it?
function CreateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
q
,
function (firstError, feed, options) {
if (firstError) throw "firstError:"+firstError;
//console.log(collection.options.);
console.log(idpkey+', '+n+', '+id+"-");
var maxn = 0;
// take 1st element from feed
if (!feed || !feed.length) {
//var response = getContext().getResponse();
//response.setBody(null);
}
else {
maxn = feed[0].n;
//var response = getContext().getResponse();
//var body = { original: '', document: '', feed: feed[0] };
//response.setBody(JSON.stringify(body));
}
console.log(maxn);
//query for existing numerical value
q = 'SELECT TOP 1 * FROM c \
WHERE c.pkey = \''+idpkey+'\' \
AND \
c.number = '+n+' \
OR \
c.id = \''+id+'\'';
var isAccepted2 = collection.queryDocuments(
collection.getSelfLink(),
q
,
function (secondFetchError, feed2, options2) {
if (secondFetchError) throw "second error:"+secondFetchError;
//if no numerical value found, create a new (autoincrement)
if (!feed || !feed.length) {
console.log("|"+idpkey);
var uuid = CreateUUID();
var newid = {
id:uuid,
pkey:idpkey,
doc_pkey:opkey,
n:maxn+1
};
//here I used the javascript query api
//it throws an error claiming the primary key is different and I don't know why, I am using idpkey all the time
var isAccepted3 = collection.upsertDocument(
collection.getSelfLink(),
newid
,
function (upsertError,feed3,options3){
if (upsertError) throw "upsert error:"+upsertError;
//if (upsertError) console.log("upsert error:|"+idpkey+"|");
//var response = getContext().getResponse();
//response.setBody(feed[0]);
});
if (!isAccepted3) throw new Error('The third query was not accepted by the server.');
console.log(" - "+uuid);
}
else {
//if id found, return it
//maxn = feed[0].n;
var response = getContext().getResponse();
response.setBody(feed[0]);
//var body = { original: '', document: '', feed: feed[0] };
//response.setBody(JSON.stringify(body));
}
});
if (!isAccepted2) throw new Error('The second query was not accepted by the server.');
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
The error message is :
"Requests originating from scripts cannot reference partition keys other than the one for which client request was submitted."
I don't understand why it thinks it is in error, as I am using the variable idpkey in all queries to hold the correct pkey.
Talk about brain fart!
I was violating my own rules because I was misspelling the partition name in the request, making the first part of the partition key /sometype/ different from the parameter sent, causing a mismatch between the execution scope's partition key and the idpkey variable, resulting in the error.

Repast: how to get a particular agent set based on the specific conditions?

I am previously working with Netlogo and there are some very good built-in methods that allow me to filter and control the desired agents from the total population. (see: http://ccl.northwestern.edu/netlogo/docs/dictionary.html#agentsetgroup). For instance, I could very easily to command the different class of people agent in a simulation with simple codes like:
ask peoples with [wealth_type = "rich"] [donate money...]
ask peoples with [wealth_type = "poor"] [get money from rich people...]
In Repast, are there list of methods specifically built for easy controlling of agent set?
The equivalent in Repast Simphony Java is to use a Query. Queries apply a predicate to each agent in the Context and returns those that evaluate to true in an iterator. The PropertyEquals query evaluates an agent's property w/r to some value (e.g. "wealth_type" and "rich"). Note that "property" here refers to a Java property, i.e., a getter type method:
String getWealthType() {
return wealthType;
}
where "wealthType" is the name of the property.
As an example, in the JZombies example model, we can query Humans whose energy is equal to 5.
Query<Object> query = new PropertyEquals<Object>(context, "energy", 5);
for (Object o : query.query()) {
Human h = (Human)o;
System.out.println(h.getEnergy());
}
The query() iterator returns all the humans whose energy is equal to 5.
You can get a bit more complicated in the equivalence test by providing your own predicate. For example,
PropertyEqualsPredicate<Integer, Integer> pep = (a, b) -> {
return a * 2 == b;
};
Query<Object> query2 = new PropertyEquals<Object>(context, "energy", 8, pep);
for (Object o : query2.query()) {
Human h = (Human)o;
System.out.println(h.getEnergy());
}
Here, we are checking if the energy * 2 == 8. The predicate is passed the agent's property value in the first parameter and the value to compare against in the second parameter. Given that the predicate returns a boolean, you could also test for inequality, greater than etc.
Simphony has a variety of queries available. See,
https://repast.github.io/docs/api/repast_simphony/repast/simphony/query/package-summary.html
https://repast.github.io/docs/RepastReference/RepastReference.html#_repast_model_design_fundamental_concepts
for more info.
You can also do this in Simphony's ReLogo dialect:
ask (turtles()){
if (wealth_type == "rich") {
donateMoney()
}
if (wealth_type == "poor") {
getMoneyFromRichPeople()
}
}
If you want to just collect the richTurtles you can do (where "it" is the default method to access the individual turtle that is iterated over with findAll):
richTurtles = turtles().findAll{
it.wealth_type == "rich"
}
or with an explicit closure argument:
richTurtles = turtles().findAll{x->
x.wealth_type == "rich"
}

Searching a List of objects for a particular object in dart using "where"

I would like to obtain an object from a List based on a specific search criteria of its member variable
this is the code I am using
class foo
{
foo(this._a);
int _a;
}
List<foo> lst = new List<foo>();
main()
{
foo f = new foo(12);
lst.add(f);
List<foo> result = lst.where( (foo m) {
return m._a == 12;
});
print(result[0]._a);
}
I am getting the error and not sure how to resolve this
Uncaught exception:
TypeError: Instance of 'WhereIterable<foo>': type 'WhereIterable<foo>' is not a subtype of type 'List<foo>'
I am trying to search for an object whose member variable a == 12. Any suggestions on what I might be doing wrong ?
The Iterable.where method returns an iterable of all the members which satisfy your test, not just one, and it's a lazily computed iterable, not a list. You can use lst.where(test).toList() to create a list, but that's overkill if you only need the first element.
You can use lst.firstWhere(test) instead to only return the first element, or you can use lst.where(test).first to do effectively the same thing.
In either case, the code will throw if there is no element matched by the test.
To avoid throwing, you can use var result = lst.firstWhere(test, orElse: () => null) so you get null if there is no such element.
Another alternative is
foo result;
int index = lst.indexWhere(test);
if (index >= 0) result = lst[index];
The answer is simple. Iterable.where returns an Iterable, not a List. AFAIK this is because _WhereIterable does its computations lazily.
If you really need to return a List, call lst.where(...).toList().
Otherwise, you can set result to be an Iterable<foo>, instead of a List<foo>.
or you can go crazy and do this:
bool checkIfProductNotFound(Map<String, Object> trendingProduct) {
bool isNotFound = this
._MyProductList
.where((element) => element["id"] == trendingProduct["id"])
.toList()
.isEmpty;
return isNotFound ;
}

Can not parse XML when getting Empty tag in xml

While parsing an XML in Blackberry using DOM i got an empty node like </image>.
while parsing is uses condition if ("image".equals(node.getNodeName().toString())) to check whether this is image node or not. but does not get inside the condition.
if i uses xyz.jpg then image name returned. so please tell me condition by which i can classify whether this is empty node or not.
NodeList childNodes = node.getChildNodes();
int numChildren = childNodes.getLength();
Node firstChild = childNodes.item(0);
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (numChildren == 1 && firstChild.getNodeType() == Node.TEXT_NODE) {
if ("headline".equals(node.getNodeName().toString())) {
vecHeadline.addElement(firstChild.getNodeValue());
}
}
}
but when i get empty tag like this will not parse. actually i want to add a string where node is empty
As you are not providing the exception I'll have to guess.
node.getNodeName().toString() is where it is crashing.
Try checking first is node.getNodeName() is not null

How would I find the text of a node that has a specific value for an attribute in groovy?

I'm using XMLSlurper. My code is below (but does not work). The problem is that it fails when it hits a node that does not have the attribute "id". How do I account for this?
//Parse XML
def page = new XmlSlurper(false,false).parseText(xml)
//Now save the value of the proper node to a property (this fails)
properties[ "finalValue" ] = page.find {
it.attributes().find { it.key.equalsIgnoreCase( 'id' ) }.value == "myNode"
};
I just need to account for nodes without "id" attribute so it doesn't fail. How do I do that?
You could alternatively use the GPath notation, and check if "#id" is empty first.
The following code snippet finds the last element (since the id attribute is "B" and the value is also "bizz", it prints out "bizz" and "B").
def xml = new XmlSlurper().parseText("<foo><bar>bizz</bar><bar id='A'>bazz</bar><bar id='B'>bizz</bar></foo>")
def x = xml.children().find{!it.#id.isEmpty() && it.text()=="bizz"}
println x
println x.#id
Apprently I can get it to work when I simply use depthFirst. So:
properties[ "finalValue" ] = page.depthFirst().find {
it.attributes().find { it.key.equalsIgnoreCase( 'id' ) }.value == "myNode"
};

Resources