Sort map with velocity - sorting

I populated a map from a xml document in velocity successfully.
Now I am trying to soft the map.
Any one have an idea how to do this.
Here is my velocity template
#set ($root = $context.root)
#set ($nodes = $root.selectNodes("MedicalHIstoryResponse/MedicalResponses"))
#set ($container = {})
#foreach( $node in $nodes )
#set($recordId = $!node.selectSingleNode("recordId/text()").getStringValue())
#set($myHashMap = {
"eventDate": $!node.selectSingleNode("EventDate/text()").getStringValue(),
"eventType": $!node.selectSingleNode("EventType/text()").getStringValue(),
"description": $!node.selectSingleNode("Description/text()").getStringValue(),
"recordId": $recordId,
"parentRecordId": $!node.selectSingleNode("parentRecordId/text()").getStringValue(),
"noofAttachment": $!node.selectSingleNode("noofAttachment/text()").getStringValue(),
"noofLinkFolder": $!node.selectSingleNode("noofLinkFolder/text()").getStringValue(),
"hide": $!node.selectSingleNode("hide/text()").getStringValue(),
"addedBy": $!node.selectSingleNode("addedBy/text()").getStringValue()
})
#set ($discard = $container.put($recordId, $myHashMap))
#end
#foreach($obj in $container)
$obj
#end

You can use a TreeMap instead of an HashMap. It will keep entries sorted by key.
You will need a small tool to create empty maps in VTL (or you can use the definitely ugly hack:
#set($dummy="")
#set($container = $dummy.class.forName("java.util.TreeMap").newInstance())
at least for testing purposes).

Quick solution: use Velocity Sort Tool - docs here.
#foreach($obj in $sorter.sort($container))
$obj
#end
You'll need to add the sort tool to the Velocity context using
VelocityContext velocityContext = new VelocityContext(variableMap);
// now add in the velocity tools required
velocityContext.put("sorter", new SortTool());
Better solution: follow MVC principles and do all this work in Java code. Amongst other benefits, this would give you the flexibility to apply a custom sort order (Comparator). See my other SO answer here for a full explanation and justification.

Related

Validation for UWP textbox

I am currently developing a UWP application, I am very new to this platform and need some help.
Thanks for the help!
So I was able to write up a demo project.
You can find it on Github Here!
I'll quickly tell you about the sample, There are two solutions:
Quick and Dirty: This took the most time for me and I had to write up a lot of code for something very trivial. I don't recommend this way but this way is non complicated and straight forward.
Dynamic Content way (Recommended): Here, I've kept things extensible might be a little bit complex but it's more easy to manage and works much better than the first way.
Since you're using MVVM, I've followed the same.
Please Note: I haven't exactly replicated your model as I didn't know what to put in the UI and what all are the validations, but from the sample you'll be able to figure it out.
I hope this helps, in-case of any queries, feel free to use the comments section.
In the recommended solution your key area to control is just a single collection:
internal ObservableCollection<ComponentModel.IFormControl> FormFields => new ObservableCollection<ComponentModel.IFormControl>(new List<ComponentModel.IFormControl>()
{
new ViewModel.TextFieldInputControlViewModel(){HeaderName = "Name",PlaceholderText="e.g. John Doe",IsMandatory = true },
new ViewModel.TextFieldInputControlViewModel(){HeaderName = "Admin No" , PlaceholderText = "e.g. ABC123"},
new ViewModel.TextFieldInputControlViewModel(){HeaderName = "Phone" , PlaceholderText = "e.g. +32538349182" ,IsMandatory = true,MatchingPattern = #"^[\+]?[1-9]{1,3}\s?[0-9]{6,11}$"},
new ViewModel.TextFieldInputControlViewModel(){HeaderName = "Item Description", PlaceholderText = "e.g. My Fav Item",IsMandatory = true },
new ViewModel.TextFieldInputControlViewModel(){HeaderName = "Location Lost", PlaceholderText = "e.g. Alaska",IsMandatory = true },
new ViewModel.DateTimeFieldInputViewModel(){ HeaderName = "Date Lost",IsMandatory = true}
});
and you can add more types from inheriting from the interface IFormControl and just add in fields here. exactly as simple as it sounds when it comes to adding more fields.

Wakanda Datastore - Find and Replace?

I've got a lot of values in a legacy Wakanda datastore which I need to update to some new values. Is there a curl-like command in the wakanda data browser page that can be used to do a mass find-and-replace in a table?
If your dataclass is called MyDataClass and the attribute you want to update is myAttribute you can use the following server-side script :
var newValue = "new value";
ds.MyDataClass.all().forEach(function(entity){
entity.myAttribute = newValue;
entity.save();
});
You can also use a transaction if you want to commit or rollback the whole operation
I don't think there is a way to do a mass of find/replace in the dataBrowser,
But I suggest you to use a query in the server side that search the records with the value you need to replace, and then a loop on this collection to set the new values
As mentioned in other answers, you are likely best to loop over a collection. There is no concept of a mass replace in Wakanda like you see in many other databases.
var myCollection = ds.DataClassName.query("attributeName == :1", "valueToFind");
myCollection.forEach(function(e){
e.attributeName = "newValue";
e.save();
});
So a fake "person" data type might look like this:
var blankFirsts = ds.Person.query("firstname == :1", "");
blankFirsts.forEach(function(person){
person.firstname = "no name";
person.save();
});

FOSElasticaBundle order query

I am integrating FOSElasticaBundle in my Symfony 2.3 project and I need to sort the results by their price property.
Here is my code:
$finder = $this->container->get('fos_elastica.finder.website.product');
$fieldTerms = new \Elastica\Query\Terms();
$fieldTerms->setTerms('taxon_ids', $taxon_ids_array);
$boolQuery->addMust($fieldTerms);
$resultSet = $finder->find($boolQuery);
How I can do this?
Thanks
Try create a \Elastica\Query object which also contains the sorting information, then send this to the finder:
$finder = $this->container->get('fos_elastica.finder.website.product');
$fieldTerms = new \Elastica\Query\Terms();
$fieldTerms->setTerms('taxon_ids', $taxon_ids_array);
$boolQuery->addMust($fieldTerms);
$finalQuery = new \Elastica\Query($boolQuery);
$finalQuery->setSort(array('price' => array('order' => 'asc')));
$resultSet = $finder->find($finalQuery);
Have a look at the elasticsearch docs on the sort parameter to see how to use it properly.
NOTE: \Elastica\Query is quite different to \Elastica\Query\AbstractQuery, the first encapsulates everything you could send to the _search API endpoint (facets, sorting, explain, etc...) The AbstractQuery represents a base type for each of the individual query types (range, fuzzy, terms, etc...).

How do URL shortener calculate the URL key? How do they work?

How do URL shortener's like bit.ly calculate a random key for each link? What algorithm would I need to know to create my own?
So far I found the code from http://briancray.com/2009/08/26/free-php-url-shortener-script/
function getShortenedURLFromID ($integer, $base = ALLOWED_CHARS)
{
$length = strlen($base);
while($integer > $length - 1)
{
$out = $base[fmod($integer, $length)] . $out;
$integer = floor( $integer / $length );
}
return $base[$integer] . $out;
}
and the more complex answer by Marcel J. mentioned above.
I think they DON'T random a new key and checks if exists in database, because it its slower than just use a sequencial number and apply some criptography algoritm to convert sequencial id to a UNIQUE string.
Ex:
idUrl = 1003;
urlCode = doSomething(idUrl); // 161Llz
URL to use:
http://bit.ly/161Llz
Tks: mykhal and nick johnson
Maybe they store it in the database and just give you an link id. When you query this key they look in their database and forward you to the stored real link. To encode the id something like base64 (or similar) might be used.
They most likely store it in a database and just generate the key randomly. I assume this because you can make your own key, and if they just decoded it you wouldn't be able to choose it yourself.
As for how to do it, you could just create a database in mySQL and have it hold the key and full site. Just search it for the key and then redirect the user to the full site.

Getting all zip codes within an n mile radius

What's the best way to get a function like the following to work:
def getNearest(zipCode, miles):
That is, given a zipcode (07024) and a radius, return all zipcodes which are within that radius?
There is a project on SourceForge that could assist with this:
http://sourceforge.net/projects/zips/
It gives you a database with zip codes and their latitude / longitude, as well as coding examples of how to calculate the distance between two sets of coordinates. There is probably a better way to do it, but you could have your function retrieve the zipcode and its coordinates, and then step through each zipcode in the list and add the zipcode to a list if it falls within the number of miles specified.
If you want this to be accurate, you must start with polygon data that includes the location and shape of every zipcode. I have a database like this (used to be published by the US census, but they no longer do that) and have built similar things atop it, but not that exact request.
If you don't care about being exact (which I'm guessing you don't), you can get a table of center points of zipcodes and query points ordered by great circle distance. PostGIS provides great tools for doing this, although you may construct a query against other databases that will perform similar tasks.
An alternate approach I've used is to construct a box that encompasses the circle you want, querying with a between clause on lon/lat and then doing the great-circle in app code.
Maybe this can help. The project is configured in kilometers though. You can modify these in CityDAO.java
public List<City> findCityInRange(GeoPoint geoPoint, double distance) {
List<City> cities = new ArrayList<City>();
QueryBuilder queryBuilder = geoDistanceQuery("geoPoint")
.point(geoPoint.getLat(), geoPoint.getLon())
//.distance(distance, DistanceUnit.KILOMETERS) original
.distance(distance, DistanceUnit.MILES)
.optimizeBbox("memory")
.geoDistance(GeoDistance.ARC);
SearchRequestBuilder builder = esClient.getClient()
.prepareSearch(INDEX)
.setTypes("city")
.setSearchType(SearchType.QUERY_THEN_FETCH)
.setScroll(new TimeValue(60000))
.setSize(100).setExplain(true)
.setPostFilter(queryBuilder)
.addSort(SortBuilders.geoDistanceSort("geoPoint")
.order(SortOrder.ASC)
.point(geoPoint.getLat(), geoPoint.getLon())
//.unit(DistanceUnit.KILOMETERS)); Original
.unit(DistanceUnit.MILES));
SearchResponse response = builder
.execute()
.actionGet();
SearchHit[] hits = response.getHits().getHits();
scroll:
while (true) {
for (SearchHit hit : hits) {
Map<String, Object> result = hit.getSource();
cities.add(mapper.convertValue(result, City.class));
}
response = esClient.getClient().prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
if (response.getHits().getHits().length == 0) {
break scroll;
}
}
return cities;
}
The "LocationFinder\src\main\resources\json\cities.json" file contains all cities from Belgium. You can delete or create entries if you want too. As long as you don't change the names and/or structure, no code changes are required.
Make sure to read the README https://github.com/GlennVanSchil/LocationFinder

Resources