SequenceList

View: New views
6 Messages — Rating Filter:   Alert me  

SequenceList

by cocoa :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

In my application a list of sport activities can be tracked and analyzed. I want to provide a summary view that shows the total time or distance of all activities within a certain time period (e.g. week) over some time (e.g. the last year). Below is the basic list setup I use.

// list of activities
EventList<Activity> source = ...;

// observe property change events
EventList<Activity> observed = new ObservableElementList(source, ...);

// group the activities by time period, e.g. per week
GroupingList<Activity> grouped = new GroupingList<Activity>(observedElementList, ...);

// then comes a function list whose function calculates the summaries
FunctionList<List<Activity>, SummaryRecord> summaries = ...;

As GroupingList does not return any empty groups, it happens that the summaries contains gaps, i.e. time periods for which no group exists. Then I stumbled upon the SequenceList, which I thought might be of some help. First I had some problems with the sequencer implementation (the summaries after the first element where lost). But here is with what I came up with.

// first create a map that maps a time period to the list of summaries
DisposableMap<Week, List<SummaryRecord>> map = GlazedLists.syncEventListToMultiMap(summaries, keyMaker());

// then pass this map to the sequencer implementation
SequenceList<SummaryRecord> sequence = new SequenceList<SummaryRecord>(summaries, new RecordSequencer(map));

The sequencer uses the map to implement next and previous so that if there is already a SummaryRecord for a time period then that SummaryRecord is returned (otherwise, an empty SummaryRecord). See the implementation of next().

public Record next(SummaryRecord value) {
    Week week = value.week.next();
    List<SummaryRecord> existing = map.get(week);
    return existing != null ? existing.get(0) : new SummaryRecord(week, 0);
}

So far, this seems to work. I am just wondering whether there is a simpler way to achieve the same thing. I'm sure others have done this kind of reporting over a data set. There is also precious few documentation for SequenceList, so I'm not sure that this is a supported way of using it (especially the Sequencer implementation).

Any suggestions?
Simon

PS: SequenceList seems to have a bug if the earliest source value is a sequence value. In that case, the earliest sequence value is duplicated in the result list (can easily be shown with month sequencer).

PS: glazedlists is amazing

re: SequenceList

by Kevin Day-7 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
I think you may run into some problems with this approach - the map is not a live map.  Be sure to test the following scenario:
 
1.  Initial condition is a setup that is missing data in week3
2.  Add an element for week 3 - did the summary get re-constructed? 
 
Repeat, but instead of adding an element for week 3, change an existing element so that it now resides in week 3.  Same test.
 
There is a lot of nastiness with event publication and dependant listeners that you have to deal with when you introduce a map that is driving another list's behavior.  It *can* be done, but the opportunity for error and odd little corner cases (that are really hard to debug) is very high.
 
 
 
Another approach to this problem that doesn't use maps would be to construct a list of dummy PlaceHolderActivity objects - these will not get added to your totals if they appear in a list that a summary operates against.  Create one PlaceHolderActivity for each bucket you want to appear in the output (so if you are doing 52 weeks, you'd have 52).  Now, composite this list with the source list using CompositeList, then pipe it into your grouping list.
 
Also, it will simplify things if you make the EventList<PlaceHolderActivity> be a SequenceList built from the source list.  Cool, eh?
 
placeHolders = new SequenceList<Activity>(source, sequencer); // sequencer returns a sub-class of Activity - PlaceHolderActivity
 
composite = new CompositeList<Activity>(source.getPubliser(), source.getReadWriteLock());
composite.addMemberList(source);
composite.addMemberList(placeHolders);
 
grouped = new GroupingList<Activity>(composite);
 
// then comes a function list whose function calculates the summaries
FunctionList<List<Activity>, SummaryRecord> summaries = ...; // function ignores list entries that are PlaceHolderActivities

summaries now contains the list that you want, including the 'missing' buckets, and you don't have the messy event publisher stuff from the map to deal with.
 
- K
 
----------------------- Original Message -----------------------
  
From: cocoa cocoa@...
Cc: 
Date: Sat, 10 Oct 2009 15:51:53 -0700 (PDT)
Subject: SequenceList
  

In my application a list of sport activities can be tracked and analyzed. I
want to provide a summary view that shows the total time or distance of all
activities within a certain time period (e.g. week) over some time (e.g. the
last year). Below is the basic list setup I use.

// list of activities
EventList<Activity> source = ...;

// observe property change events
EventList<Activity> observed = new ObservableElementList(source, ...);

// group the activities by time period, e.g. per week
GroupingList<Activity> grouped = new
GroupingList<Activity>(observedElementList, ...);

// then comes a function list whose function calculates the summaries
FunctionList<List<Activity>, SummaryRecord> summaries = ...;

As GroupingList does not return any empty groups, it happens that the
summaries contains gaps, i.e. time periods for which no group exists. Then I
stumbled upon the SequenceList, which I thought might be of some help. First
I had some problems with the sequencer implementation (the summaries after
the first element where lost). But here is with what I came up with.

// first create a map that maps a time period to the list of summaries
DisposableMap<Week, List<SummaryRecord>> map =
GlazedLists.syncEventListToMultiMap(summaries, keyMaker());

// then pass this map to the sequencer implementation
SequenceList<SummaryRecord> sequence = new
SequenceList<SummaryRecord>(summaries, new RecordSequencer(map));

The sequencer uses the map to implement next and previous so that if there
is already a SummaryRecord for a time period then that SummaryRecord is
returned (otherwise, an empty SummaryRecord). See the implementation of
next().

public Record next(SummaryRecord value) {
   Week week = value.week.next();
   List<SummaryRecord> existing = map.get(week);
   return existing != null ? existing.get(0) : new SummaryRecord(week, 0);
}

So far, this seems to work. I am just wondering whether there is a simpler
way to achieve the same thing. I'm sure others have done this kind of
reporting over a data set. There is also precious few documentation for
SequenceList, so I'm not sure that this is a supported way of using it
(especially the Sequencer implementation).

Any suggestions?
Simon

PS: SequenceList seems to have a bug if the earliest source value is a
sequence value. In that case, the earliest sequence value is duplicated in
the result list (can easily be shown with month sequencer).

PS: glazedlists is amazing :clap:
--
View this message in context: http://www.nabble.com/SequenceList-tp25838609p25838609.html
Sent from the GlazedLists - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...


--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@... For additional commands, e-mail: users-help@...

Re: re: SequenceList

by cocoa :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I soon saw that my initial approach does not work. The map, as you mentioned, is not updated so the approach is broken. Next I've tried the proposed approach using a CompositeList.

The first list is a SequenceList that produces PlaceholderActivity objects with a Sequencer. However, I've run into an issue with the SequenceList. It adds the source Activity objects to the SequenceList (not the placeholder activity objects). This results in incorrect duration totals (i.e. the first one is twice as large as it should be). So I've added a FunctionList<Activity, PlaceholderActivity> to the source list. That way, I get the expected sequence lists consisting only of PlaceholderActivity.

The CompositeList stuff works as advertised. I get the missing buckets with a 0 total duration.

Simon


PS: I'm not groking why the first value of the SequenceList is duplicated. It does not hurt in my case, because placeholder activities are not used for the calculations. Below is a simple snipped that shows what I mean:

EventList<Integer> src = new BasicEventList<Integer>();
src.add(1);
src.add(3);
               
SequenceList<Integer> integers = new SequenceList<Integer>(src, new Sequencer<Integer>() {
        public Integer next(Integer value) {
                return value + 1;
        }
        public Integer previous(Integer value) {
                return value - 1;
        }
});
               
for (Integer value : integers) {
        System.out.println(value);
}

Output is :
1
1
2
3

Re: re: SequenceList

by James Lemieux :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Simon,

The SequenceList problem you mention is a legit bug in my opinion. Would you mind filing a bug in our bugtracker?

As for the approach to your problem (inserting sequence placeholders into a list), that's something that isn't trivial to do with our existing transformations. If I was in your shoes, I'd consider extending TransformedList and implementing that transformation myself from the ground up. It actually shouldn't be that hard to implement, overall.

We probably could dream up some type of transformation in the core that, given two adjacent items in the source EventList, delegated to a Sequencer type of object that filled in the gaps... I'm unsure of how useful that is to our general audience.

Good Luck,

James

On Sun, Oct 11, 2009 at 3:02 PM, cocoa <cocoa@...> wrote:

I soon saw that my initial approach does not work. The map, as you mentioned,
is not updated so the approach is broken. Next I've tried the proposed
approach using a CompositeList.

The first list is a SequenceList that produces PlaceholderActivity objects
with a Sequencer. However, I've run into an issue with the SequenceList. It
adds the source Activity objects to the SequenceList (not the placeholder
activity objects). This results in incorrect duration totals (i.e. the first
one is twice as large as it should be). So I've added a
FunctionList<Activity, PlaceholderActivity> to the source list. That way, I
get the expected sequence lists consisting only of PlaceholderActivity.

The CompositeList stuff works as advertised. I get the missing buckets with
a 0 total duration.

Simon


PS: I'm not groking why the first value of the SequenceList is duplicated.
It does not hurt in my case, because placeholder activities are not used for
the calculations. Below is a simple snipped that shows what I mean:

EventList<Integer> src = new BasicEventList<Integer>();
src.add(1);
src.add(3);

SequenceList<Integer> integers = new SequenceList<Integer>(src, new
Sequencer<Integer>() {
       public Integer next(Integer value) {
               return value + 1;
       }
       public Integer previous(Integer value) {
               return value - 1;
       }
});

for (Integer value : integers) {
       System.out.println(value);
}

Output is :
1
1
2
3

--
View this message in context: http://www.nabble.com/SequenceList-tp25838609p25848064.html
Sent from the GlazedLists - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...



Re: re: SequenceList

by cocoa :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The SequenceList problem you mention is a legit bug in my opinion. Would you mind filing a bug in our bugtracker?
I've filed a bug, see https://glazedlists.dev.java.net/issues/show_bug.cgi?id=482. A bug attachment contains a failing unit test.

As for the approach to your problem (inserting sequence placeholders into a list), that's something that isn't trivial to do with our existing transformations. If I was in your shoes, I'd consider extending TransformedList and implementing that transformation myself from the ground up. It actually shouldn't be that hard to implement, overall.
Implementing my own TransformedList seems daunting :S. I've had a quick look at some TransformedList implementations. The current solution with the CompositeList seems to work so far. As long as it works I abstain from implementing any TransformedList ;). Unless somebody is willing to help me get up to speed with all those internal details of glazed lists.

We probably could dream up some type of transformation in the core that, given two adjacent items in the source EventList, delegated to a Sequencer type of object that filled in the gaps... I'm unsure of how useful that is to our general audience.
My use case is to generate a report that shows the total time (or distance) of activities grouped by a time period (e.g. week, month, ...). Obviously, it is possible that some period does not contain any activity. So, the bucket is missing in the GroupingList, which is not acceptable. The missing bucket is important information by itself (i.e. the user did not perform any sport activity).

re[3]: SequenceList

by Kevin Day-7 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
The use case here is fairly common (we do something similar frequently) - but I think the suggested solution is sufficient for the bulk of cases.  It would be *much* more useful to have access to the deleted element in delete events (this would allow effective caching of computed values).
 
- K
 
----------------------- Original Message -----------------------
  
From: cocoa cocoa@...
Cc: 
Date: Mon, 12 Oct 2009 13:47:10 -0700 (PDT)
Subject: Re: re: SequenceList
  



> The SequenceList problem you mention is a legit bug in my opinion. Would
> you mind filing a bug in our bugtracker?
>

I've filed a bug, see
https://glazedlists.dev.java.net/issues/show_bug.cgi?id=482
https://glazedlists.dev.java.net/issues/show_bug.cgi?id=482 . A bug
attachment contains a failing unit test.



> As for the approach to your problem (inserting sequence placeholders into
> a list), that's something that isn't trivial to do with our existing
> transformations. If I was in your shoes, I'd consider extending
> TransformedList and implementing that transformation myself from the
> ground up. It actually shouldn't be that hard to implement, overall.
>

Implementing my own TransformedList seems daunting :S. I've had a quick look
at some TransformedList implementations. The current solution with the
CompositeList seems to work so far. As long as it works I abstain from
implementing any TransformedList ;). Unless somebody is willing to help me
get up to speed with all those internal details of glazed lists.



> We probably could dream up some type of transformation in the core that,
> given two adjacent items in the source EventList, delegated to a Sequencer
> type of object that filled in the gaps... I'm unsure of how useful that is
> to our general audience.
>

My use case is to generate a report that shows the total time (or distance)
of activities grouped by a time period (e.g. week, month, ...). Obviously,
it is possible that some period does not contain any activity. So, the
bucket is missing in the GroupingList, which is not acceptable. The missing
bucket is important information by itself (i.e. the user did not perform any
sport activity).
--
View this message in context: http://www.nabble.com/SequenceList-tp25838609p25862874.html
Sent from the GlazedLists - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...


--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@... For additional commands, e-mail: users-help@...