You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pivot.apache.org by Chris Bartlett <cb...@gmail.com> on 2011/07/02 23:36:33 UTC

Idea for a useful change to BXMLSerializer

Firstly, my apologies for the length of this email (and if there are
lots of typos).  It might be easier to just jump to the example BXML
fragments which demonstrate possibilities of the proposed change, and
then skip back to the more wordy stuff.

I will post some proof of concept code in the morning if there is any
interest in this.


* Notes
The examples are meant to demonstrate ideas, so might seem a little contrived.
Although Transformables are designed to be triggered by
BXMLSerializer, they can just as easily be used programmatically.
The transform() method could be provided with a specific classloader
by BXMLSerializer if required


* References
http://pivot.apache.org/tutorials/bxml-primer.html
Specifically the section titled 'Class Instances'

http://svn.apache.org/repos/asf/pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java


* Summary
Make a backwardly compatible change to BXMLSerializer to enable
support for a simple 'Transformable<T>' interface.

public interface Transformable<T> {
    public Collection<T> transform();
}

The interface would have a single method named 'transform()' which
would return a java.util.Collection<T>.

A bean implementing the interface would be constructed as normal by
BXMLSerializer, but would have its 'transform()' method called when
the bean would usually be returned (if it was the root element) or
added to the parent object somehow (if it had a parent).

If the bean is the root element, the Collection would be returned as
the result of the BXMLSerializer.readObject(InputStream) method;

If the bean is not the root element, BXMLSerializer would the iterate
over the items in the returned Collection and process them in exactly
the same way as the original bean would have been processed.

i.e. If the original bean was going to be added to a Sequence defined
by a DefaultProperty, then each of the items in the Collection would
be added to the same Sequence instead.

i.e. If the original bean was going to be set as the value for a
writeable property, each of the items in the Collection would be set
as values for the same writeable property, in the order defined by the
Collection's iterator)


* What difference would that make?
This simple change would provide flexibility by allowing a special
type of 'Class Instance' (an implementation of Transformable) to
decide how many items to return (and of what types) when it is
'created', rather than exactly 1 object as currently happens.


* How could that help me?
It essentially turns Transformable objects into macros that can
perform arbitrary tasks.



Example 1 - User defined, simplified API for creating object graphs

This is the original problem that lead to the proposed idea.
Being able to create simplified APIs for Pivot Components means that
designers could be provided with a much smaller and simpler 'toolkit'
to work with.  Having a smaller API would also be helpful for people
who add in auto-complete functionality into their editor tools.
Even just the ability to refer to a Component by a different name can
be very useful, especially when there are similarly named widgets in
various UI frameworks.

<!-- This would create and populate a layout without needing to know
how it was being implemented behind the scenes -->
<ThreeColumnLayout>
  <leftColumn>
    ...
  </leftColumn>
  <middleColumn>
    ...
  </middleColumn>
  <rightColumn>
    ...
  </rightColumn>
</ThreeColumnLayout>


Here is a more complete example...

TablePaneBuilder implements Transformable<TablePane> and has 'columns'
and 'components' properties.  The latter being a Sequence<Component>
annotated as the DefaultProperty.  Its 'transform()' method returns a
newly created TablePane with the requested number of columns, and
sufficient rows to populate the cells using the supplied Components.

@DefaultProperty("components")
public class TablePaneBuilder implements Transformable<TablePane> {

    private final List<Component> components = new ArrayList<Component>();
    private int columns = 1;

    public Sequence<Component> getComponents() {
        return components;
    }

    public int getColumns() {
        return columns;
    }
    public void setColumns(int columns) {
        if (columns < 1) {
            throw new IllegalArgumentException();
        }
        this.columns = columns;
    }

    @Override
    public Collection<TablePane> transform() {
        final TablePane tablePane = new TablePane();
        for (int i = 0; i < columns; i++) {
            tablePane.getColumns().add(new Column());
        }
        TablePane.Row row = null;
        for (Component component : components) {
            if (row == null || row.getLength() == columns) {
                row = new TablePane.Row();
                tablePane.getRows().add(row);
            }
            row.add(component);
        }
        return Arrays.asList(tablePane);
    }
}

Usage in BXML
<TablePaneBuilder columns="2" >
  <!-- Row 1 -->
  <wtk:Label text="Label 1" />
  <wtk:Label text="Label 2" />

  <!-- Row 2 -->
  <wtk:PushButton buttonData="PushButton 1" />
  <wtk:PushButton buttonData="PushButton 2" />

  <!-- Row 3 -->
  <wtk:TextInput text="TextInput 1" />
  <wtk:TextInput text="TextInput 2" />
</TablePaneBuilder>



Example 2 - Ability to instantiate classes which do not have a no-arg
constructor

public final class UnfriendlyPOJO {
    public final int mandatory;
    public UnfriendlyPOJO(int mandatory) {
        this.mandatory = mandatory;
    }
}

public class UnfriendlyPOJOBuilder implements Transformable<UnfriendlyPOJO> {
    private int mandatory;
    public int getMandatory() {
        return mandatory;
    }
    public void setMandatory(int mandatory) {
        this.mandatory = mandatory;
    }

    @Override
    public Collection<UnfriendlyPOJO> transform() {
        return Arrays.asList(new UnfriendlyPOJO(mandatory));
    }
}


<UnfriendlyPOJOBuilder mandatory="99" />



Example 3 - Can be used to hide attribute ordering restrictions

This BXML will work, as the selectedIndex is being set once the
ListView has data
<wtk:ListView listData="['One', 'Two', 'Three']" selectedIndex="0"/>

But this BXML will fail, as the selectedIndex is being set before the
ListView has data
<wtk:ListView selectedIndex="0" listData="['One', 'Two', 'Three']"/>


@DefaultProperty("listView")
public class ListViewBuilder implements Transformable<ListView> {
    private final ListView listView = new ListView();
    private int selectedIndex;
    private List<?> listData;

    public int getSelectedIndex() {
        return selectedIndex;
    }
    public void setSelectedIndex(int selectedIndex) {
        this.selectedIndex = selectedIndex;
    }

    public void setListData(String listData) {
        try {
            this.listData = JSONSerializer.parseList(listData);
        } catch (SerializationException exception) {
            throw new IllegalArgumentException(exception);
        }
    }

    @Override
    public Collection<ListView> transform() {
        listView.setListData(listData);
        // Ensure that the index selection happens after the list population
        listView.setSelectedIndex(selectedIndex);
        return Arrays.asList(listView);
    }
}

<ListViewBuilder selectedIndex="0" listData="['One', 'Two', 'Three']" />



Example 4 - Provide similar functionality to named styles only for properties

The same could essentially be achieved by subclassing a Component and
hard coding some properties into its constructor.
Using a Transformable is another option, and could also be used with
final classes.

@DefaultProperty("textInput")
public class PasswordInput implements Transformable<TextInput> {
    private TextInput textInput = null;
    public void setTextInput(TextInput textInput) {
        this.textInput = textInput;
    }

    @Override
    public Collection<TextInput> transform() {
        if (textInput == null) {
            textInput = new TextInput();
        }
        textInput.setPassword(true);
        textInput.setPrompt("Enter password");
        return Arrays.asList(textInput);
    }
}

<!-- Creates and returns a new TextInput -->
<PasswordInput />
<!-- Uses the supplied TextInput -->
<PasswordInput>
  <wtk:TextInput tooltipText="Using supplied TextInput" text="secret" />
</PasswordInput>


This idea can be taken further by a Transformable that 'clones'
specified objects (0..n times).
It would create new instances based on the supplied source objects,
and then iterate over the source's properties and styles while setting
the same values on the newly created 'clone'.  (I knocked up a working
example of this in about 20 mins)



Example 5 - Transformable that returns an empty Collection

This could be used to conditionally include sections of BXML file
based on any arbitrary logic.
(Result of a webquery, result of a JVM scripting function, JVM
version, availability of classes on the classpath, Operating System,
user name etc)
If the critera is met, the Transformable would return a Collection
containing the BXML, otherwise just an empty Collection.

<WindowsOS>
  <WindowsWidget />
  <bxml:reference id="$commonToAllOperatingSystems"/>
  ...
</WindowsOS>
<MacOS>
  <MacWidget />
  <bxml:reference id="$commonToAllOperatingSystems"/>
  ...
</MacOS>



Example 6 - Enhanced BXML include

<!-- Include all files that match the regular expression or wildcard
syntax, retrieving them asynchronously -->
<Include async="true" regex="/path/to/bxml/files/widget[5-7].bxml" />

or even

<Async>
  <Include regex="/path/to/bxml/files/widget[5-7].bxml" />
</Async>

The Async would queue a callback to populate the same position with
data once it had been retrieved from a potentially slow source.
(This is just an example of the sorts of options which are made
available by this change - not a proposal to create such a new
'Includer')



Example 7 - Dynamic UI creation (think automatic CRUD forms for a POJO/bean)

<!-- Show a 'person' bean in a form -->
<FormBuilder editable="true" source="$person" fieldOrder="['id',
'title', 'firstName', 'lastName', 'age']" />
or
<!-- Show a 'person' bean in a name/value TableView where the values
are editable -->
<TableViewBuilder editable="true" source="$person" fieldOrder="['id',
'title', 'firstName', 'lastName', 'age']" />

(These examples are for generic XXXBuilders, but they could obviously
have internal knowledge of certain types.)



Example 8 - Reuseable and sharable

Due to the simplicity of the interface, Transformables can easily be
shared among Pivot developers.
This could lead to an online repository of reuseable components (even
just wiki pages of source).

There have been many mailing list questions about how to achieve
particular layouts.
Common layouts could be implemented as Transformables and mailed to
the list for easy reuse.

(I suppose Transformables could be considered similar to a JSP tag library)


Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Better naming options might be

public interface Command<T> {
   public Collection<T> execute();
}

or

public interface Function<T> {
   public Collection<T> execute();
}


On 3 July 2011 04:36, Chris Bartlett <cb...@gmail.com> wrote:
> public interface Transformable<T> {
>    public Collection<T> transform();
> }

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
Makes sense to me. The skunk branch is a perfect place for such prototyping.

On Jul 9, 2011, at 6:06 AM, Noel Grandin wrote:

> I'm liking the level of discussion going on here - it shows that we have
> people with passion in this project, which is awesome.
> 
> A while ago we used to have branches in the repo for each committer, where
> that committer could push prototypes and proposed changes - discussions are
> a lot easier when the code is visible and browseable.
> 
> I think the appropriate place for that would be in the main repo under the
> existing /skunk directory.
> Create a directory like /skunk/cbartlett and go wild.
> 
> Greg, what do you think?
> 
> -- Noel


Re: Idea for a useful change to BXMLSerializer

Posted by Noel Grandin <no...@gmail.com>.
I'm liking the level of discussion going on here - it shows that we have
people with passion in this project, which is awesome.

A while ago we used to have branches in the repo for each committer, where
that committer could push prototypes and proposed changes - discussions are
a lot easier when the code is visible and browseable.

I think the appropriate place for that would be in the main repo under the
existing /skunk directory.
Create a directory like /skunk/cbartlett and go wild.

Greg, what do you think?

-- Noel

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> Den 09.07.2011 15:25, skrev Greg Brown:
>> It is theoretically possible to serialize a component hierarchy into BXML. The challenge would be handling includes, script, and define blocks, which are not intrinsically part of the UI. These elements would need to be attached to their associated objects somehow so that BXMLSerializer#writeObject() would know how to handle them.
> 
> I didn't think of that. For a GUI builder there isn't really a need to create the BXML from an object, it can be solely based on the BXML file I guess. Probably much easier and cleaner.

Yeah, that's typically where I end up whenever I start thinking about GUI builders, too.  :-)


Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.
Den 09.07.2011 15:25, skrev Greg Brown:
> It is theoretically possible to serialize a component hierarchy into BXML. The challenge would be handling includes, script, and define blocks, which are not intrinsically part of the UI. These elements would need to be attached to their associated objects somehow so that BXMLSerializer#writeObject() would know how to handle them.

I didn't think of that. For a GUI builder there isn't really a need to 
create the BXML from an object, it can be solely based on the BXML file 
I guess. Probably much easier and cleaner.

-- Edvin

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
It is theoretically possible to serialize a component hierarchy into BXML. The challenge would be handling includes, script, and define blocks, which are not intrinsically part of the UI. These elements would need to be attached to their associated objects somehow so that BXMLSerializer#writeObject() would know how to handle them.

On Jul 9, 2011, at 9:16 AM, SYSE | Edvin wrote:

> Den 09.07.2011 14:13, skrev Greg Brown:
>> OK, thanks for clarifying. I hadn't really considered it before, but I think I agree that serialization should be reciprocal. And yes, it does seem like mutating the input stream would violate that reciprocity (though, at the moment, BXMLSerializer does not support writeObject(), so it is sort of an academic issue).
> 
> Wonder if that would be a cool way to create a GUI-builder for Pivot - build the GUI and save it with BXMLSerializer#writeObject :) Pivot has a giant advantage to Swing in this respect, as almost all Swing GUI builders create code that is hard/painful to maintain, or use some proprietary file format. The BXML could however probably be created almost identical to what one would write manually.


Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.
Den 09.07.2011 14:13, skrev Greg Brown:
> OK, thanks for clarifying. I hadn't really considered it before, but I think I agree that serialization should be reciprocal. And yes, it does seem like mutating the input stream would violate that reciprocity (though, at the moment, BXMLSerializer does not support writeObject(), so it is sort of an academic issue).

Wonder if that would be a cool way to create a GUI-builder for Pivot - 
build the GUI and save it with BXMLSerializer#writeObject :) Pivot has a 
giant advantage to Swing in this respect, as almost all Swing GUI 
builders create code that is hard/painful to maintain, or use some 
proprietary file format. The BXML could however probably be created 
almost identical to what one would write manually.

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
OK, thanks for clarifying. I hadn't really considered it before, but I think I agree that serialization should be reciprocal. And yes, it does seem like mutating the input stream would violate that reciprocity (though, at the moment, BXMLSerializer does not support writeObject(), so it is sort of an academic issue).
G

On Jul 9, 2011, at 6:08 AM, SYSE | Edvin wrote:

> Den 08.07.2011 21:28, skrev Greg Brown:
>>> Den 08.07.2011 21:04, skrev Greg Brown:
>>>> Sorry, I wasn't clear either.  :-)  I should have asked "what do you mean by 'it'"? In other words, what do you think breaks the contract defined by Serializer?
>>> 
>>> That's what I tried to say with this sentence:
>>> 
>>> "If you write an object you expect to get the same object back when you read back the stream you wrote earlier. If you add some mutator to it, that's not serialization anymore, that's something else IMHO".
>> 
>> Right, I read that but I wasn't sure what you were getting at. What specifically do you think would violate this reciprocity?
> 
> The first principle I think of when I hear the word Serializer, is that you can write an object, and later read that same object back again. Even if you do it over and over, you'd still get the same object.
> 
> If the "ebxml" file mutates the object, let's say to create a collection somewhere in the hierarchy, then writing this object back to "ebxml" again would probably describe a collection instead of the original markup that described an object to be mutated, right? The collection won't have information on it to be able to reverse-engineer it back to the same state when writeObject is called.
> 
> -- Edvin
> 
> 


Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.
Den 08.07.2011 21:28, skrev Greg Brown:
>> Den 08.07.2011 21:04, skrev Greg Brown:
>>> Sorry, I wasn't clear either.  :-)  I should have asked "what do you mean by 'it'"? In other words, what do you think breaks the contract defined by Serializer?
>>
>> That's what I tried to say with this sentence:
>>
>> "If you write an object you expect to get the same object back when you read back the stream you wrote earlier. If you add some mutator to it, that's not serialization anymore, that's something else IMHO".
>
> Right, I read that but I wasn't sure what you were getting at. What specifically do you think would violate this reciprocity?

The first principle I think of when I hear the word Serializer, is that 
you can write an object, and later read that same object back again. 
Even if you do it over and over, you'd still get the same object.

If the "ebxml" file mutates the object, let's say to create a collection 
somewhere in the hierarchy, then writing this object back to "ebxml" 
again would probably describe a collection instead of the original 
markup that described an object to be mutated, right? The collection 
won't have information on it to be able to reverse-engineer it back to 
the same state when writeObject is called.

-- Edvin



Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> Den 08.07.2011 21:04, skrev Greg Brown:
>> Sorry, I wasn't clear either.  :-)  I should have asked "what do you mean by 'it'"? In other words, what do you think breaks the contract defined by Serializer?
> 
> That's what I tried to say with this sentence:
> 
> "If you write an object you expect to get the same object back when you read back the stream you wrote earlier. If you add some mutator to it, that's not serialization anymore, that's something else IMHO".

Right, I read that but I wasn't sure what you were getting at. What specifically do you think would violate this reciprocity?




Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.
Den 08.07.2011 21:04, skrev Greg Brown:
> Sorry, I wasn't clear either.  :-)  I should have asked "what do you mean by 'it'"? In other words, what do you think breaks the contract defined by Serializer?

That's what I tried to say with this sentence:

"If you write an object you expect to get the same object back when you 
read back the stream you wrote earlier. If you add some mutator to it, 
that's not serialization anymore, that's something else IMHO".

-- Edvin


Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
Sorry, I wasn't clear either.  :-)  I should have asked "what do you mean by 'it'"? In other words, what do you think breaks the contract defined by Serializer?

On Jul 8, 2011, at 2:56 PM, SYSE | Edvin wrote:

> 
> 
> Den 08.07.2011 19:38, skrev Greg Brown:
>>> It atleast breaks with BXMLSerializer, but one could argue it breaks with Serializer as well
>> 
>> Can you clarify what you mean by "breaks" here?
> 
> I mean "breaks the contract of", or "goes outside the scope of" the original intent. Sorry for the bad language :)
> 
> -- Edvin


Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.

Den 08.07.2011 19:38, skrev Greg Brown:
>> It atleast breaks with BXMLSerializer, but one could argue it breaks with Serializer as well
>
> Can you clarify what you mean by "breaks" here?

I mean "breaks the contract of", or "goes outside the scope of" the 
original intent. Sorry for the bad language :)

-- Edvin

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> It atleast breaks with BXMLSerializer, but one could argue it breaks with Serializer as well

Can you clarify what you mean by "breaks" here?



Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.
Den 08.07.2011 19:00, skrev Greg Brown:
>> "that the Serializer interface encapsulates." ->  "what the Serializer interface encapsulates."
>>
>> As you stated earlier, the Serializer is not supposed to perform transformations and such, just create object instances based on the source. Chris's suggestions might go beyond what the Serializer contract describes.
>
> I assume you are talking about BXMLSerializer specifically, rather than the Serializer interface? The Serializer contract is simply:
>
> - Given an input stream, return an object
> - Given an object and an output stream, write the object
>
> BXMLSerializer specifically returns the object represented by the root element of the BXML document. Other serializers obviously deserialize objects via different means, but they all return a single object. Serializers that need to return multiple objects can simply return a collection. For example, JSONSerializer returns a List when it reads "[0, 1, 2]", and BXMLSerializer will return an ArrayList if the root element of the document is<ArrayList>.

It atleast breaks with BXMLSerializer, but one could argue it breaks 
with Serializer as well - if you write an object you expect to get the 
same object back when you read back the stream you wrote earlier. If you 
add some mutator to it, that's not serialization anymore, that's 
something else IMHO :)

-- Edvin

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> "that the Serializer interface encapsulates." -> "what the Serializer interface encapsulates."
> 
> As you stated earlier, the Serializer is not supposed to perform transformations and such, just create object instances based on the source. Chris's suggestions might go beyond what the Serializer contract describes.

I assume you are talking about BXMLSerializer specifically, rather than the Serializer interface? The Serializer contract is simply: 

- Given an input stream, return an object
- Given an object and an output stream, write the object

BXMLSerializer specifically returns the object represented by the root element of the BXML document. Other serializers obviously deserialize objects via different means, but they all return a single object. Serializers that need to return multiple objects can simply return a collection. For example, JSONSerializer returns a List when it reads "[0, 1, 2]", and BXMLSerializer will return an ArrayList if the root element of the document is <ArrayList>.


Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.
Den 08.07.2011 18:34, skrev Greg Brown:
>>> I would just use my custom version of BXMLSerializer to process all
>>> BXML files whether they are official '.bxml' files or '.ebxml'
>>> If the BXML file doesn't contain any 'Transformable' objects, then it
>>> will behave in exactly the same way as the official BXMLSerializer.
>>
>> I think this kind of forking could be a healthy way to add "exotic" features that might skew the perception of that the Serializer interface encapsulates.
>
> Not sure what perception you are referring to. Can you clarify?
>
> IMO forking in any capacity is not "healthy". It only serves to fragment the code and community.

"that the Serializer interface encapsulates." -> "what the Serializer 
interface encapsulates."

As you stated earlier, the Serializer is not supposed to perform 
transformations and such, just create object instances based on the 
source. Chris's suggestions might go beyond what the Serializer contract 
describes.

 > Prototyping - yes. Forking - no.

I absolutely agree, but if Chris forks or otherwise adds this 
functionality to enhance "BXML to object creation", maybe his 
experiences could benefit BXMLSerializer or Pivot outside of 
BXMLSerializer in some way further down the road.

-- Edvin

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
OK. Thanks for clarifying. Carry on.  :-)

On Jul 8, 2011, at 3:02 PM, Chris Bartlett wrote:

> Greg,
> 
> Understood, and I think we are in general agreement, but things have
> gone off topic a little.
> 
> Hopefully you understand I am not proposing to fork anything merely
> for the sake of it.  Any decision to a fork would only come about
> after the collaboration process 'rejected' the proposal, but when the
> functionality might yet benefit (a potentially small number) of
> others.  If nobody cares about it, then it will remain in my private
> library.  If someone cares, and I have time, I am happy to make it
> public.
> 
> I originally asked if anyone was interested in the idea, but didn't
> attempt to force it upon anyone.  I personally see value in the
> flexibility, functionality and simplicity of it (subjective terms,
> obviously) and was simply asking if anyone else could find a use for
> it.  My feelings won't be hurt if the reception is just 'the sound of
> crickets, and tumbleweeds rolling by!' :)
> 
> If I do proceed with this publicly in any way, its purpose, future
> goals, dangers, possibilities etc will all be prominently stated.  As
> will the fact that it is based upon the sterling work of the Pivot
> contributors.  It would never be presented as anything other than a
> way to process BXML slightly differently, from the 'official' way.
> 
> However, even saying that makes it sound like a much bigger deal than
> anything I envisioned.  I was thinking of < 10 core classes bundled
> into a jar and potentially lots of reuseable 'Transformable'
> implementations hosted somewhere.  Certainly not a move to steal
> Pivot's thunder in any way.
> 
> Chris
> 
> 
> On 9 July 2011 01:21, Greg Brown <gk...@verizon.net> wrote:
>> By the way, I don't mean to be preachy - I'm just saying that, if you think you have a good idea, then put it out there and let it get tossed around a bit. From my experience, that's the best way to reach a solution that everyone is happy with.
>> 
>> On Jul 8, 2011, at 2:14 PM, Greg Brown wrote:
>> 
>>> What I'm trying to say is that, even though collaboration may be difficult at times, it generally produces a better result than the efforts of multiple individuals working independently. Just because I may not agree with all aspects of a change you propose (or vice versa) does not mean that I don't see any value in it. By discussing a proposed change in the open, that value can generally be drawn out. In my opinion, choosing to fork rather than collaborate is simply counter to the spirit of the ASF.
>>> 
>>> G
>>> 
>> 
>> 


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Greg,

Understood, and I think we are in general agreement, but things have
gone off topic a little.

Hopefully you understand I am not proposing to fork anything merely
for the sake of it.  Any decision to a fork would only come about
after the collaboration process 'rejected' the proposal, but when the
functionality might yet benefit (a potentially small number) of
others.  If nobody cares about it, then it will remain in my private
library.  If someone cares, and I have time, I am happy to make it
public.

I originally asked if anyone was interested in the idea, but didn't
attempt to force it upon anyone.  I personally see value in the
flexibility, functionality and simplicity of it (subjective terms,
obviously) and was simply asking if anyone else could find a use for
it.  My feelings won't be hurt if the reception is just 'the sound of
crickets, and tumbleweeds rolling by!' :)

If I do proceed with this publicly in any way, its purpose, future
goals, dangers, possibilities etc will all be prominently stated.  As
will the fact that it is based upon the sterling work of the Pivot
contributors.  It would never be presented as anything other than a
way to process BXML slightly differently, from the 'official' way.

However, even saying that makes it sound like a much bigger deal than
anything I envisioned.  I was thinking of < 10 core classes bundled
into a jar and potentially lots of reuseable 'Transformable'
implementations hosted somewhere.  Certainly not a move to steal
Pivot's thunder in any way.

Chris


On 9 July 2011 01:21, Greg Brown <gk...@verizon.net> wrote:
> By the way, I don't mean to be preachy - I'm just saying that, if you think you have a good idea, then put it out there and let it get tossed around a bit. From my experience, that's the best way to reach a solution that everyone is happy with.
>
> On Jul 8, 2011, at 2:14 PM, Greg Brown wrote:
>
>> What I'm trying to say is that, even though collaboration may be difficult at times, it generally produces a better result than the efforts of multiple individuals working independently. Just because I may not agree with all aspects of a change you propose (or vice versa) does not mean that I don't see any value in it. By discussing a proposed change in the open, that value can generally be drawn out. In my opinion, choosing to fork rather than collaborate is simply counter to the spirit of the ASF.
>>
>> G
>>
>
>

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
By the way, I don't mean to be preachy - I'm just saying that, if you think you have a good idea, then put it out there and let it get tossed around a bit. From my experience, that's the best way to reach a solution that everyone is happy with.

On Jul 8, 2011, at 2:14 PM, Greg Brown wrote:

> What I'm trying to say is that, even though collaboration may be difficult at times, it generally produces a better result than the efforts of multiple individuals working independently. Just because I may not agree with all aspects of a change you propose (or vice versa) does not mean that I don't see any value in it. By discussing a proposed change in the open, that value can generally be drawn out. In my opinion, choosing to fork rather than collaborate is simply counter to the spirit of the ASF.
> 
> G
> 


Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
What I'm trying to say is that, even though collaboration may be difficult at times, it generally produces a better result than the efforts of multiple individuals working independently. Just because I may not agree with all aspects of a change you propose (or vice versa) does not mean that I don't see any value in it. By discussing a proposed change in the open, that value can generally be drawn out. In my opinion, choosing to fork rather than collaborate is simply counter to the spirit of the ASF.

G


Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> If a feature is not wanted by the 'main' project, but might be useful

> to others, then forking and making it public provides the feature to
> others who might be interested

If a proposed feature is truly useful to others, then I'd say that it should be considered for inclusion in the main project, not implemented in a forked, potentially incompatible, side project. It is up to the PMC to decide what constitutes a valuable feature. 

> If the project clearly states its purposes and intentions, especially
> if it is an experimental feature which is not intended to be merged
> back into the original source tree, then its use is a free choice for
> someone to make.  They can be made aware if there is no intention of
> maintaining ongoing compatibility, or furthering development past a
> certain point.

I agree with this. If something is clearly marked as experimental then there is most likely no harm in making it public.

G



Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
On 8 July 2011 23:34, Greg Brown <gk...@verizon.net> wrote:
>> I think this kind of forking could be a healthy way to add "exotic" features that might skew the perception of that the Serializer interface encapsulates.
>
> ...snip...
> IMO forking in any capacity is not "healthy". It only serves to fragment the code and community. Prototyping - yes. Forking - no.

As I asked before, what other option is there to forking if I, or
anyone else, wishes to share something derived from Pivot?  (Apologies
if I am misusing the term forking.)

If a feature is not wanted by the 'main' project, but might be useful
to others, then forking and making it public provides the feature to
others who might be interested (assuming that the licensing terms
allow it and are adhered to).  Keeping it private doesn't seem like a
solution that benefits anyone.

If the project clearly states its purposes and intentions, especially
if it is an experimental feature which is not intended to be merged
back into the original source tree, then its use is a free choice for
someone to make.  They can be made aware if there is no intention of
maintaining ongoing compatibility, or furthering development past a
certain point.  If it is of no interest to anyone, then nobody will
get hurt or confused.  The download counter on the hosting site might
just end up being a monument to the uselessness of the feature in the
first place. :)

The title of this thread sums up my intentions  - simply to suggest a
change that might be useful.  There has not been a huge amount of
interest in it, and even if there had been, I would be quite happy for
BXMLSerializer to remain unchanged if that is where the consensus was.

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
>> I would just use my custom version of BXMLSerializer to process all
>> BXML files whether they are official '.bxml' files or '.ebxml'
>> If the BXML file doesn't contain any 'Transformable' objects, then it
>> will behave in exactly the same way as the official BXMLSerializer.
> 
> I think this kind of forking could be a healthy way to add "exotic" features that might skew the perception of that the Serializer interface encapsulates.

Not sure what perception you are referring to. Can you clarify?

IMO forking in any capacity is not "healthy". It only serves to fragment the code and community. Prototyping - yes. Forking - no.

G


Re: Idea for a useful change to BXMLSerializer

Posted by SYSE | Edvin <es...@syse.no>.

Den 08.07.2011 17:25, skrev Chris Bartlett:
> Yes, 100%.    If it turns out to be as useful to me as my 15 min
> prototype suggested, I will start to use it, and will be happy to
> share it via an Apache Extras project or similar.
>
> I would just use my custom version of BXMLSerializer to process all
> BXML files whether they are official '.bxml' files or '.ebxml'
> If the BXML file doesn't contain any 'Transformable' objects, then it
> will behave in exactly the same way as the official BXMLSerializer.

I think this kind of forking could be a healthy way to add "exotic" 
features that might skew the perception of that the Serializer interface 
encapsulates.

-- Edvin

Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
(Switched from the  'org.apache.pivot.util.MessageBus' thread to avoid
taking it off topic)

On 8 July 2011 22:04, SYSE | Edvin <es...@syse.no> wrote:
> As for BXMLSerializer, it looks like it is used mainly in demos/tutorials,
> some skin/internal stuff etc, but quite frankly - couldn't you just fork
> BXMLSerializer in your project and add all your goodies to it, and use it on
> your .ebxml (extended bxml :) files without problems? :)
>
> No Pivot internal code would try to read your ebxml files anyway right?

Yes, 100%.    If it turns out to be as useful to me as my 15 min
prototype suggested, I will start to use it, and will be happy to
share it via an Apache Extras project or similar.

I would just use my custom version of BXMLSerializer to process all
BXML files whether they are official '.bxml' files or '.ebxml'
If the BXML file doesn't contain any 'Transformable' objects, then it
will behave in exactly the same way as the official BXMLSerializer.

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
I just mean that if project A includes some source derived from
project B, but does not maintain any dependency on project B, then
project B can do whatever it wants with no impact on project A.

On 8 July 2011 21:05, Greg Brown <gk...@verizon.net> wrote:
> I must be misunderstanding what you mean by "standalone". Do you mean an application that is tied to a specific version of the Pivot platform? If so, then yes, you are correct - but that obviously has other disadvantages.
>
> On Jul 8, 2011, at 10:00 AM, Chris Bartlett wrote:
>
>>>> Any changes in the original source tree wouldn't stop a
>>>> standalone forked project from functioning
>>>
>>> Not true. Changes in a future release could easily break the forked code.
>>
>> 'standalone'
>
>

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
I must be misunderstanding what you mean by "standalone". Do you mean an application that is tied to a specific version of the Pivot platform? If so, then yes, you are correct - but that obviously has other disadvantages.

On Jul 8, 2011, at 10:00 AM, Chris Bartlett wrote:

>>> Any changes in the original source tree wouldn't stop a
>>> standalone forked project from functioning
>> 
>> Not true. Changes in a future release could easily break the forked code.
> 
> 'standalone'


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
>> Any changes in the original source tree wouldn't stop a
>> standalone forked project from functioning
>
> Not true. Changes in a future release could easily break the forked code.

'standalone'

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> Of course it is forking.  I thought that was too obvious to bother stating.
> 
> I feel that the 'opening the door to future incompatibility' bit was
> melodramatic.  

It was not meant to be. Forking is something that is generally discouraged at the ASF. It goes against the collaborative nature of open source. I just wanted to make that clear.

> Any changes in the original source tree wouldn't stop a
> standalone forked project from functioning

Not true. Changes in a future release could easily break the forked code.

> And any time I even extend a class (as suggested throughout this
> thread), be it from Pivot or elsewhere outside of my control, I am
> 'opening the door to future incompatibility'.

Possibly, but less likely. When you extend a class, you are operating within the bounds established by the class's designer. When you replace it, the same does not apply.





Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Greg,

Thanks for taking the time to reply.

I will definitely look into the possibilities offered by
newTypedObject().  If it can help me achieve some of my goals, I will
be happy.

I don't see any point in us trying to change the other's opinions, so
I'll leave things as they are - with the exception of clarifying this

>>> You can do this of course, but you'd basically be forking the code and opening the door to future incompatibility.
>> That is a little melodramatic considering it potentially concerns just
>> a few changes in a single class.
>
> It's not melodramatic - it's just accurate. If you copy a class and modify it without pushing those changes back into the main source tree, you have forked the code.
>
Of course it is forking.  I thought that was too obvious to bother stating.

I feel that the 'opening the door to future incompatibility' bit was
melodramatic.  Any changes in the original source tree wouldn't stop a
standalone forked project from functioning, and even if a fork was
never updated past the very first version, it could still provide
value.   This is testament to how much is possible with BXMLSerializer
now, and the work you (and others?) have done on it.

And any time I even extend a class (as suggested throughout this
thread), be it from Pivot or elsewhere outside of my control, I am
'opening the door to future incompatibility'.

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> - Instantiating a final class with no public no-arg constructor
> (UnfriendlyPOJO example)
> - Instantiating an immutable object (essentially the same as above)
> - Instantiating objects via a 'Builder' style pattern (similar to the above)
> - Retrieving objects via a factory (similar to previous items)

You are correct that none of these are directly supported, but you can accomplish them by subclassing BXMLSerializer and overriding newTypedObject(Class<?>).

> - Ability to return a different class to the one that would otherwise
> be instantiated (see the PasswordInput & TableBuilder examples)
> (This is similar to the first batch, but stresses a key concept)

You could use newTypedObject() to achieve this, but it seems like it would be really confusing. A big part of the value of BXML (in my opinion) is its opaqueness. Returning a different object than the one specified goes very much against that. 

> - Hiding attribute ordering restrictions from the end user (ListView example)

I must have missed this example so I'm not entirely sure what the use case is, but the order in which BXML's attributes are processed is quite deterministic. Attempting to circumvent it is more likely to cause confusion than anything else.

> - Ability to 'create' 0 or >1 objects
> See the conditional BXML inclusion example for when returning 0 items
> might be useful.

Again, this is by design. A serializer returns a single object. If you want to return multiple objects, have your serializer return a collection.

>>> The fact that it is a small, backwardly compatible change
>> FWIW, I don't see this as a small change.
> Obviously I respect your personal opinion on the size of the change,
> and know that you have far more experience with BXMLSerializer than I
> do.  Is there perhaps some fundamental problem that you can see but I
> might be overlooking?

It's not the literal size of the change (i.e. number of lines) but the nature of the change that I'm not really in favor of. From my perspective, many of the changes you propose are simply not in line with the intent of BXML.

>>> Because it is such a small change, and limited to BXMLSerializer, it
>>> would be easy to just push this into a tiny Apache Extras project as
>>> Sandro suggested.
>> 
>> You can do this of course, but you'd basically be forking the code and opening the door to future incompatibility.
> That is a little melodramatic considering it potentially concerns just
> a few changes in a single class.

It's not melodramatic - it's just accurate. If you copy a class and modify it without pushing those changes back into the main source tree, you have forked the code.

> And anyway, is there another option if it doesn't fit or belong with
> Pivot proper?

No, probably not. 

G


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Greg,

I have been away from my desk for the last 2 days, so apologies for
the delay, but this is the first chance I have had to reply.

Firstly, I want to clarify that my desire for functionality is the
driver here, and that I have no special attachment to the specifics of
the proposal.  Any other simple method to achieve the same things
would be welcomed with open arms.

Replies/questions in-line.


On 5 July 2011 21:59, Greg Brown <gk...@verizon.net> wrote:
>> You mention concerns, but do you see any value in i?  Whether in my examples or in other areas?
>
> If the same thing can be accomplished via existing means (which, based on your examples, seems possible), then I don't personally see a strong case for it.

Unless I am missing something, at least some of the provided examples
*cannot* be accomplished via existing means (whether by design or
otherwise).  Please correct me if I am mistaken, as I can think of
valid uses for all of the following, but don't know how to achieve any
with BXML.

- Instantiating a final class with no public no-arg constructor
(UnfriendlyPOJO example)
- Instantiating an immutable object (essentially the same as above)
- Instantiating objects via a 'Builder' style pattern (similar to the above)
- Retrieving objects via a factory (similar to previous items)

- Ability to return a different class to the one that would otherwise
be instantiated (see the PasswordInput & TableBuilder examples)
(This is similar to the first batch, but stresses a key concept)

- Hiding attribute ordering restrictions from the end user (ListView example)

- Ability to 'create' 0 or >1 objects
See the conditional BXML inclusion example for when returning 0 items
might be useful.
A dynamic GUI creation Transformable example might wish to return
multiple individual Components rather than a single parent Container.

>> The fact that it is a small, backwardly compatible change
> FWIW, I don't see this as a small change.
Obviously I respect your personal opinion on the size of the change,
and know that you have far more experience with BXMLSerializer than I
do.  Is there perhaps some fundamental problem that you can see but I
might be overlooking?

I don't imagine for a second that this is a panacea, but it offers many options.

> I also don't like the inconsistencies it would create (as outlined in my previous email).
What inconsistencies did you mean?  You mentioned the use of a
non-Pivot Collection, but that could clearly be changed to a Pivot one
or simply Object[].

Are you perhaps referring to the intent of the Serializer interface?
And that the result of 'creating' an item in BXML would depend on
whether the element represents a traditional Java bean class or a
Transformable implementation?

>> Because it is such a small change, and limited to BXMLSerializer, it
>> would be easy to just push this into a tiny Apache Extras project as
>> Sandro suggested.
>
> You can do this of course, but you'd basically be forking the code and opening the door to future incompatibility.
That is a little melodramatic considering it potentially concerns just
a few changes in a single class.
And anyway, is there another option if it doesn't fit or belong with
Pivot proper?

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> You mention concerns, but do you see any value in i?  Whether in my
> examples or in other areas?

If the same thing can be accomplished via existing means (which, based on your examples, seems possible), then I don't personally see a strong case for it.

> The fact that it is a small, backwardly compatible change

FWIW, I don't see this as a small change. I also don't like the inconsistencies it would create (as outlined in my previous email).

> Because it is such a small change, and limited to BXMLSerializer, it
> would be easy to just push this into a tiny Apache Extras project as
> Sandro suggested.

You can do this of course, but you'd basically be forking the code and opening the door to future incompatibility.

G


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Greg,

My replies are inline.
You mention concerns, but do you see any value in i?  Whether in my
examples or in other areas?

The fact that it is a small, backwardly compatible change (unless I
have missed something major) which offers many new possibilities and
alternatives is the big selling point for me.

Because it is such a small change, and limited to BXMLSerializer, it
would be easy to just push this into a tiny Apache Extras project as
Sandro suggested.
I intend to put my proof of concept code up there in the next 48 hours anyway.

Chris


On 5 July 2011 20:29, Greg Brown <gk...@verizon.net> wrote:
> That's an extensive proposal.
Well, an extensive email, but a very simple proposal IMHO.

>> <!-- This would create and populate a layout without needing to know
>> how it was being implemented behind the scenes -->
>> <ThreeColumnLayout>
>>  <leftColumn>
>>    ...
>>  </leftColumn>
>>  <middleColumn>
>>    ...
>>  </middleColumn>
>>  <rightColumn>
>>    ...
>>  </rightColumn>
>> </ThreeColumnLayout>
>
> Why not simply create a new component named ThreeColumnLayout that defines "leftColumn", "middleColumn", and "rightColumn" properties? It could either extend TablePane or use it internally in its skin.

I would argue that creating a new Component and/or skin would take
longer, require more Pivot experience and quite possibly require more
testing.  With such a simple interface, even novice users would be
able to use this to create very lightweight, standalone, aliases to
meet their specific needs.  If I know how to create an object graph in
BXML (or in Java, obviously), I can very quickly produce an 'alias'
for it.

I very quickly (5 mins) implemented the workaround for this issue into
a functioning 'alias'.
https://issues.apache.org/jira/browse/PIVOT-768

Ultimately though, it is also about choice and flexibility.  This is
an alternative that might well be preferable to some people, much like
using BXML might be preferable to constructing object graphs in Java.

>> This is the original problem that lead to the proposed idea.
>> Being able to create simplified APIs for Pivot Components means that
>> designers could be provided with a much smaller and simpler 'toolkit'
>> to work with.  Having a smaller API would also be helpful for people
>> who add in auto-complete functionality into their editor tools.
>
> Since all BXML properties are ultimately Bean properties, it should be possible to implement auto-complete via reflection. In this case, it shouldn't matter how many properties a component exposes.

I was thinking more about manually adding 'templates' here for the
auto-complete part, but that would be just as valid for a standard
Pivot Component.

The main point was that I can create my own custom subset of
lightweight aliases that include only the properties or styles that I
need or use.  This could prove very useful for instance when a new
member joins a team working on a Pivot app.  They would instantly be
able to see what is relevant for a certain scenario, merely because
the alias would only perform tasks that *were* relevant to its
purpose.


>> The interface would have a single method named 'transform()' which
>> would return a java.util.Collection<T>.
>
> This would be inconsistent with the rest of the Pivot API, which uses org.apache.pivot.collections.
Of course this could easily be switched to org.apache.pivot.*

I was thinking more in terms of how such a feature might be used, and
not wishing to impose the use of Pivot collections in a situation
where they wouldn't add any value.  ie Just a simple, short lived, bag
of items that would be returned and processed almost immediately
within the same class.


>> ...If the original bean was going to be set as the value for a
>> writeable property, each of the items in the Collection would be set
>> as values for the same writeable property, in the order defined by the
>> Collection's iterator)
>
> What would be the point of this? Why not just set the last one, since all of the previous values would be overwritten?
I was trying to explain the concept clearly, and not muddy the waters
by including optimizations (obvious or otherwise).
It also demonstrates that the change can be very unintrusive within
the BXMLSerializer code.


>> * What difference would that make?
>> This simple change would provide flexibility by allowing a special
>> type of 'Class Instance' (an implementation of Transformable) to
>> decide how many items to return (and of what types) when it is
>> 'created', rather than exactly 1 object as currently happens.
>
> The Serializer interface is designed to read and write a single object. If you need to read or write more values, you can just use a collection as your root object.
Yes, and that is part of the point.
It is currently 1:1, but perhaps there are valid use cases for 1:0, 1:1 & 1:n.
For example the 'conditional include' example I gave can choose to
return 0 items, and a 'repeater' class could clone or create a chunk
of a GUI and repeat it n times.


>> TablePaneBuilder implements Transformable<TablePane> and has 'columns'
>> and 'components' properties.  The latter being a Sequence<Component>
>> annotated as the DefaultProperty.  Its 'transform()' method returns a
>> newly created TablePane with the requested number of columns, and
>> sufficient rows to populate the cells using the supplied Components.
>
> The idea of supporting builders in BXML is not unreasonable. But I suspect that there are probably simpler ways to accomplish it.
Yes, there may well be *other* ways to accomplish this, but is this
way particularly offensive? :)
And is the provided TablePaneBuilder example not simple?



> FWIW, you mentioned Lombok later on in the thread. We had been using Lombok extensively on my current project but ultimately abandoned it because it made using an IDE more difficult. Since the properties are generated via annotation, the IDE can't see them and displays compiler errors in every file that refers to them.
Um, the Lombok properties/methods show up fine in Eclipse for me.  I
can't remember the current state of affairs, but think it supports at
least one other IDE too, NetBeans perhaps?  While I have had
occasional compilation issues, they have been limited to deep object
hierarchies, or large objects.

I tend to use it while prototyping and then 'delombok' once things are
more settled.

Chris
>
> G
>
>

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
Hi Chris,

That's an extensive proposal. You have obviously put a lot of thought into it. I'd have some concerns about the complexity and overall approach, though. I have tried to capture these in my comments below.

> Example 1 - User defined, simplified API for creating object graphs
> 
> <!-- This would create and populate a layout without needing to know
> how it was being implemented behind the scenes -->
> <ThreeColumnLayout>
>  <leftColumn>
>    ...
>  </leftColumn>
>  <middleColumn>
>    ...
>  </middleColumn>
>  <rightColumn>
>    ...
>  </rightColumn>
> </ThreeColumnLayout>

Why not simply create a new component named ThreeColumnLayout that defines "leftColumn", "middleColumn", and "rightColumn" properties? It could either extend TablePane or use it internally in its skin.

> This is the original problem that lead to the proposed idea.
> Being able to create simplified APIs for Pivot Components means that
> designers could be provided with a much smaller and simpler 'toolkit'
> to work with.  Having a smaller API would also be helpful for people
> who add in auto-complete functionality into their editor tools.

Since all BXML properties are ultimately Bean properties, it should be possible to implement auto-complete via reflection. In this case, it shouldn't matter how many properties a component exposes.

> Even just the ability to refer to a Component by a different name can
> be very useful, especially when there are similarly named widgets in
> various UI frameworks.

I agree that this would be handy. But I'd prefer to see it implemented as a Java language extension (i.e. typedefs for Java). Among other things, it would help simplify the use of generics, and would also help maintain backwards compatibility (when a class is moved or renamed, for example).

> The interface would have a single method named 'transform()' which
> would return a java.util.Collection<T>.

This would be inconsistent with the rest of the Pivot API, which uses org.apache.pivot.collections.

> ...If the original bean was going to be set as the value for a
> writeable property, each of the items in the Collection would be set
> as values for the same writeable property, in the order defined by the
> Collection's iterator)

What would be the point of this? Why not just set the last one, since all of the previous values would be overwritten?

> * What difference would that make?
> This simple change would provide flexibility by allowing a special
> type of 'Class Instance' (an implementation of Transformable) to
> decide how many items to return (and of what types) when it is
> 'created', rather than exactly 1 object as currently happens.

The Serializer interface is designed to read and write a single object. If you need to read or write more values, you can just use a collection as your root object.

> TablePaneBuilder implements Transformable<TablePane> and has 'columns'
> and 'components' properties.  The latter being a Sequence<Component>
> annotated as the DefaultProperty.  Its 'transform()' method returns a
> newly created TablePane with the requested number of columns, and
> sufficient rows to populate the cells using the supplied Components.

The idea of supporting builders in BXML is not unreasonable. But I suspect that there are probably simpler ways to accomplish it.

FWIW, you mentioned Lombok later on in the thread. We had been using Lombok extensively on my current project but ultimately abandoned it because it made using an IDE more difficult. Since the properties are generated via annotation, the IDE can't see them and displays compiler errors in every file that refers to them.

G


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
I wasn't aware of Felxjson, but Metawidget and similar projects were
certainly an inspiration for the dynamic GUI / object CRUD stuff.

I'm sure many more possibilities will become apparent as the idea is
applied to different problem domains.

On 4 July 2011 11:55, Superstring Media <su...@gmail.com> wrote:
> Some of the applications of your idea seem to be inclusive of functions in other APIs like Flexjson's Transformers or Metawidget's dynamic UIs.
> All really great applications coming from a single enhancement, sounds excellent indeed.
>
> http://flexjson.sourceforge.net
> http://metawidget.org
>
> Thom
>
>
> On 2011-07-02, at 4:36 PM, Chris Bartlett wrote:
>
>> Firstly, my apologies for the length of this email (and if there are
>> lots of typos).  It might be easier to just jump to the example BXML
>> fragments which demonstrate possibilities of the proposed change, and
>> then skip back to the more wordy stuff.
>>
>> I will post some proof of concept code in the morning if there is any
>> interest in this.
>>
>>
>> * Notes
>> The examples are meant to demonstrate ideas, so might seem a little contrived.
>> Although Transformables are designed to be triggered by
>> BXMLSerializer, they can just as easily be used programmatically.
>> The transform() method could be provided with a specific classloader
>> by BXMLSerializer if required
>>
>>
>> * References
>> http://pivot.apache.org/tutorials/bxml-primer.html
>> Specifically the section titled 'Class Instances'
>>
>> http://svn.apache.org/repos/asf/pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java
>>
>>
>> * Summary
>> Make a backwardly compatible change to BXMLSerializer to enable
>> support for a simple 'Transformable<T>' interface.
>>
>> public interface Transformable<T> {
>>    public Collection<T> transform();
>> }
>>
>> The interface would have a single method named 'transform()' which
>> would return a java.util.Collection<T>.
>>
>> A bean implementing the interface would be constructed as normal by
>> BXMLSerializer, but would have its 'transform()' method called when
>> the bean would usually be returned (if it was the root element) or
>> added to the parent object somehow (if it had a parent).
>>
>> If the bean is the root element, the Collection would be returned as
>> the result of the BXMLSerializer.readObject(InputStream) method;
>>
>> If the bean is not the root element, BXMLSerializer would the iterate
>> over the items in the returned Collection and process them in exactly
>> the same way as the original bean would have been processed.
>>
>> i.e. If the original bean was going to be added to a Sequence defined
>> by a DefaultProperty, then each of the items in the Collection would
>> be added to the same Sequence instead.
>>
>> i.e. If the original bean was going to be set as the value for a
>> writeable property, each of the items in the Collection would be set
>> as values for the same writeable property, in the order defined by the
>> Collection's iterator)
>>
>>
>> * What difference would that make?
>> This simple change would provide flexibility by allowing a special
>> type of 'Class Instance' (an implementation of Transformable) to
>> decide how many items to return (and of what types) when it is
>> 'created', rather than exactly 1 object as currently happens.
>>
>>
>> * How could that help me?
>> It essentially turns Transformable objects into macros that can
>> perform arbitrary tasks.
>>
>>
>>
>> Example 1 - User defined, simplified API for creating object graphs
>>
>> This is the original problem that lead to the proposed idea.
>> Being able to create simplified APIs for Pivot Components means that
>> designers could be provided with a much smaller and simpler 'toolkit'
>> to work with.  Having a smaller API would also be helpful for people
>> who add in auto-complete functionality into their editor tools.
>> Even just the ability to refer to a Component by a different name can
>> be very useful, especially when there are similarly named widgets in
>> various UI frameworks.
>>
>> <!-- This would create and populate a layout without needing to know
>> how it was being implemented behind the scenes -->
>> <ThreeColumnLayout>
>>  <leftColumn>
>>    ...
>>  </leftColumn>
>>  <middleColumn>
>>    ...
>>  </middleColumn>
>>  <rightColumn>
>>    ...
>>  </rightColumn>
>> </ThreeColumnLayout>
>>
>>
>> Here is a more complete example...
>>
>> TablePaneBuilder implements Transformable<TablePane> and has 'columns'
>> and 'components' properties.  The latter being a Sequence<Component>
>> annotated as the DefaultProperty.  Its 'transform()' method returns a
>> newly created TablePane with the requested number of columns, and
>> sufficient rows to populate the cells using the supplied Components.
>>
>> @DefaultProperty("components")
>> public class TablePaneBuilder implements Transformable<TablePane> {
>>
>>    private final List<Component> components = new ArrayList<Component>();
>>    private int columns = 1;
>>
>>    public Sequence<Component> getComponents() {
>>        return components;
>>    }
>>
>>    public int getColumns() {
>>        return columns;
>>    }
>>    public void setColumns(int columns) {
>>        if (columns < 1) {
>>            throw new IllegalArgumentException();
>>        }
>>        this.columns = columns;
>>    }
>>
>>    @Override
>>    public Collection<TablePane> transform() {
>>        final TablePane tablePane = new TablePane();
>>        for (int i = 0; i < columns; i++) {
>>            tablePane.getColumns().add(new Column());
>>        }
>>        TablePane.Row row = null;
>>        for (Component component : components) {
>>            if (row == null || row.getLength() == columns) {
>>                row = new TablePane.Row();
>>                tablePane.getRows().add(row);
>>            }
>>            row.add(component);
>>        }
>>        return Arrays.asList(tablePane);
>>    }
>> }
>>
>> Usage in BXML
>> <TablePaneBuilder columns="2" >
>>  <!-- Row 1 -->
>>  <wtk:Label text="Label 1" />
>>  <wtk:Label text="Label 2" />
>>
>>  <!-- Row 2 -->
>>  <wtk:PushButton buttonData="PushButton 1" />
>>  <wtk:PushButton buttonData="PushButton 2" />
>>
>>  <!-- Row 3 -->
>>  <wtk:TextInput text="TextInput 1" />
>>  <wtk:TextInput text="TextInput 2" />
>> </TablePaneBuilder>
>>
>>
>>
>> Example 2 - Ability to instantiate classes which do not have a no-arg
>> constructor
>>
>> public final class UnfriendlyPOJO {
>>    public final int mandatory;
>>    public UnfriendlyPOJO(int mandatory) {
>>        this.mandatory = mandatory;
>>    }
>> }
>>
>> public class UnfriendlyPOJOBuilder implements Transformable<UnfriendlyPOJO> {
>>    private int mandatory;
>>    public int getMandatory() {
>>        return mandatory;
>>    }
>>    public void setMandatory(int mandatory) {
>>        this.mandatory = mandatory;
>>    }
>>
>>    @Override
>>    public Collection<UnfriendlyPOJO> transform() {
>>        return Arrays.asList(new UnfriendlyPOJO(mandatory));
>>    }
>> }
>>
>>
>> <UnfriendlyPOJOBuilder mandatory="99" />
>>
>>
>>
>> Example 3 - Can be used to hide attribute ordering restrictions
>>
>> This BXML will work, as the selectedIndex is being set once the
>> ListView has data
>> <wtk:ListView listData="['One', 'Two', 'Three']" selectedIndex="0"/>
>>
>> But this BXML will fail, as the selectedIndex is being set before the
>> ListView has data
>> <wtk:ListView selectedIndex="0" listData="['One', 'Two', 'Three']"/>
>>
>>
>> @DefaultProperty("listView")
>> public class ListViewBuilder implements Transformable<ListView> {
>>    private final ListView listView = new ListView();
>>    private int selectedIndex;
>>    private List<?> listData;
>>
>>    public int getSelectedIndex() {
>>        return selectedIndex;
>>    }
>>    public void setSelectedIndex(int selectedIndex) {
>>        this.selectedIndex = selectedIndex;
>>    }
>>
>>    public void setListData(String listData) {
>>        try {
>>            this.listData = JSONSerializer.parseList(listData);
>>        } catch (SerializationException exception) {
>>            throw new IllegalArgumentException(exception);
>>        }
>>    }
>>
>>    @Override
>>    public Collection<ListView> transform() {
>>        listView.setListData(listData);
>>        // Ensure that the index selection happens after the list population
>>        listView.setSelectedIndex(selectedIndex);
>>        return Arrays.asList(listView);
>>    }
>> }
>>
>> <ListViewBuilder selectedIndex="0" listData="['One', 'Two', 'Three']" />
>>
>>
>>
>> Example 4 - Provide similar functionality to named styles only for properties
>>
>> The same could essentially be achieved by subclassing a Component and
>> hard coding some properties into its constructor.
>> Using a Transformable is another option, and could also be used with
>> final classes.
>>
>> @DefaultProperty("textInput")
>> public class PasswordInput implements Transformable<TextInput> {
>>    private TextInput textInput = null;
>>    public void setTextInput(TextInput textInput) {
>>        this.textInput = textInput;
>>    }
>>
>>    @Override
>>    public Collection<TextInput> transform() {
>>        if (textInput == null) {
>>            textInput = new TextInput();
>>        }
>>        textInput.setPassword(true);
>>        textInput.setPrompt("Enter password");
>>        return Arrays.asList(textInput);
>>    }
>> }
>>
>> <!-- Creates and returns a new TextInput -->
>> <PasswordInput />
>> <!-- Uses the supplied TextInput -->
>> <PasswordInput>
>>  <wtk:TextInput tooltipText="Using supplied TextInput" text="secret" />
>> </PasswordInput>
>>
>>
>> This idea can be taken further by a Transformable that 'clones'
>> specified objects (0..n times).
>> It would create new instances based on the supplied source objects,
>> and then iterate over the source's properties and styles while setting
>> the same values on the newly created 'clone'.  (I knocked up a working
>> example of this in about 20 mins)
>>
>>
>>
>> Example 5 - Transformable that returns an empty Collection
>>
>> This could be used to conditionally include sections of BXML file
>> based on any arbitrary logic.
>> (Result of a webquery, result of a JVM scripting function, JVM
>> version, availability of classes on the classpath, Operating System,
>> user name etc)
>> If the critera is met, the Transformable would return a Collection
>> containing the BXML, otherwise just an empty Collection.
>>
>> <WindowsOS>
>>  <WindowsWidget />
>>  <bxml:reference id="$commonToAllOperatingSystems"/>
>>  ...
>> </WindowsOS>
>> <MacOS>
>>  <MacWidget />
>>  <bxml:reference id="$commonToAllOperatingSystems"/>
>>  ...
>> </MacOS>
>>
>>
>>
>> Example 6 - Enhanced BXML include
>>
>> <!-- Include all files that match the regular expression or wildcard
>> syntax, retrieving them asynchronously -->
>> <Include async="true" regex="/path/to/bxml/files/widget[5-7].bxml" />
>>
>> or even
>>
>> <Async>
>>  <Include regex="/path/to/bxml/files/widget[5-7].bxml" />
>> </Async>
>>
>> The Async would queue a callback to populate the same position with
>> data once it had been retrieved from a potentially slow source.
>> (This is just an example of the sorts of options which are made
>> available by this change - not a proposal to create such a new
>> 'Includer')
>>
>>
>>
>> Example 7 - Dynamic UI creation (think automatic CRUD forms for a POJO/bean)
>>
>> <!-- Show a 'person' bean in a form -->
>> <FormBuilder editable="true" source="$person" fieldOrder="['id',
>> 'title', 'firstName', 'lastName', 'age']" />
>> or
>> <!-- Show a 'person' bean in a name/value TableView where the values
>> are editable -->
>> <TableViewBuilder editable="true" source="$person" fieldOrder="['id',
>> 'title', 'firstName', 'lastName', 'age']" />
>>
>> (These examples are for generic XXXBuilders, but they could obviously
>> have internal knowledge of certain types.)
>>
>>
>>
>> Example 8 - Reuseable and sharable
>>
>> Due to the simplicity of the interface, Transformables can easily be
>> shared among Pivot developers.
>> This could lead to an online repository of reuseable components (even
>> just wiki pages of source).
>>
>> There have been many mailing list questions about how to achieve
>> particular layouts.
>> Common layouts could be implemented as Transformables and mailed to
>> the list for easy reuse.
>>
>> (I suppose Transformables could be considered similar to a JSP tag library)
>>
>>
>> Chris
>
>

Re: Idea for a useful change to BXMLSerializer

Posted by Superstring Media <su...@gmail.com>.
Some of the applications of your idea seem to be inclusive of functions in other APIs like Flexjson's Transformers or Metawidget's dynamic UIs.
All really great applications coming from a single enhancement, sounds excellent indeed.

http://flexjson.sourceforge.net
http://metawidget.org

Thom


On 2011-07-02, at 4:36 PM, Chris Bartlett wrote:

> Firstly, my apologies for the length of this email (and if there are
> lots of typos).  It might be easier to just jump to the example BXML
> fragments which demonstrate possibilities of the proposed change, and
> then skip back to the more wordy stuff.
> 
> I will post some proof of concept code in the morning if there is any
> interest in this.
> 
> 
> * Notes
> The examples are meant to demonstrate ideas, so might seem a little contrived.
> Although Transformables are designed to be triggered by
> BXMLSerializer, they can just as easily be used programmatically.
> The transform() method could be provided with a specific classloader
> by BXMLSerializer if required
> 
> 
> * References
> http://pivot.apache.org/tutorials/bxml-primer.html
> Specifically the section titled 'Class Instances'
> 
> http://svn.apache.org/repos/asf/pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java
> 
> 
> * Summary
> Make a backwardly compatible change to BXMLSerializer to enable
> support for a simple 'Transformable<T>' interface.
> 
> public interface Transformable<T> {
>    public Collection<T> transform();
> }
> 
> The interface would have a single method named 'transform()' which
> would return a java.util.Collection<T>.
> 
> A bean implementing the interface would be constructed as normal by
> BXMLSerializer, but would have its 'transform()' method called when
> the bean would usually be returned (if it was the root element) or
> added to the parent object somehow (if it had a parent).
> 
> If the bean is the root element, the Collection would be returned as
> the result of the BXMLSerializer.readObject(InputStream) method;
> 
> If the bean is not the root element, BXMLSerializer would the iterate
> over the items in the returned Collection and process them in exactly
> the same way as the original bean would have been processed.
> 
> i.e. If the original bean was going to be added to a Sequence defined
> by a DefaultProperty, then each of the items in the Collection would
> be added to the same Sequence instead.
> 
> i.e. If the original bean was going to be set as the value for a
> writeable property, each of the items in the Collection would be set
> as values for the same writeable property, in the order defined by the
> Collection's iterator)
> 
> 
> * What difference would that make?
> This simple change would provide flexibility by allowing a special
> type of 'Class Instance' (an implementation of Transformable) to
> decide how many items to return (and of what types) when it is
> 'created', rather than exactly 1 object as currently happens.
> 
> 
> * How could that help me?
> It essentially turns Transformable objects into macros that can
> perform arbitrary tasks.
> 
> 
> 
> Example 1 - User defined, simplified API for creating object graphs
> 
> This is the original problem that lead to the proposed idea.
> Being able to create simplified APIs for Pivot Components means that
> designers could be provided with a much smaller and simpler 'toolkit'
> to work with.  Having a smaller API would also be helpful for people
> who add in auto-complete functionality into their editor tools.
> Even just the ability to refer to a Component by a different name can
> be very useful, especially when there are similarly named widgets in
> various UI frameworks.
> 
> <!-- This would create and populate a layout without needing to know
> how it was being implemented behind the scenes -->
> <ThreeColumnLayout>
>  <leftColumn>
>    ...
>  </leftColumn>
>  <middleColumn>
>    ...
>  </middleColumn>
>  <rightColumn>
>    ...
>  </rightColumn>
> </ThreeColumnLayout>
> 
> 
> Here is a more complete example...
> 
> TablePaneBuilder implements Transformable<TablePane> and has 'columns'
> and 'components' properties.  The latter being a Sequence<Component>
> annotated as the DefaultProperty.  Its 'transform()' method returns a
> newly created TablePane with the requested number of columns, and
> sufficient rows to populate the cells using the supplied Components.
> 
> @DefaultProperty("components")
> public class TablePaneBuilder implements Transformable<TablePane> {
> 
>    private final List<Component> components = new ArrayList<Component>();
>    private int columns = 1;
> 
>    public Sequence<Component> getComponents() {
>        return components;
>    }
> 
>    public int getColumns() {
>        return columns;
>    }
>    public void setColumns(int columns) {
>        if (columns < 1) {
>            throw new IllegalArgumentException();
>        }
>        this.columns = columns;
>    }
> 
>    @Override
>    public Collection<TablePane> transform() {
>        final TablePane tablePane = new TablePane();
>        for (int i = 0; i < columns; i++) {
>            tablePane.getColumns().add(new Column());
>        }
>        TablePane.Row row = null;
>        for (Component component : components) {
>            if (row == null || row.getLength() == columns) {
>                row = new TablePane.Row();
>                tablePane.getRows().add(row);
>            }
>            row.add(component);
>        }
>        return Arrays.asList(tablePane);
>    }
> }
> 
> Usage in BXML
> <TablePaneBuilder columns="2" >
>  <!-- Row 1 -->
>  <wtk:Label text="Label 1" />
>  <wtk:Label text="Label 2" />
> 
>  <!-- Row 2 -->
>  <wtk:PushButton buttonData="PushButton 1" />
>  <wtk:PushButton buttonData="PushButton 2" />
> 
>  <!-- Row 3 -->
>  <wtk:TextInput text="TextInput 1" />
>  <wtk:TextInput text="TextInput 2" />
> </TablePaneBuilder>
> 
> 
> 
> Example 2 - Ability to instantiate classes which do not have a no-arg
> constructor
> 
> public final class UnfriendlyPOJO {
>    public final int mandatory;
>    public UnfriendlyPOJO(int mandatory) {
>        this.mandatory = mandatory;
>    }
> }
> 
> public class UnfriendlyPOJOBuilder implements Transformable<UnfriendlyPOJO> {
>    private int mandatory;
>    public int getMandatory() {
>        return mandatory;
>    }
>    public void setMandatory(int mandatory) {
>        this.mandatory = mandatory;
>    }
> 
>    @Override
>    public Collection<UnfriendlyPOJO> transform() {
>        return Arrays.asList(new UnfriendlyPOJO(mandatory));
>    }
> }
> 
> 
> <UnfriendlyPOJOBuilder mandatory="99" />
> 
> 
> 
> Example 3 - Can be used to hide attribute ordering restrictions
> 
> This BXML will work, as the selectedIndex is being set once the
> ListView has data
> <wtk:ListView listData="['One', 'Two', 'Three']" selectedIndex="0"/>
> 
> But this BXML will fail, as the selectedIndex is being set before the
> ListView has data
> <wtk:ListView selectedIndex="0" listData="['One', 'Two', 'Three']"/>
> 
> 
> @DefaultProperty("listView")
> public class ListViewBuilder implements Transformable<ListView> {
>    private final ListView listView = new ListView();
>    private int selectedIndex;
>    private List<?> listData;
> 
>    public int getSelectedIndex() {
>        return selectedIndex;
>    }
>    public void setSelectedIndex(int selectedIndex) {
>        this.selectedIndex = selectedIndex;
>    }
> 
>    public void setListData(String listData) {
>        try {
>            this.listData = JSONSerializer.parseList(listData);
>        } catch (SerializationException exception) {
>            throw new IllegalArgumentException(exception);
>        }
>    }
> 
>    @Override
>    public Collection<ListView> transform() {
>        listView.setListData(listData);
>        // Ensure that the index selection happens after the list population
>        listView.setSelectedIndex(selectedIndex);
>        return Arrays.asList(listView);
>    }
> }
> 
> <ListViewBuilder selectedIndex="0" listData="['One', 'Two', 'Three']" />
> 
> 
> 
> Example 4 - Provide similar functionality to named styles only for properties
> 
> The same could essentially be achieved by subclassing a Component and
> hard coding some properties into its constructor.
> Using a Transformable is another option, and could also be used with
> final classes.
> 
> @DefaultProperty("textInput")
> public class PasswordInput implements Transformable<TextInput> {
>    private TextInput textInput = null;
>    public void setTextInput(TextInput textInput) {
>        this.textInput = textInput;
>    }
> 
>    @Override
>    public Collection<TextInput> transform() {
>        if (textInput == null) {
>            textInput = new TextInput();
>        }
>        textInput.setPassword(true);
>        textInput.setPrompt("Enter password");
>        return Arrays.asList(textInput);
>    }
> }
> 
> <!-- Creates and returns a new TextInput -->
> <PasswordInput />
> <!-- Uses the supplied TextInput -->
> <PasswordInput>
>  <wtk:TextInput tooltipText="Using supplied TextInput" text="secret" />
> </PasswordInput>
> 
> 
> This idea can be taken further by a Transformable that 'clones'
> specified objects (0..n times).
> It would create new instances based on the supplied source objects,
> and then iterate over the source's properties and styles while setting
> the same values on the newly created 'clone'.  (I knocked up a working
> example of this in about 20 mins)
> 
> 
> 
> Example 5 - Transformable that returns an empty Collection
> 
> This could be used to conditionally include sections of BXML file
> based on any arbitrary logic.
> (Result of a webquery, result of a JVM scripting function, JVM
> version, availability of classes on the classpath, Operating System,
> user name etc)
> If the critera is met, the Transformable would return a Collection
> containing the BXML, otherwise just an empty Collection.
> 
> <WindowsOS>
>  <WindowsWidget />
>  <bxml:reference id="$commonToAllOperatingSystems"/>
>  ...
> </WindowsOS>
> <MacOS>
>  <MacWidget />
>  <bxml:reference id="$commonToAllOperatingSystems"/>
>  ...
> </MacOS>
> 
> 
> 
> Example 6 - Enhanced BXML include
> 
> <!-- Include all files that match the regular expression or wildcard
> syntax, retrieving them asynchronously -->
> <Include async="true" regex="/path/to/bxml/files/widget[5-7].bxml" />
> 
> or even
> 
> <Async>
>  <Include regex="/path/to/bxml/files/widget[5-7].bxml" />
> </Async>
> 
> The Async would queue a callback to populate the same position with
> data once it had been retrieved from a potentially slow source.
> (This is just an example of the sorts of options which are made
> available by this change - not a proposal to create such a new
> 'Includer')
> 
> 
> 
> Example 7 - Dynamic UI creation (think automatic CRUD forms for a POJO/bean)
> 
> <!-- Show a 'person' bean in a form -->
> <FormBuilder editable="true" source="$person" fieldOrder="['id',
> 'title', 'firstName', 'lastName', 'age']" />
> or
> <!-- Show a 'person' bean in a name/value TableView where the values
> are editable -->
> <TableViewBuilder editable="true" source="$person" fieldOrder="['id',
> 'title', 'firstName', 'lastName', 'age']" />
> 
> (These examples are for generic XXXBuilders, but they could obviously
> have internal knowledge of certain types.)
> 
> 
> 
> Example 8 - Reuseable and sharable
> 
> Due to the simplicity of the interface, Transformables can easily be
> shared among Pivot developers.
> This could lead to an online repository of reuseable components (even
> just wiki pages of source).
> 
> There have been many mailing list questions about how to achieve
> particular layouts.
> Common layouts could be implemented as Transformables and mailed to
> the list for easy reuse.
> 
> (I suppose Transformables could be considered similar to a JSP tag library)
> 
> 
> Chris


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
On 4 July 2011 19:41, Sandro Martini <sa...@gmail.com> wrote:
>>Yes, it could certainly lead to some weird BXML files that are written
>>in multiple 'human languages', but right now it is possible to use
>>BXMLSerializer to create graphs of objects that have 'non-English'
>>class names.
>
> Ok, for me you can try and see what happens ... but for what I can suggest,
> in international projects usually a good practice is to have English names
> everywhere, otherwise maintenance will become a nightmare.

I totally agree.
This was just an example of one of the many different things that
become possible via a small change.

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Sandro Martini <sa...@gmail.com>.
>Good point. I suppose it could be BXMLCommand?
Yes, this could be  a better name :-) ...

>>>This proposal also opens the possibility of
>>>internationalizing/translating bean class and property/styles names
>>>via simple alias classes.  Styles can be exposed as bean properties to
>>>simplify things even further as demonstrated below.
>> On this I have no idea, could be powerful but I don't know if could
>> generate
>> code too much "strange" to read, for example on anyone has to give
>> support
>> ... but probably with a real (minimal) example could be easily
>> understood.
>
>Yes, it could certainly lead to some weird BXML files that are written
>in multiple 'human languages', but right now it is possible to use
>BXMLSerializer to create graphs of objects that have 'non-English'
>class names.

Ok, for me you can try and see what happens ... but for what I can suggest,
in international projects usually a good practice is to have English names
everywhere, otherwise maintenance will become a nightmare.

On the inclusion or not in Pivot I don't know, we have to see what others
say. 
But in any case you'd have to publish in another place, please consider one
of our apache-extras projects ... so a custom class could be a good idea, at
least now.


Bye



--
View this message in context: http://apache-pivot-developers.417237.n3.nabble.com/Idea-for-a-useful-change-to-BXMLSerializer-tp3133361p3137431.html
Sent from the Apache Pivot - Developers mailing list archive at Nabble.com.

Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
On 4 July 2011 17:13, Sandro Martini <sa...@gmail.com> wrote:
> I'd prefer something like Command, but usually I've seen that the Command
> pattern returns void in its execute method
Good point. I suppose it could be BXMLCommand?
I also thought about Action as a name, but that clashes with
org.apache.pivot.wtk.Action.

>>This proposal also opens the possibility of
>>internationalizing/translating bean class and property/styles names
>>via simple alias classes.  Styles can be exposed as bean properties to
>>simplify things even further as demonstrated below.
> On this I have no idea, could be powerful but I don't know if could generate
> code too much "strange" to read, for example on anyone has to give support
> ... but probably with a real (minimal) example could be easily understood.

Yes, it could certainly lead to some weird BXML files that are written
in multiple 'human languages', but right now it is possible to use
BXMLSerializer to create graphs of objects that have 'non-English'
class names.

The point here was just that internationalization becomes an option.
Someone would be free to could provide translated 'aliases' for
languages spoken in emerging markets or the 5 most common languages
spoken in the world.  Perhaps Pivot would become popular in such a
country simply because of this?

> I like the idea of "BXMLExpander", could be another way to pre-process bxml
> files ... and the right project for it could be the Tools subproject (no
> more existing in 2.0.x) ... let's see what others say.
> Even the version of ApplicationContext for JUnit automated tests could go
> under Tools (or better, "Developer Tools" subproject).
>
> Note, if you want to prototype something, tell me for grants under our
> apache-extras projects ... or otherwise for prototypes with direct impact on
> Pivot core projects a better place could be the /skunk area ... as you
> prefer.

This all depends on whether the idea is accepted and becomes an
official part of Pivot.

If there is no desire to include it, it could easily be forked and
made available as a drop-in replacement for BXMLSerializer.  Then
anyone who wished to use this could just download a tiny jar (with
dependencies on pivot-core) and use 'FooBXMLSerializer' rather than
BXMLSerializer.

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Sandro Martini <sa...@gmail.com>.
Hi Chris,

>Better naming options might be
>
>public interface Command<T> {
>   public Collection<T> execute();
>}
>
>or
>
>public interface Function<T> {
>   public Collection<T> execute();
>}
>
>
>On 3 July 2011 04:36, Chris Bartlett <[hidden email]> wrote:
>> public interface Transformable<T> {
>>    public Collection<T> transform();
>> } 
>
I'd prefer something like Command, but usually I've seen that the Command
pattern returns void in its execute method (for example take a look here:
http://en.wikipedia.org/wiki/Command_pattern ), so why not
TransformableCommand (or Transformable) ? 
It's just a suggestion, to avoid confusion with generic patterns ...


>This proposal also opens the possibility of
>internationalizing/translating bean class and property/styles names
>via simple alias classes.  Styles can be exposed as bean properties to
>simplify things even further as demonstrated below.
On this I have no idea, could be powerful but I don't know if could generate
code too much "strange" to read, for example on anyone has to give support
... but probably with a real (minimal) example could be easily understood.


I like the idea of "BXMLExpander", could be another way to pre-process bxml
files ... and the right project for it could be the Tools subproject (no
more existing in 2.0.x) ... let's see what others say.
Even the version of ApplicationContext for JUnit automated tests could go
under Tools (or better, "Developer Tools" subproject).


Note, if you want to prototype something, tell me for grants under our
apache-extras projects ... or otherwise for prototypes with direct impact on
Pivot core projects a better place could be the /skunk area ... as you
prefer.

Bye,
Sandro


--
View this message in context: http://apache-pivot-developers.417237.n3.nabble.com/Idea-for-a-useful-change-to-BXMLSerializer-tp3133361p3137116.html
Sent from the Apache Pivot - Developers mailing list archive at Nabble.com.

Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
A 'BXMLExpander' tool is another possibility.  It would take an input
BXML file, process each Transformable, expand it into BXML, and then
output to a new file.

For those of you familiar with the fantastic Project Lombok, this
would be equivalent to the 'delombok' tool.
http://projectlombok.org/
http://projectlombok.org/features/delombok.html


In a simple example this BXML fragment ...
<PasswordInput>
  <wtk:TextInput tooltipText="Using supplied TextInput" text="secret" />
</PasswordInput>

... would be expanded to
<TextInput tooltipText="Using supplied TextInput" text="secret"
password="true" prompt="Enter password" />


Such a tool might require an additional change to BXML serializer to
support this scenario
PasswordDecorator sets properties of the 'textInput' Component, but it
was already created in a previous XML element.  I don't think it is
currently possible to represent this in BXML (as there is no real
use-case to support it).
bxml:reference adds/sets the referenced object, but this scenario
would require just dereferencing before modifying the object in some
way.

<bxml:define>
  <TextInput bxml:id="textInput" />
</bxml:define>

<!-- Tweak any TextInput's properties to make it into a 'password'
style component -->
<PasswordDecorator target="$textInput" />



Combining a number of ideas from before, this change allows the
following workflow
- An offshore design team in country X could rapidly prototype a Pivot GUI
- built using their in house library of custom, powerful Transformables
- (which are all in the native language of country X)
- without having any knowledge of Pivot (just using a simple BXML viewer app)
- and then 'expand' the resulting BXML files to generate standard BXML
files which reference only org.apache.pivot.wtk.* classes.
- without having to reveal their highly prized Transformables to the
client or their competitors

All of the above could be achieved by the offshore team if it made
this proposed change to BXMLSerializer themselves.  However if it was
officially supported (ie, bundled into the Pivot jars), they would be
able to share their library of Transformables with the Pivot community
in a similar way to how css stylesheets, blog themes, or application
skins are shared.

Chris

Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Sandro made the same completely valid point.

This was just another example of one of the many possibilities that
this simple change would allow.  It is certainly not a suggestion that
the Pivot project should perform such a task.

I was trying to demonstrate how a small change would permit 'custom'
aliases of stock Pivot components.  These aliases then essentially
become a 'DSL' for a specific problem domain.

However, the option would remain open to someone who *did* wish to
create and maintain their own translations for use by teams in various
countries.  Combined with the 'expander' tool idea, this would allow
GUI development in one language to be seamlessly introduced into a
more traditional international project workflow.  This is very similar
to how the previously mentioned Project Lombok can be used by one
developer on a team without the knowledge of anyone else they interact
with.

And of course, there may well be alternative ways to achieve many of
the examples I listed, but that was not the point of the email.


On 5 July 2011 19:57, Greg Brown <gk...@verizon.net> wrote:
>> This proposal also opens the possibility of
>> internationalizing/translating bean class and property/styles names
>> via simple alias classes.  Styles can be exposed as bean properties to
>> simplify things even further as demonstrated below.
>
> An interesting idea, but it could cause quite a bit of confusion and would make documentation a nightmare. Might be easier to simply localize the bean properties, via annotation or some other means.
>
>

Re: Idea for a useful change to BXMLSerializer

Posted by Greg Brown <gk...@verizon.net>.
> This proposal also opens the possibility of
> internationalizing/translating bean class and property/styles names
> via simple alias classes.  Styles can be exposed as bean properties to
> simplify things even further as demonstrated below.

An interesting idea, but it could cause quite a bit of confusion and would make documentation a nightmare. Might be easier to simply localize the bean properties, via annotation or some other means.


Re: Idea for a useful change to BXMLSerializer

Posted by Chris Bartlett <cb...@gmail.com>.
Another thing that popped into my mind...

This proposal also opens the possibility of
internationalizing/translating bean class and property/styles names
via simple alias classes.  Styles can be exposed as bean properties to
simplify things even further as demonstrated below.

The following example of a simplified Chinese translation (according
to Google translate) is possible with a little hack to make
BXMLSerializer think that the first character of '文字输入' is a capital
letter, and therefore represents a class to be instantiated.

Hopefully Google hasn't suggested any offensive terms when it translated :)

BXML
<!-- TextInput, text property, color style in simplified Chinese/zh-CN -->
<文字输入 文字="Text for the TextInput" 的颜色="#ff0000" />

Java
// 文字输入 - text input
// 文字 - text
// 的颜色 - color
public class 文字输入 implements Transformable<TextInput> {
    private TextInput textInput = new TextInput();

    // 'text' property
    private String text = "";
    public String get文字() {
        return text;
    }
    public void set文字(String text) {
        this.text = text;
    }

    // 'color' style
    private Color color = (Color) textInput.getStyles().get("color");
    public Color get的颜色() {
        return color;
    }
    public void set的颜色(String color) {
        this.color = Color.decode(color);
    }

    @Override
    public Collection<TextInput> transform() {
        textInput.setText(text);
        textInput.getStyles().put("color", color);
        return Arrays.asList(textInput);
    }
}


The class above has hard coded 'translations' but it shouldn't be
difficult to write a base AbstractTranslator class (implementing
Dictionary) that would read the translations and 'style to property'
mappings from a resource file.

The alias classes could even be automatically generated from the resource files.

Chris