I have written an Service Provider implementation for OAuth and one of the Devs found a bug in the way the implementation was ordering query parameters. I totally missed the lexicographical ordering requirement in the OAuth spec and was just doing a basic string sort on the name value parameters
Given the following URI request from the consumer:
http://api.com/v1/People/Search?searchfor=fl&communication=test#test.com&Include=addresses
The resulting signature base should order the parameters as:
Include=addresses, communication=test#test.com, searchfor=fl
Given the following URI request from the consumer:
http://api.com/v1/People/Search?searchfor=fl&communication=test#test.com&include=addresses
The resulting signature base should order the parameters as:
communication=test#test.com, include=addresses, searchfor=fl
Note the case difference in the querystring parameter "include". From what I understand, lexicographical byte value ordering will order parameters using the ascii value and then order asc.
Since I = 73 and i = 105, the capital I should be ordered before the lowercase i.
I have the following so far:
IEnumerable<QueryParameter> queryParameters = parameters
.OrderBy(parm => parm.Key)
.ThenBy(parm => parm.Value)
.Select(
parm => new QueryParameter(parm.Key, UrlEncode(parm.Value)));
But that will not cover the ascii character by character sort (IncLude=test&Include=test will not sort properly).
Any thoughts on how to make an efficient algorithm that will answer this problem? Or how to make the sort case sensitive via ICompare?
I solved the problem by creating a custom comparer, however, it seems clunky and I feel there must be a better way:
public class QueryParameterComparer : IComparer<QueryParameter> {
public int Compare(QueryParameter x, QueryParameter y) {
if(x.Key == y.Key) {
return string.Compare(x.Value, y.Value, StringComparison.Ordinal);
}
else {
return string.Compare(x.Key, y.Key, StringComparison.Ordinal);
}
}
}
Using the Ordinal string comparison is what did it for me. It does byte comparisons which is exactly what I needed.
Nick, as you've discovered StringComparison.Ordinal is the way to go. I just wanted to call out a caution that you sort AFTER you URI encode each of the keys and values.
BTW, there are already a few OAuth libraries out there, DotNetOpenAuth being my favorite (disclaimer: for biased reasons). Are you sure you want to build/maintain this one?
I had problem with the same expression (though it is not misspelled anymore in the OAuth documentation, - if that's the place where it was misspelled.)
Wikipedia sais, "lexicographical ordering" has meaning, when the letter ordering is given. It specifies the ordering of series of elements (letters) when the element's order is specified already.
It sounds reasonable to me. :).
Related
Is there a quick way to look up an Enum with only using the label of the enum instead of the value. Let's say the Enum type is SalesStatus, I want to be able to basically call into some kind of a function like enumLabel2Value(enumStr(SalesStatus), "Open order") and it will return 1.
I'm trying to avoid looping thru all possible values and checking each one separately, it seems like this should be something that's readily available since whenever a user filters on a enum column on a grid, they enter in the label, not the value, but I haven't seen anything like it.
You can use the str2Enum function for that. From the documentation:
Retrieves the enum element whose localized Label property value
matches the input string.
In addition to the caveats from Alex Kwitny's answer, I recommend taking a look at the comments of the documentation, specifically the comment
Please note that str2Enum performs partial matching and matches the
beginning of the string. If there are multiple matches, it will take
the first one.
In addition take a look at method string2Enum of class DMFEntityBase, which supports different options how the enum element can be specified. I think with the DictEnum.name2Value() method enum elements specified by their label are handled.
Update
OP mentioned in the comments to Alex Kwitny's answer that it is a specific enum ExchangeRateDisplayFactor he has issues with. str2Enum also works with that enum, as the following job demonstrates:
static void str2EnumTest(Args _args)
{
ExchangeRateDisplayFactor factor;
factor = str2Enum(factor, '1');
info(strFmt('%1', factor)); // outputs '1'
factor = str2Enum(factor, '10');
info(strFmt('%1', factor)); // outputs '10'
factor = str2Enum(factor, '100');
info(strFmt('%1', factor)); // outputs '100'
factor = str2Enum(factor, '1000');
info(strFmt('%1', factor)); // outputs '1000'
factor = str2Enum(factor, '10000');
info(strFmt('%1', factor)); // outputs '10000'
}
It doesn't exist because labels can be all sorts of things in different languages. symbol2Value() exists though and may be what you're looking for, but your question is specifically on labels. An example of where this could be very bad...
Let's say you have an enum called GoodBadPresent, to indicate what type of Christmas present you will receive, with two values:
GoodBadPresent::Poison English label: "Poison"; German label: "Gift"
GoodBadPresent::Gift English label: "Gift"; German label: "Geschenk"
If this example isn't clear, the word for Poison in German is Gift. So if you tried to resolve Gift to an enum value, you'd also have to provide the language. The performance problems here are probably greater than the performance problems of looping through an enum.
You can look at DictEnum to see if there are any methods that can help you more succinctly achieve what you want though. https://msdn.microsoft.com/en-us/library/gg837824.aspx
I'm more curious to the details of your scenario where you need to get back to an enum from a label.
I need your help with following issue:
In my code I have a list of elements, I need to sort this list according to 2 attributes: season and number.
List example:
<episode_list>
<episode id="280" number="13" season="1">
<title><![CDATA[Bowl Game]]></title>
</episode>
<episode id="314" number="12" season="1">
<title><![CDATA[Piss Test]]></title>
</episode>
<episode id="730" number="11" season="1">
I use Collections.sort(), but getting exception. As I understand I can't use it with JDOM Elements:
List<Element> episodes;
Collections.sort(episodes, new Comparator<Element>() {
#Override
public int compare(Element elem1, Element elem2) {
Integer seasonNumber1 = Integer.valueOf(myService.valueOfAttribute("season", elem1));
Integer seasonNumber2 = Integer.valueOf(myService.valueOfAttribute("season", elem2));
int seasonComp = seasonNumber1.compareTo(seasonNumber2);
if (seasonComp != 0) {
return seasonComp;
} else {
Integer episodeNumber1 = Integer.valueOf(myService.valueOfAttribute("number", elem1));
Integer episodeNumber2 = Integer.valueOf(myService.valueOfAttribute("number", elem2));
return episodeNumber1.compareTo(episodeNumber2);
}
}
});
Exception: java.util.Collections$UnmodifiableList$1.set(Unknown Source)
java.util.Collections.sort(Unknown Source)
Actually I don't need sorted xml, the only thing I need is the episode attribute "id" (for the lowest season and the lowest episode number).
What could you recommend? I have another implementation, where I go through all elements, but I don't think it's a nice solution...I also can create Java class Episode(id, episode, season), transform List to List and sort it, but also don't think it's a good idea. There is also sortContent method for Element, but I'm not sure how to implement it.
I'll appreciate any help.
Content attached to JDOM Elements cannot be sorted using the standard Collections.sort() mechanism because that process does not honour the only-attached-at-one-place-at-a-time rule for XML content.
JDOM has sort() methods built in to the Element class that allows you to sort the chile Elements or other Child content: See The Element.sortChildren() Javadoc for the JDOM way to do it.
Update: Also, for your reference, the error you are getting is because at some point you created an unmodifiable version of the List.... this is not something that happens from JDOM method calls. The error you are getting is because you are trying to modify a List that has been intentionally made read-only.
What's wrong with going through the list and finding the minimum. It is O(n), while sorting is O(n*log(n)). You might use a generic min function, such as the one in guava
Element firstEpisode = Ordering.from(your-comparator).min(episodes.iterator());
If you really want to sort it, why don't you sort new ArrayList<Element>(episodes) (I agree with rolfl that you cannot use Collections.sort for JDOM lists and that the error comes from your use of unmodifiable list).
I think I managed to fit most of the question in to the title on this one!
I'm pulling back an Object from Java in my native C++ code:
jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject);
It's possible for me to check wether the return object is one of the native types using something like:
jclass boolClass = env->FindClass("java/lang/Boolean");
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { }
So, I now have a jobject which I know is a Boolean (note the upper case B) - The question is, what is the most efficient way (considering I already have the jobject in my native code) to convert this to a bool. Typecasting doesn't work which makes sense.
Although the above example is a Boolean I also want to convert Character->char, Short->short, Integer->int, Float->float, Double->double.
(Once i've implemented it I will post an answer to this which does Boolean.booleanValue())
You have two choices.
Option #1 is what you wrote in your self-answer: use the public method defined for each class to extract the primitive value.
Option #2 is faster but not strictly legal: access the internal field directly. For Boolean, that would be Boolean.value. For each primitive box class you have a fieldID for the "value" field, and you just read the field directly. (JNI cheerfully ignores the fact that it's declared private. You can also write to "final" fields and do other stuff that falls into the "really bad idea" category.)
The name of the "value" field is unlikely to change since that would break serialization. So officially this is not recommended, but in practice you can get away with it if you need to.
Either way, you should be caching the jmethodID / jfieldID values, not looking them up every time (the lookups are relatively expensive).
You could also use the less expensive IsSameObject function rather than IsInstanceof, because the box classes are "final". That requires making an extra GetObjectClass call to get valueObject's class, but you only have to do that once before your various comparisons.
BTW, be careful with your use of "char". In your example above you're casting the result of CallCharMethod (a 16-bit UTF-16 value) to a char (an 8-bit value). Remember, char != jchar (unless you're somehow configured for wide chars), long != jlong (unless you're compiling with 64-bit longs).
This is the solution I'm going to use if I get no more input. Hopefully it isn't this difficult but knowing JNI i'm thinking it might be:
if (env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE)
{
jmethodID booleanValueMID = env->GetMethodID(boolClass, "booleanValue", "()Z");
bool booleanValue = (bool) env->CallBooleanMethod(valueObject, booleanValueMID);
addBoolean(key, booleanValue);
}
else if(env->IsInstanceOf(valueObject, charClass) == JNI_TRUE)
{
jmethodID characterValueMID = env->GetMethodID(charClass, "charValue", "()C");
char characterValue = (char) env->CallCharMethod(valueObject, characterValueMID);
addChar (key, characterValue);
}
In general, I write jni for the better performance.
How to gain the better performance ? Using asm, primitive types and few method call.
I suggest that design your method return type can use in c/c++, such as
jint, jlong, jboolean, jbyte and jchar etc.
The redundant function call and convert will make inefficient and unmaintainable implementation.
Stumped on this one. In Grails it seems one cannot define a default sort on multiple columns in domain mapping a la static mapping = { sort 'prop1 desc, prop2 asc' }, or { sort([prop1:'desc', prop2:'asc']) }. Only first column gets sorted, lame.
Similarly, when trying to Groovy sort a Grails findAllBy query on multiple columns, the second sort overrides the first.
def list = [[rowNum:2,position:3],[rowNum:1,position:2],[rowNum:3,position:1]]
list.sort{it.rowNum}.sort{it.position}
Obviously missing the boat on the latter case, the groovy sort. I have seen postings re: implementing comparable, but looking for something more concise if possible.
Here is a Groovy solution. Still essentially implementing a Comparator though.
list.sort { map1, map2 -> map1.rowNum <=> map2.rowNum ?: map1.position <=> map2.position }
Thanks to the link from GreenGiant, we see that the issue is closed as fixed as of version 2.3.
There is also example code:
static mapping =
{ sort([lastname:'asc', name:'asc']) }
It is working for me in 2.4.3
You can use String.format if you know max length. I assumed max 10 lenght:
list.sort { String.format('%010d%010d', it.rowNum, it.position) }
I'm testing out CouchDB to see how it could handle logging some search results. What I'd like to do is produce a view where I can produce the top queries from the results. At the moment I have something like this:
Example document portion
{
"query": "+dangerous +dogs",
"hits": "123"
}
Map function
(Not exactly what I need/want but it's good enough for testing)
function(doc) {
if (doc.query) {
var split = doc.query.split(" ");
for (var i in split) {
emit(split[i], 1);
}
}
}
Reduce Function
function (key, values, rereduce) {
return sum(values);
}
Now this will get me results in a format where a query term is the key and the count for that term on the right, which is great. But I'd like it ordered by the value, not the key. From the sounds of it, this is not yet possible with CouchDB.
So does anyone have any ideas of how I can get a view where I have an ordered version of the query terms & their related counts? I'm very new to CouchDB and I just can't think of how I'd write the functions needed.
It is true that there is no dead-simple answer. There are several patterns however.
http://wiki.apache.org/couchdb/View_Snippets#Retrieve_the_top_N_tags. I do not personally like this because they acknowledge that it is a brittle solution, and the code is not relaxing-looking.
Avi's answer, which is to sort in-memory in your application.
couchdb-lucene which it seems everybody finds themselves needing eventually!
What I like is what Chris said in Avi's quote. Relax. In CouchDB, databases are lightweight and excel at giving you a unique perspective of your data. These days, the buzz is all about filtered replication which is all about slicing out subsets of your data to put in a separate DB.
Anyway, the basics are simple. You take your .rows from the view output and you insert it into a separate DB which simply emits keyed on the count. An additional trick is to write a very simple _list function. Lists "render" the raw couch output into different formats. Your _list function should output
{ "docs":
[ {..view row1...},
{..view row2...},
{..etc...}
]
}
What that will do is format the view output exactly the way the _bulk_docs API requires it. Now you can pipe curl directly into another curl:
curl host:5984/db/_design/myapp/_list/bulkdocs_formatter/query_popularity \
| curl -X POST host:5984/popularity_sorter/_design/myapp/_view/by_count
In fact, if your list function can handle all the docs, you may just have it sort them itself and return them to the client sorted.
This came up on the CouchDB-user mailing list, and Chris Anderson, one of the primary developers, wrote:
This is a common request, but not supported directly by CouchDB's
views -- to do this you'll need to copy the group-reduce query to
another database, and build a view to sort by value.
This is a tradeoff we make in favor of dynamic range queries and
incremental indexes.
I needed to do this recently as well, and I ended up doing it in my app tier. This is easy to do in JavaScript:
db.view('mydesigndoc', 'myview', {'group':true}, function(err, data) {
if (err) throw new Error(JSON.stringify(err));
data.rows.sort(function(a, b) {
return a.value - b.value;
});
data.rows.reverse(); // optional, depending on your needs
// do something with the data…
});
This example runs in Node.js and uses node-couchdb, but it could easily be adapted to run in a browser or another JavaScript environment. And of course the concept is portable to any programming language/environment.
HTH!
This is an old question but I feel it still deserves a decent answer (I spent at least 20 minutes on searching for the correct answer...)
I disapprove of the other suggestions in the answers here and feel that they are unsatisfactory. Especially I don't like the suggestion to sort the rows in the applicative layer, as it doesn't scale well and doesn't deal with a case where you need to limit the result set in the DB.
The better approach that I came across is suggested in this thread and it posits that if you need to sort the values in the query you should add them into the key set and then query the key using a range - specifying a desired key and loosening the value range. For example if your key is composed of country, state and city:
emit([doc.address.country,doc.address.state, doc.address.city], doc);
Then you query just the country and get free sorting on the rest of the key components:
startkey=["US"]&endkey=["US",{}]
In case you also need to reverse the order - note that simple defining descending: true will not suffice. You actually need to reverse the start and end key order, i.e.:
startkey=["US",{}]&endkey=["US"]
See more reference at this great source.
I'm unsure about the 1 you have as your returned result, but I'm positive this should do the trick:
emit([doc.hits, split[i]], 1);
The rules of sorting are defined in the docs.
Based on Avi's answer, I came up with this Couchdb list function that worked for my needs, which is simply a report of most-popular events (key=event name, value=attendees).
ddoc.lists.eventPopularity = function(req, res) {
start({ headers : { "Content-type" : "text/plain" } });
var data = []
while(row = getRow()) {
data.push(row);
}
data.sort(function(a, b){
return a.value - b.value;
}).reverse();
for(i in data) {
send(data[i].value + ': ' + data[i].key + "\n");
}
}
For reference, here's the corresponding view function:
ddoc.views.eventPopularity = {
map : function(doc) {
if(doc.type == 'user') {
for(i in doc.events) {
emit(doc.events[i].event_name, 1);
}
}
},
reduce : '_count'
}
And the output of the list function (snipped):
165: Design-Driven Innovation: How Designers Facilitate the Dialog
165: Are Your Customers a Crowd or a Community?
164: Social Media Mythbusters
163: Don't Be Afraid Of Creativity! Anything Can Happen
159: Do Agencies Need to Think Like Software Companies?
158: Customer Experience: Future Trends & Insights
156: The Accidental Writer: Great Web Copy for Everyone
155: Why Everything is Amazing But Nobody is Happy
Every solution above will break couchdb performance I think. I am very new to this database. As I know couchdb views prepare results before it's being queried. It seems we need to prepare results manually. For example each search term will reside in database with hit counts. And when somebody searches, its search terms will be looked up and increments hit count. When we want to see search term popularity, it will emit (hitcount, searchterm) pair.
The Link Retrieve_the_top_N_tags seems to be broken, but I found another solution here.
Quoting the dev who wrote that solution:
rather than returning the results keyed by the tag in the map step, I would emit every occurrence of every tag instead. Then in the reduce step, I would calculate the aggregation values grouped by tag using a hash, transform it into an array, sort it, and choose the top 3.
As stated in the comments, the only problem would be in case of a long tail:
Problem is that you have to be careful with the number of tags you obtain; if the result is bigger than 500 bytes, you'll have couchdb complaining about it, since "reduce has to effectively reduce". 3 or 6 or even 20 tags shouldn't be a problem, though.
It worked perfectly for me, check the link to see the code !