#249 Porting to Dart language

Dmitriy Vasilyev Tue 20 Jan 2015

Hi! I'm going to port haystack-java to Dart. We making a web application for SkySpark. We think it's better to port exist client library for haystack instead write own implementation, right?

So, I have a questions. Can I just copy all this repo to Dart or task is not trivial? Should I port all java files or I need in a part if this?

Port will be published on https://pub.dartlang.org as open source.

Thank you.

Brian Frank Tue 20 Jan 2015

Porting to Dart would really only require the client portions of the Java library. Plus you would probably want to make use of the Browser's XMLHttpRequest.

  • org.projecthaystack: APIs to model core data values, grids, dicts
  • org.projecthaystack.io: grid encoders/decoders (just really need Zinc)
  • org.projecthaystack.client: really want to make HClient work in browser

If do get a working Dart client library, please let us know!

Mike Jarmy Tue 20 Jan 2015

Sounds like a really interesting project, please post us a link once you've got it working. As Brian said, it shouldn't be that hard.

Dmitriy Vasilyev Tue 20 Jan 2015

Thank you for answer! Sure I'll get you know when I'm done. With Dart language you'll get JavaScript library automatically (I'll publish it on github)

Alper Üzmezler Tue 20 Jan 2015

That will be our open source push to the community.

Dmitriy Vasilyev Fri 23 Jan 2015

Hi, guys. Working on HStr class and have a questions about split method.

Do I need really port your split algorithm or I can use common Dart String.split() method?

If I do need so can you tell me what the last string of method is doing:

public static String[] split(String str, int separator, boolean trim)
{
  ArrayList toks = new ArrayList(16);
  //...
  return (String[])toks.toArray(new String[toks.size()]);
}

Mike Jarmy Fri 23 Jan 2015

It looks like that method is only used for splitting up mime types in the Accept header of an HTTP request. So you basically just need to do whatever works properly for that. If there is any easier way to do it with Dart, then thats fine.

FYI the last line is the standard java idiom for turning a List into an Array of a given type.

Dmitriy Vasilyev Fri 23 Jan 2015

Thank you. What about this:

In HNum.hashCode():

long bits = Double.doubleToLongBits(val);
int hash = (int)(bits ^ (bits >>> 32));

This code cuts number to 32 bit. Is it really need? Or this operation servers for convert to int type only?

Can I just convert double to int without this operations?

Dmitriy Vasilyev Mon 26 Jan 2015

I have one idea. In all val objects (extends HVal) there are equals method. Can I just override == operator instead use equals methods?

Brian Frank Mon 26 Jan 2015

In Java you use equals and hashCode overrides to manage equality so that you could use a class like HRef as a key in a hash map. I have never programmed in Dart, but I believe you do this by overriding the == operator.

Dmitriy Vasilyev Tue 27 Jan 2015

ok, got it. Thank you.

Dmitriy Vasilyev Tue 3 Feb 2015

Hi again. Now I'm working on HZincReader class. It works on StringStream as I understand, and reads string char by char.

I have a working project (ActionScript3) where I split response on strings, than split by commas (and/or by space if needed). It works with regexp. Just split, than convert to real values and types. It works well on our project.

So, what is do you think better way to do it in Dart: split by regexp or read char by char? May be regexp takes a lot of time compare it with one-char reading?

Mike Jarmy Tue 3 Feb 2015

That really depends on Dart itself, or rather the performance of its libraries. I myself have no first-hand experience with Dart.

Brian Frank Tue 3 Feb 2015

Now I'm working on HZincReader class. It works on StringStream as I understand, and reads string char by char.

If you are porting that code, then you have to handle it char by char. If you split by comma or anything, then your code won't handle commas inside quoted strings for example. Given that very similar code is already running successfully in JavaScript, I wouldn't worry too much about performance (assuming Dart does good job to compile into JS).

Dmitriy Vasilyev Tue 3 Feb 2015

I wrote this in AS3:

var spaceRE:RegExp = /(?:\s|^)(?:(?:"[^"]*")|(?:\([^\(\)]*\))|(?:[^\s\(\)"]*))*(?=\s|$)/g;

var commaRE:RegExp = /(?:,|^)(?:(?:"[^"]*")|(?:\([^\(\)]*\))|(?:[^,\(\)"]*))*(?=,|$)/g;

It's dumb expresses: lefts commas(spaces) in match start. Need to clean it after. Also need make together parts like haystackCur:@S.EnergyDVRDemo.AHU_3.Fan and "EnergyDVRDemo AHU_3 Fan".

I split body by \n char, then I search matches in rows with commas or space chars using this reg exps. It works well in our project. What do you think?

Brian Frank Tue 3 Feb 2015

What do you think?

Well I personally find that code difficult to understand, but then again I'm not a huge fan of regex :) So its really a personal thing as long it works. Just make sure when you test suite you try out complicated combinations like:

foo,"bar \", baz"

I would recommend you port the Java test suite in its entirety which has tons of boundary conditions to test

Dmitriy Vasilyev Tue 3 Feb 2015

Yes, I understand. I'll try to port code as is, as I did it for model core data values, grids, dicts (with all tests). Thank you.

Dmitriy Vasilyev Mon 9 Feb 2015

May be bug in HZincReader/Writer classes with null values:

There is string in your ZincTest.java in grid (5th test):

"Bin(text/plain),N\n"

So, it reads ok, as null value. But then ZincWriter makes this string:

"Bin(text/plain),\n"

And now new body can't be parsed, because there isn't value after comma, so in a row values less than columns (1 < 2).

Reader works this way(HZincReader.java 86-96):

for (int i=0; i<numCols; ++i)
{
  skipSpace();
  if (cur != ',' && cur != '\n') cells[i] = readVal();
  skipSpace();
  if (i+1 < numCols)
  {
    if (cur != ',') throw errChar("Expecting comma in row");
    consume();
  }
}

Writes works this way (HZincWriter.java 122-130):

if (i > 0) out.write(',');
if (val == null)
{
  if (i == 0) out.write('N');
}
else
{
  out.write(val.toZinc());
}

I met this bug after run ported zinc tests.

So, what to do: add null values if commas meets or always write N for nulls? Do your tests works in java well?

P.S. I have met zinc responses where was ,,, rows, so I did first way in Dart now.

Brian Frank Tue 10 Feb 2015

An empty cell is always treated the same as N - both resulting in null for that cell. The Java code works both ways, but I believe the writer always prefers the empty cell to the N cell. I just tested it a couple different ways and it looks like the Java code handles both cases just fine.

However, remember that there is one special case - a single column grid. In this case you must use N and can't leave the entire row empty, because otherwise you end up with an empty line which is considered end of grid.

Dmitriy Vasilyev Tue 10 Feb 2015

Oh, sorry, understood. You have pre-filled array with nulls.

HVal[] cells = new HVal[numCols];

I never do it like this and miss.

Dmitriy Vasilyev Wed 11 Feb 2015

I'm making HClient class. How can I try and test calls to a haystack?

I have installed skyspark locally in my laptop. I run it and can login into it with web form, can see some information in demo project.

Then I have started simple http server to host html page with dart code. But when I try making a simple request from dart to skyspark (/api/demo/about) I catch cross domain error.

So, I don't understand: how I can reach skyspark? How I can test and use haystack-dart library?

Brian Frank Wed 11 Feb 2015

So, I don't understand: how I can reach skyspark?

Everything has to be be loaded in the browser from the same domain. Simplest way to load JS code into the browser from SkySpark is to put all your files into the {home}/pub/ directory which is then available in browser under /pub/.

Also remember that to access a project you will need to be logged into that project, or more simply for testing just run with -noAuth flag

Dmitriy Vasilyev Fri 13 Feb 2015

So, looks like I haven't way to retrieve Folio-Auth-Api-Uri HTTP header (because browser always follows redirect). I have to hardcode auth api uri in code or skip it.

What is most appropriate way to implement auth? In other words:

  1. Should I make Basic auth?
  2. Should I make Folio auth?
  3. Which ones uri I should hardcode for Folio auth? I know follows cases:
    • /auth/project/api?username (EnergyDvr)
    • /auth/project/salt?username and /auth/project/login (SkySpark Login form)

Brian Frank Fri 13 Feb 2015

We don't really have a standard authentication mechanism, I guess if we just always required https we could stick with Basic. You really want both for now though. I would suggest just copying the logic in the Java HClient which is well tested for various servers.

For folio nothing is hardcoded, you just look for the Folio-Auth-Api-Uri HTTP header.

Dmitriy Vasilyev Fri 13 Feb 2015

I can't just copy java. When I try to get api/project/about server answer with 303 status (redirect) and Folio-Auth-Api-Uri HTTP header. Dart (as JavaScript) works in browser and using for Html requests browser's XMLHttpRequest object which always follows redirect. This is W3C standard. After redirect I got html login page which doesn't contain Folio-Auth-Api-Uri HTTP header. This is why I can't use java's way.

By the way, your login form page doesn't read this header too. Paths are included in html's javascript (may be with template engine).

Just wanted to ask your opinion for best solution in this problem.

Brian Frank Fri 13 Feb 2015

In the browser, you are going to be served up from the server system already most likely for cross-domain reasons. So typically you will defer to the authentication mechanism and login pages of the source system. For example in SkySpark, any URIs to an authenticated realm will redirect to the login page, then back to the original URI after login.

Dmitriy Vasilyev Fri 13 Feb 2015

Understood. Now I have skipped auth part of HClient.

Alper Üzmezler Mon 16 Feb 2015

Hi Brian and community,

Haystack dart port is written and community feedback would be essential.

Dmitry will be publishing the open source toolkit (client side only) today.

Dmitriy Vasilyev Mon 16 Feb 2015

Hi, guys. It's almost done. I ommited all server parts. And now still exists one annoyed bug with timezone, but it's only as I know.

Can you preview it and make few comments? Bitbucket rep

Brian Frank Mon 16 Feb 2015

Until someone actually tries to use in practice, you probably won't get the feedback you really need. But just looking thru the code and having only a superficial knowledge of Dart it looks like a very straight forward port of the Java code which should make for solid design. It looks like you have the key tests for HVal, HDict, and zinc stuff all duplicated too - so if those tests are fully passing then you should have a pretty solid start.

Pretty awesome guys, thanks for your contributions. I will update the Downloads section to port to this repo too ok?

Alper Üzmezler Mon 16 Feb 2015

Thank you Brian.

Posting on download section would be great start to get more community attention.

I think all asynchronous testings are working. We just need to improve the timezone classes.

Dmitriy Vasilyev Thu 19 Feb 2015

Project published. Use this link: https://pub.dartlang.org/packages/haystack.

Tell me, if something is wrong in descriptions.

Brian Frank Fri 20 Feb 2015

Link will be in next upgrade of website (whenever I post that)

Login or Signup to reply.