You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@devicemap.apache.org by Radu Cotescu <ra...@apache.org> on 2013/06/24 19:26:14 UTC

devicemap java client cleanup

Hi devs,

On Thursday I'm invited to talk at meeting no. 13 of the Bucharest Java
User Group [1]. I've decided to tell people about our efforts of providing
tools for client detection, both server-side and client-side.

Since it's trivial to write a web app on top of Apache Sling for my demo
I've decided to use the new client written by Reza because it's a hell lot
easier to modify it for an OSGi environment compared to the current OpenDDR
donated code.

However, in order to make the jar file more friendly, I do need to change a
few things:

   1. the DeviceMapClient initialisation should be performed with the help
   of a configuration Map<String, Object> - I need to be able to pass
   InputStreams instead of having the code look for files on a file system;
   this way the driver code can do whatever it wants as long as it provides
   InputStreams
   2. 1 implies that we don't need the FileLoader class any more
   3. delete the Util.log (now called debugLog) method and pass all the
   logging stuff to SLF4J
   4. maybe replace Main.java with a test (already covered in my changeset)
   ?

Would anyone mind if I commit the previously mentioned changes?

Thanks,
Radu

[1] - http://www.bjug.ro/editii/13.html

Re: devicemap java client cleanup

Posted by Reza <re...@yahoo.com>.
Oops, I forgot about loading data resources over the internet using HTTP urls... That's definitely an easy option too.


________________________________
 From: Reza <re...@yahoo.com>
To: "devicemap-dev@incubator.apache.org" <de...@incubator.apache.org> 
Sent: Monday, June 24, 2013 2:10 PM
Subject: Re: devicemap java client cleanup
 

Right, so if you look in the DeviceMapClient, there is a convenience method:

loadFromFolder(String folder)


This is kind of a remnant from OpenDDR, but basically there is a resource folder that is filled with xml files. Simply point the client to the folder and it will do the rest. Remember, there are at least 4+ xml files which all contribute to the index. Also, there are several internal compilation steps which need to be done inbetween loading these files. Right, the actual names of the files should be configurable, just didnt get to that step yet.

The optimal way to do this is to detect the DeviceMap data jar in the classpath and load the resources without asking the user.

So what you are asking for is to expose the inner methods of the Loader and have the developer open the device and builder files and the patch files and manually feed them in? They then need to know when to kick off the internal compiling methods too. So this would all have to be exposed. Not sure if an off the shelf developer is going to be able to comprehend the inner guts of this package and properly execute all of this...

The simplest approach would be to auto detect the resource jar and use it. Also, create a method for the developer to load files from the local file system. I think its reasonable to make the actual filenames configurable but having the developer drive the file loading and indexing doesn't seem like a good feature.

Also, I just moved some classes around into a package hierarchy.


________________________________
From: Radu Cotescu <ra...@apache.org>
To: devicemap-dev <de...@incubator.apache.org> 
Sent: Monday, June 24, 2013 1:57 PM
Subject: Re: devicemap java client cleanup


Hi Reza,


> 1 and 2) There is a generic Loader (org.apache.devicemap.client.Loader)
> which takes in Readers (like an inputstream but it has an encoding: UTF8).
> FileLoader then wraps this and loads files and I was planning on creating a
> JarLoader which will detect and load resources from a jar. So it should
> probably be organized a bit better (interface and package), but I think if
> there is a new loading method, just wrap Loader, no?


Why should we provide multiple loaders and try to imagine all the use cases
when we could have only one way to initialise the client? The final users
of our client are developers. I'm sure they can wrap whatever type of data
source into an InputStream - files from the file system, files from a JAR,
JCR nodes, Apache Sling resources, URLs, etc.

I'm in favour of keeping things as simple as possible.

WDYT?

Cheers,
Radu

Re: devicemap java client cleanup

Posted by Reza <re...@yahoo.com>.
>> Let's not limit ourselves to thinking only in file system abstractions

Im not. How else can we load data apart from File, Jar, or URL?

So heres my counter point, lets make sure its easy to use. I think most developers want drop ins with zero configuration. Take a look at the feedback OpenDDR got compared to other commercial offerings, it was too complex to use.

What you list below is not simple. Here is what I had in mind:

DeviceMapClient client=new DeviceMapClient(true); //the true parameter will autoload the resources from jar if it exists otherwise the internet

-or-

DeviceMapClient client=new DeviceMapClient();

client.loadFromFolder("/usr/local/data/devicemap");

-or-

DeviceMapClient client=new DeviceMapClient();

client.setDeviceFilePath("/usr/local/data/devicemap/devices.xml");
client.setDeviceFilePatchPath("/usr/local/data/devicemap/devicespatches.xml");

client.setBuilderPath("/usr/local/data/devicemap/builder.xml");

client.load();

-or-

DeviceMapClient client=new DeviceMapClient();

client.setCustomLoader(new CustomLoaderInterface());

With the 4th option, all the code you have below goes into an object which gets passed into the client and invoked. Personally, I think a *large* amount of our usage will fall into the 1st and 2nd use case with a small percentage hitting the 3rd and 4th.


________________________________
 From: Radu Cotescu <ra...@apache.org>
To: devicemap-dev <de...@incubator.apache.org>; Reza <re...@yahoo.com> 
Sent: Monday, June 24, 2013 2:29 PM
Subject: Re: devicemap java client cleanup
 


Hi,

Not really. A dev could just feed the DeviceMapClient a configuration map with InputStreams for the required data sources. Let's not limit ourselves to thinking only in file system abstractions and allow devs to build their own logic for loading some data sources.


This is how I thought to modify the DeviceMapClient:

public DeviceMapClient(Map<String, Object> configuration) throws InitialisationException, IOException {
        devices = new HashMap<String, Device>();
        patterns = new HashMap<String, Device>();

        Loader loader = new Loader();
        BufferedReader br;

        if (configuration == null || configuration.isEmpty()) {
            throw new InitialisationException("Cannot initialise the DeviceMapClient without a configuration map.");
        }

        InputStream builderDataSourceIS = (InputStream) configuration.get(DEVICE_DATA_SOURCE_PROP_NAME);
        if (builderDataSourceIS == null) {
            throw new InitialisationException(buildErrorMessageForIS(DEVICE_DATA_SOURCE_PROP_NAME));
        }
        br = new BufferedReader(new InputStreamReader(builderDataSourceIS));
        loader.loadDeviceData(br);
        builderDataSourceIS.close();

        InputStream builderDataSourcePatchIS = (InputStream) configuration.get(DEVICE_DATA_SOURCE_PATCH_PROP_NAME);
        if (builderDataSourcePatchIS != null) {
            br = new BufferedReader(new InputStreamReader(builderDataSourcePatchIS));
            loader.loadDeviceData(br);
            builderDataSourcePatchIS.close();
        }

        loader.setParentAttributes();

        InputStream deviceDataSourceIS = (InputStream) configuration.get(BUILDER_DATA_SOURCE_PROP_NAME);
        if (deviceDataSourceIS == null) {
            throw new InitialisationException(buildErrorMessageForIS(BUILDER_DATA_SOURCE_PROP_NAME));
        }
        br = new BufferedReader(new InputStreamReader(deviceDataSourceIS));
        loader.loadDevicePatterns(br);
        deviceDataSourceIS.close();

        InputStream deviceDataSourcePatchIS = (InputStream) configuration.get(BUILDER_DATA_SOURCE_PATCH_PROP_NAME);
        if (deviceDataSourcePatchIS != null) {
            br = new BufferedReader(new InputStreamReader(deviceDataSourcePatchIS));
            loader.loadDevicePatterns(br);
            deviceDataSourcePatchIS.close();
        }

        devices = loader.getDevices();
        createIndex();
    }

As you can see no one but us has to know the internal logics. A consumer would just have to provide a configuration object which can be thoroughly documented regarding its expected values.

Thanks,
Radu

On Mon, Jun 24, 2013 at 9:10 PM, Reza <re...@yahoo.com> wrote:

Right, so if you look in the DeviceMapClient, there is a convenience method:
>
>loadFromFolder(String folder)
>
>
>This is kind of a remnant from OpenDDR, but basically there is a resource folder that is filled with xml files. Simply point the client to the folder and it will do the rest. Remember, there are at least 4+ xml files which all contribute to the index. Also, there are several internal compilation steps which need to be done inbetween loading these files. Right, the actual names of the files should be configurable, just didnt get to that step yet.
>
>The optimal way to do this is to detect the DeviceMap data jar in the classpath and load the resources without asking the user.
>
>So what you are asking for is to expose the inner methods of the Loader and have the developer open the device and builder files and the patch files and manually feed them in? They then need to know when to kick off the internal compiling methods too. So this would all have to be exposed. Not sure if an off the shelf developer is going to be able to comprehend the inner guts of this package and properly execute all of this...
>
>The simplest approach would be to auto detect the resource jar and use it. Also, create a method for the developer to load files from the local file system. I think its reasonable to make the actual filenames configurable but having the developer drive the file loading and indexing doesn't seem like a good feature.
>
>Also, I just moved some classes around into a package hierarchy.
>
>
>
>________________________________
> From: Radu Cotescu <ra...@apache.org>
>To: devicemap-dev <de...@incubator.apache.org>
>Sent: Monday, June 24, 2013 1:57 PM
>Subject: Re: devicemap java client cleanup
>
>
>
>Hi Reza,
>
>
>> 1 and 2) There is a generic Loader (org.apache.devicemap.client.Loader)
>> which takes in Readers (like an inputstream but it has an encoding: UTF8).
>> FileLoader then wraps this and loads files and I was planning on creating a
>> JarLoader which will detect and load resources from a jar. So it should
>> probably be organized a bit better (interface and package), but I think if
>> there is a new loading method, just wrap Loader, no?
>
>
>Why should we provide multiple loaders and try to imagine all the use cases
>when we could have only one way to initialise the client? The final users
>of our client are developers. I'm sure they can wrap whatever type of data
>source into an InputStream - files from the file system, files from a JAR,
>JCR nodes, Apache Sling resources, URLs, etc.
>
>I'm in favour of keeping things as simple as possible.
>
>WDYT?
>
>Cheers,
>Radu

Re: devicemap java client cleanup

Posted by Radu Cotescu <ra...@apache.org>.
Hi,

Not really. A dev could just feed the DeviceMapClient a configuration map
with InputStreams for the required data sources. Let's not limit ourselves
to thinking only in file system abstractions and allow devs to build their
own logic for loading some data sources.

This is how I thought to modify the DeviceMapClient:

public DeviceMapClient(Map<String, Object> configuration) throws
InitialisationException, IOException {
        devices = new HashMap<String, Device>();
        patterns = new HashMap<String, Device>();

        Loader loader = new Loader();
        BufferedReader br;

        if (configuration == null || configuration.isEmpty()) {
            throw new InitialisationException("Cannot initialise the
DeviceMapClient without a configuration map.");
        }

        InputStream builderDataSourceIS = (InputStream)
configuration.get(DEVICE_DATA_SOURCE_PROP_NAME);
        if (builderDataSourceIS == null) {
            throw new
InitialisationException(buildErrorMessageForIS(DEVICE_DATA_SOURCE_PROP_NAME));
        }
        br = new BufferedReader(new InputStreamReader(builderDataSourceIS));
        loader.loadDeviceData(br);
        builderDataSourceIS.close();

        InputStream builderDataSourcePatchIS = (InputStream)
configuration.get(DEVICE_DATA_SOURCE_PATCH_PROP_NAME);
        if (builderDataSourcePatchIS != null) {
            br = new BufferedReader(new
InputStreamReader(builderDataSourcePatchIS));
            loader.loadDeviceData(br);
            builderDataSourcePatchIS.close();
        }

        loader.setParentAttributes();

        InputStream deviceDataSourceIS = (InputStream)
configuration.get(BUILDER_DATA_SOURCE_PROP_NAME);
        if (deviceDataSourceIS == null) {
            throw new
InitialisationException(buildErrorMessageForIS(BUILDER_DATA_SOURCE_PROP_NAME));
        }
        br = new BufferedReader(new InputStreamReader(deviceDataSourceIS));
        loader.loadDevicePatterns(br);
        deviceDataSourceIS.close();

        InputStream deviceDataSourcePatchIS = (InputStream)
configuration.get(BUILDER_DATA_SOURCE_PATCH_PROP_NAME);
        if (deviceDataSourcePatchIS != null) {
            br = new BufferedReader(new
InputStreamReader(deviceDataSourcePatchIS));
            loader.loadDevicePatterns(br);
            deviceDataSourcePatchIS.close();
        }

        devices = loader.getDevices();
        createIndex();
    }

As you can see no one but us has to know the internal logics. A consumer
would just have to provide a configuration object which can be thoroughly
documented regarding its expected values.

Thanks,
Radu

On Mon, Jun 24, 2013 at 9:10 PM, Reza <re...@yahoo.com> wrote:

> Right, so if you look in the DeviceMapClient, there is a convenience
> method:
>
> loadFromFolder(String folder)
>
>
> This is kind of a remnant from OpenDDR, but basically there is a resource
> folder that is filled with xml files. Simply point the client to the folder
> and it will do the rest. Remember, there are at least 4+ xml files which
> all contribute to the index. Also, there are several internal compilation
> steps which need to be done inbetween loading these files. Right, the
> actual names of the files should be configurable, just didnt get to that
> step yet.
>
> The optimal way to do this is to detect the DeviceMap data jar in the
> classpath and load the resources without asking the user.
>
> So what you are asking for is to expose the inner methods of the Loader
> and have the developer open the device and builder files and the patch
> files and manually feed them in? They then need to know when to kick off
> the internal compiling methods too. So this would all have to be exposed.
> Not sure if an off the shelf developer is going to be able to comprehend
> the inner guts of this package and properly execute all of this...
>
> The simplest approach would be to auto detect the resource jar and use it.
> Also, create a method for the developer to load files from the local file
> system. I think its reasonable to make the actual filenames configurable
> but having the developer drive the file loading and indexing doesn't seem
> like a good feature.
>
> Also, I just moved some classes around into a package hierarchy.
>
>
> ________________________________
>  From: Radu Cotescu <ra...@apache.org>
> To: devicemap-dev <de...@incubator.apache.org>
> Sent: Monday, June 24, 2013 1:57 PM
> Subject: Re: devicemap java client cleanup
>
>
> Hi Reza,
>
>
> > 1 and 2) There is a generic Loader (org.apache.devicemap.client.Loader)
> > which takes in Readers (like an inputstream but it has an encoding:
> UTF8).
> > FileLoader then wraps this and loads files and I was planning on
> creating a
> > JarLoader which will detect and load resources from a jar. So it should
> > probably be organized a bit better (interface and package), but I think
> if
> > there is a new loading method, just wrap Loader, no?
>
>
> Why should we provide multiple loaders and try to imagine all the use cases
> when we could have only one way to initialise the client? The final users
> of our client are developers. I'm sure they can wrap whatever type of data
> source into an InputStream - files from the file system, files from a JAR,
> JCR nodes, Apache Sling resources, URLs, etc.
>
> I'm in favour of keeping things as simple as possible.
>
> WDYT?
>
> Cheers,
> Radu
>

Re: devicemap java client cleanup

Posted by Reza <re...@yahoo.com>.
Right, so if you look in the DeviceMapClient, there is a convenience method:

loadFromFolder(String folder)


This is kind of a remnant from OpenDDR, but basically there is a resource folder that is filled with xml files. Simply point the client to the folder and it will do the rest. Remember, there are at least 4+ xml files which all contribute to the index. Also, there are several internal compilation steps which need to be done inbetween loading these files. Right, the actual names of the files should be configurable, just didnt get to that step yet.

The optimal way to do this is to detect the DeviceMap data jar in the classpath and load the resources without asking the user.

So what you are asking for is to expose the inner methods of the Loader and have the developer open the device and builder files and the patch files and manually feed them in? They then need to know when to kick off the internal compiling methods too. So this would all have to be exposed. Not sure if an off the shelf developer is going to be able to comprehend the inner guts of this package and properly execute all of this...

The simplest approach would be to auto detect the resource jar and use it. Also, create a method for the developer to load files from the local file system. I think its reasonable to make the actual filenames configurable but having the developer drive the file loading and indexing doesn't seem like a good feature.

Also, I just moved some classes around into a package hierarchy.


________________________________
 From: Radu Cotescu <ra...@apache.org>
To: devicemap-dev <de...@incubator.apache.org> 
Sent: Monday, June 24, 2013 1:57 PM
Subject: Re: devicemap java client cleanup
 

Hi Reza,


> 1 and 2) There is a generic Loader (org.apache.devicemap.client.Loader)
> which takes in Readers (like an inputstream but it has an encoding: UTF8).
> FileLoader then wraps this and loads files and I was planning on creating a
> JarLoader which will detect and load resources from a jar. So it should
> probably be organized a bit better (interface and package), but I think if
> there is a new loading method, just wrap Loader, no?


Why should we provide multiple loaders and try to imagine all the use cases
when we could have only one way to initialise the client? The final users
of our client are developers. I'm sure they can wrap whatever type of data
source into an InputStream - files from the file system, files from a JAR,
JCR nodes, Apache Sling resources, URLs, etc.

I'm in favour of keeping things as simple as possible.

WDYT?

Cheers,
Radu

Re: devicemap java client cleanup

Posted by Radu Cotescu <ra...@apache.org>.
Hi Reza,


> 1 and 2) There is a generic Loader (org.apache.devicemap.client.Loader)
> which takes in Readers (like an inputstream but it has an encoding: UTF8).
> FileLoader then wraps this and loads files and I was planning on creating a
> JarLoader which will detect and load resources from a jar. So it should
> probably be organized a bit better (interface and package), but I think if
> there is a new loading method, just wrap Loader, no?


Why should we provide multiple loaders and try to imagine all the use cases
when we could have only one way to initialise the client? The final users
of our client are developers. I'm sure they can wrap whatever type of data
source into an InputStream - files from the file system, files from a JAR,
JCR nodes, Apache Sling resources, URLs, etc.

I'm in favour of keeping things as simple as possible.

WDYT?

Cheers,
Radu

Re: devicemap java client cleanup

Posted by Reza <re...@yahoo.com>.
1 and 2) There is a generic Loader (org.apache.devicemap.client.Loader) which takes in Readers (like an inputstream but it has an encoding: UTF8). FileLoader then wraps this and loads files and I was planning on creating a JarLoader which will detect and load resources from a jar. So it should probably be organized a bit better (interface and package), but I think if there is a new loading method, just wrap Loader, no?

3) sure

4) yes, we need a test framework. Right now im using org.apache.devicemap.client.Main for benchmarks and testing.


________________________________
 From: Radu Cotescu <ra...@apache.org>
To: devicemap-dev <de...@incubator.apache.org> 
Sent: Monday, June 24, 2013 1:26 PM
Subject: devicemap java client cleanup
 

Hi devs,

On Thursday I'm invited to talk at meeting no. 13 of the Bucharest Java
User Group [1]. I've decided to tell people about our efforts of providing
tools for client detection, both server-side and client-side.

Since it's trivial to write a web app on top of Apache Sling for my demo
I've decided to use the new client written by Reza because it's a hell lot
easier to modify it for an OSGi environment compared to the current OpenDDR
donated code.

However, in order to make the jar file more friendly, I do need to change a
few things:

   1. the DeviceMapClient initialisation should be performed with the help
   of a configuration Map<String, Object> - I need to be able to pass
   InputStreams instead of having the code look for files on a file system;
   this way the driver code can do whatever it wants as long as it provides
   InputStreams
   2. 1 implies that we don't need the FileLoader class any more
   3. delete the Util.log (now called debugLog) method and pass all the
   logging stuff to SLF4J
   4. maybe replace Main.java with a test (already covered in my changeset)
   ?

Would anyone mind if I commit the previously mentioned changes?

Thanks,
Radu

[1] - http://www.bjug.ro/editii/13.html