|
View:
New views
6 Messages
—
Rating Filter:
Alert me
|
|
|
SequenceListIn 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: SequenceListI 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@...
To: users@...
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@... |
|
|
Re: re: SequenceListI 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: SequenceListSimon,
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:
|
|
|
Re: re: SequenceListI've filed a bug, see https://glazedlists.dev.java.net/issues/show_bug.cgi?id=482. A bug attachment contains a failing unit test. 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. 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]: SequenceListThe 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@...
To: users@...
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@... |
| Free embeddable forum powered by Nabble | Forum Help |