Cherry picking r9609 into releases/2.2 git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.2@9611 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/PersonEditorWorkflow.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/PersonEditorWorkflow.java index 51ce66f..51ad62c 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/PersonEditorWorkflow.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/PersonEditorWorkflow.java
@@ -28,7 +28,10 @@ import com.google.gwt.requestfactory.shared.RequestContext; import com.google.gwt.requestfactory.shared.Violation; import com.google.gwt.sample.dynatablerf.client.events.EditPersonEvent; +import com.google.gwt.sample.dynatablerf.client.widgets.MentorSelector; import com.google.gwt.sample.dynatablerf.client.widgets.PersonEditor; +import com.google.gwt.sample.dynatablerf.client.widgets.ScheduleEditor; +import com.google.gwt.sample.dynatablerf.client.widgets.TimeSlotListWidget; import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory; import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory.PersonRequest; import com.google.gwt.sample.dynatablerf.shared.PersonProxy; @@ -88,7 +91,10 @@ this.requestFactory = requestFactory; this.manager = manager; this.person = person; - personEditor = new PersonEditor(requestFactory); + TimeSlotListWidget timeSlotEditor = new TimeSlotListWidget(requestFactory); + ScheduleEditor scheduleEditor = new ScheduleEditor(timeSlotEditor); + MentorSelector mentorEditor = new MentorSelector(requestFactory); + personEditor = new PersonEditor(mentorEditor, scheduleEditor); Binder.BINDER.createAndBindUi(this); contents.addDomHandler(new KeyUpHandler() { public void onKeyUp(KeyUpEvent event) {
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java index 0ecdd4b..ddbfaf4 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java
@@ -20,7 +20,6 @@ import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.editor.client.Editor; import com.google.gwt.editor.ui.client.ValueBoxEditorDecorator; -import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory; import com.google.gwt.sample.dynatablerf.shared.PersonProxy; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; @@ -52,9 +51,13 @@ @UiField Focusable nameBox; + + @UiField(provided = true) + ScheduleEditor classSchedule; - public PersonEditor(DynaTableRequestFactory factory) { - mentor = new MentorSelector(factory); + public PersonEditor(MentorSelector mentorEditor, ScheduleEditor scheduleEditor) { + classSchedule = scheduleEditor; + this.mentor = mentorEditor; initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this)); }
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml index 3b29ba3..40b32ce 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml
@@ -35,5 +35,8 @@ <dt:AddressEditor ui:field="address" stylePrimaryName="{style.editField}" /> Mentor: <dt:MentorSelector ui:field="mentor" stylePrimaryName="{style.editField}" /> + <br /> + Schedule: + <dt:ScheduleEditor ui:field="classSchedule" stylePrimaryName="{style.editField}" /> </g:HTMLPanel> </ui:UiBinder> \ No newline at end of file
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/ScheduleEditor.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/ScheduleEditor.java new file mode 100644 index 0000000..4d4d175 --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/ScheduleEditor.java
@@ -0,0 +1,45 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.client.widgets; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.editor.client.Editor; +import com.google.gwt.sample.dynatablerf.shared.ScheduleProxy; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + +/** + * Edits a persons's schedule. + */ +public class ScheduleEditor extends Composite implements Editor<ScheduleProxy> { + + interface ScheduleEditorUiBinder extends UiBinder<Widget, ScheduleEditor> { + } + + private static ScheduleEditorUiBinder uiBinder = GWT.create( + ScheduleEditorUiBinder.class); + + @UiField(provided = true) + TimeSlotListWidget timeSlots; + + public ScheduleEditor(TimeSlotListWidget timeSlotEditor) { + timeSlots = timeSlotEditor; + initWidget(uiBinder.createAndBindUi(this)); + } + +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/ScheduleEditor.ui.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/ScheduleEditor.ui.xml new file mode 100644 index 0000000..4a8771e --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/ScheduleEditor.ui.xml
@@ -0,0 +1,13 @@ +<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> +<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" + xmlns:g="urn:import:com.google.gwt.user.client.ui" + xmlns:dt='urn:import:com.google.gwt.sample.dynatablerf.client.widgets' > + <ui:style> + .table { + width: 100%; + } + </ui:style> + <g:HTMLPanel> + <dt:TimeSlotListWidget ui:field="timeSlots" stylePrimaryName="{style.table}" /> + </g:HTMLPanel> +</ui:UiBinder> \ No newline at end of file
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/SummaryWidget.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/SummaryWidget.java index 4024b61..78a0d9d 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/SummaryWidget.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/SummaryWidget.java
@@ -34,6 +34,8 @@ import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory; import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory.PersonRequest; import com.google.gwt.sample.dynatablerf.shared.PersonProxy; +import com.google.gwt.sample.dynatablerf.shared.ScheduleProxy; +import com.google.gwt.sample.dynatablerf.shared.TimeSlotProxy; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; @@ -98,7 +100,7 @@ @Override public String getValue(PersonProxy object) { - return object.getSchedule(); + return object.getScheduleDescription(); } } @@ -177,8 +179,11 @@ void onCreate(ClickEvent event) { PersonRequest context = requestFactory.personRequest(); AddressProxy address = context.create(AddressProxy.class); + ScheduleProxy schedule = context.create(ScheduleProxy.class); + schedule.setTimeSlots(new ArrayList<TimeSlotProxy>()); PersonProxy person = context.edit(context.create(PersonProxy.class)); person.setAddress(address); + person.setClassSchedule(schedule); context.persist().using(person); eventBus.fireEvent(new EditPersonEvent(person, context)); }
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/TimeSlotListWidget.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/TimeSlotListWidget.java new file mode 100644 index 0000000..1d098f7 --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/TimeSlotListWidget.java
@@ -0,0 +1,267 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.client.widgets; + +import com.google.gwt.cell.client.ClickableTextCell; +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.client.GWT; +import com.google.gwt.editor.client.EditorDelegate; +import com.google.gwt.editor.client.ValueAwareEditor; +import com.google.gwt.requestfactory.shared.Receiver; +import com.google.gwt.sample.dynatablerf.client.widgets.SummaryWidget.TableResources; +import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory; +import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory.ScheduleRequest; +import com.google.gwt.sample.dynatablerf.shared.TimeSlotProxy; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +/** + * Edits a list of time slots. + */ +public class TimeSlotListWidget extends Composite implements ValueAwareEditor<List<TimeSlotProxy>> { + + interface TimeSlotListWidgetUiBinder extends UiBinder<Widget, TimeSlotListWidget> { + } + + private class ScheduleRow { + int hour; + + ScheduleRow(int hour) { + this.hour = hour; + } + + public int getHour() { + return hour; + } + + public boolean isInUse(WeekDay day) { + return currentSchedule.contains(new TimeSlotKey(day, hour)); + } + + public void toggleInUse(WeekDay day) { + final TimeSlotKey key = new TimeSlotKey(day, hour); + if (currentSchedule.contains(key)) { + currentSchedule.remove(key); + table.redraw(); + } else if (!existingSlots.containsKey(key)) { + acceptClicks = false; + ScheduleRequest context = factory.scheduleRequest(); + context.createTimeSlot(day.ordinal(), hour * 60, hour * 60 + 50).fire( + new Receiver<TimeSlotProxy>() { + public void onSuccess(TimeSlotProxy slot) { + existingSlots.put(key, slot); + backing.add(slot); + currentSchedule.add(key); + table.redraw(); + acceptClicks = true; + } + }); + } else { + currentSchedule.add(key); + table.redraw(); + } + } + } + + private static class TimeSlotKey { + private int hour; + private WeekDay day; + + TimeSlotKey(WeekDay day, int hour) { + this.day = day; + this.hour = hour; + } + + TimeSlotKey(TimeSlotProxy slot) { + day = WeekDay.fromInt(slot.getDayOfWeek()); + hour = slot.getStartMinutes() / 60; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TimeSlotKey other = (TimeSlotKey) obj; + if (day == null) { + if (other.day != null) { + return false; + } + } else if (!day.equals(other.day)) { + return false; + } + if (hour != other.hour) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return 31 * (31 + ((day == null) ? 0 : day.hashCode())) + hour; + } + } + + private class WeekDayColumn extends Column<ScheduleRow, String> { + private WeekDay day; + + public WeekDayColumn(WeekDay day) { + super(new ClickableTextCell()); + this.day = day; + } + + @Override + public String getValue(ScheduleRow row) { + if (day == null) { + int hour = row.getHour(); + return Integer.toString(hour <= 12 ? hour : hour - 12) + ":00" + + ((hour < 12) ? "AM" : "PM"); + } + return row.isInUse(day) ? "X" : "."; + } + } + + private static final int ROWS_IN_A_DAY = 9; + private static final int FIRST_HOUR = 8; + + private static TimeSlotListWidgetUiBinder uiBinder = GWT.create( + TimeSlotListWidgetUiBinder.class); + + @UiField(provided = true) + CellTable<ScheduleRow> table; + + private enum WeekDay { + SUNDAY("Su"), MONDAY("Mo"), TUESDAY("Tu"), WEDNESDAY("We"), + THURSDAY("Th"), FRIDAY("Fr"), SATURDAY("Sa"); + + public static WeekDay fromInt(int ordinal) { + return values()[ordinal]; + } + + private String shortName; + + WeekDay(String shortName) { + this.shortName = shortName; + } + + public String getShortName() { + return shortName; + } + } + + private List<TimeSlotProxy> backing; + private HashSet<TimeSlotKey> currentSchedule; + private HashMap<TimeSlotKey, TimeSlotProxy> existingSlots; + private DynaTableRequestFactory factory; + private HashSet<TimeSlotKey> initialSchedule; + private boolean acceptClicks = true; + + public TimeSlotListWidget(DynaTableRequestFactory factory) { + this.factory = factory; + table = new CellTable<TimeSlotListWidget.ScheduleRow>(ROWS_IN_A_DAY, + GWT.<TableResources> create(TableResources.class)); + table.addColumn(new WeekDayColumn(null), "Hour"); + for (WeekDay day : WeekDay.values()) { + WeekDayColumn col = new WeekDayColumn(day); + + class Updater implements FieldUpdater<ScheduleRow, String> { + private WeekDay columnDay; + + public Updater(WeekDay day) { + columnDay = day; + } + + public void update(int index, ScheduleRow row, String value) { + if (acceptClicks) { + row.toggleInUse(columnDay); + } + } + } + + FieldUpdater<ScheduleRow, String> fieldUpdater = new Updater(day); + col.setFieldUpdater(fieldUpdater); + table.addColumn(col, day.getShortName()); + } + + table.setRowCount(ROWS_IN_A_DAY, false); + table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED); + initWidget(uiBinder.createAndBindUi(this)); + } + + public void flush() { + HashMap<TimeSlotProxy, TimeSlotKey> index = new HashMap<TimeSlotProxy, TimeSlotKey>(); + + for (TimeSlotProxy slot : backing) { + index.put(slot, new TimeSlotKey(slot)); + } + + // Compute slots that need to be removed from the backing + initialSchedule.removeAll(currentSchedule); + + for (Iterator<TimeSlotProxy> iterator = backing.iterator(); iterator.hasNext();) { + TimeSlotProxy slot = iterator.next(); + TimeSlotKey key = index.get(slot); + if (initialSchedule.contains(key)) { + iterator.remove(); + } + } + } + + public void onPropertyChange(String... paths) { + } + + public void setDelegate(EditorDelegate<List<TimeSlotProxy>> delegate) { + } + + public void setValue(List<TimeSlotProxy> value) { + backing = value; + currentSchedule = new HashSet<TimeSlotKey>(); + existingSlots = new HashMap<TimeSlotKey, TimeSlotProxy>(); + + initialSchedule = new HashSet<TimeSlotKey>(); + + for (TimeSlotProxy slot : backing) { + TimeSlotKey key = new TimeSlotKey(slot); + currentSchedule.add(key); + existingSlots.put(key, slot); + initialSchedule.add(new TimeSlotKey(slot)); + } + + ArrayList<ScheduleRow> rows = new ArrayList<ScheduleRow>(ROWS_IN_A_DAY); + for (int i = 0; i < ROWS_IN_A_DAY; i++) { + rows.add(new ScheduleRow(FIRST_HOUR + i)); + } + table.setRowData(rows); + } + +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/TimeSlotListWidget.ui.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/TimeSlotListWidget.ui.xml new file mode 100644 index 0000000..6ae0e5b --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/TimeSlotListWidget.ui.xml
@@ -0,0 +1,13 @@ +<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> +<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" + xmlns:g="urn:import:com.google.gwt.user.client.ui" + xmlns:cv='urn:import:com.google.gwt.user.cellview.client'> + <ui:style> + .table { + width: 100%; + } + </ui:style> + <g:HTMLPanel> + <cv:CellTable ui:field="table" stylePrimaryName="{style.table}" /> + </g:HTMLPanel> +</ui:UiBinder> \ No newline at end of file
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java index 6f65c67..8a0a88c 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java
@@ -127,8 +127,8 @@ public String getNote() { return note; } - - public String getSchedule() { + + public String getScheduleDescription() { return getScheduleWithFilter(daysFilters); } @@ -148,11 +148,6 @@ return new Person(this); } - /** - * When this was written the RequestFactory required a persist method per - * type. That requirement should be relaxed very soon (and may well have been - * already if we forget to update this comment). - */ public void persist() { SchoolCalendarService.persist(this); } @@ -160,6 +155,10 @@ public void setAddress(Address address) { this.address = address; } + + public void setClassSchedule(Schedule schedule) { + this.classSchedule = schedule; + } public void setDaysFilter(List<Boolean> daysFilter) { assert daysFilter.size() == this.daysFilters.size();
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Schedule.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Schedule.java index 14b6ddb..114c1f1 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Schedule.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Schedule.java
@@ -16,14 +16,23 @@ package com.google.gwt.sample.dynatablerf.domain; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** - * Hold the relevant data for a Schedule. + * Holds the relevant data for a Schedule entity. + * This entity does not follow the usual pattern of providing getId(), getVersion() + * and findSchedule() methods for RequestFactory's use. + * {@link com.google.gwt.sample.dynatablerf.server.ScheduleLocator} handles + * those responsibilities instead. */ public class Schedule { private List<TimeSlot> timeSlots = new ArrayList<TimeSlot>(); + + private Integer key; + + private Integer revision; public Schedule() { } @@ -34,7 +43,9 @@ public String getDescription(List<Boolean> daysFilter) { String s = null; - for (TimeSlot timeSlot : timeSlots) { + ArrayList<TimeSlot> sortedSlots = new ArrayList<TimeSlot>(timeSlots); + Collections.sort(sortedSlots); + for (TimeSlot timeSlot : sortedSlots) { if (daysFilter.get(timeSlot.getDayOfWeek())) { if (s == null) { s = timeSlot.getDescription(); @@ -51,6 +62,30 @@ } } + public Integer getKey() { + return key; + } + + public Integer getRevision() { + return revision; + } + + public List<TimeSlot> getTimeSlots() { + return timeSlots; + } + + public void setKey(Integer key) { + this.key = key; + } + + public void setRevision(Integer revision) { + this.revision = revision; + } + + public void setTimeSlots(List<TimeSlot> timeSlots) { + this.timeSlots = new ArrayList<TimeSlot>(timeSlots); + } + @Override public String toString() { return getDescription(null);
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/TimeSlot.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/TimeSlot.java index c9ccec1..2b681c3 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/TimeSlot.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/TimeSlot.java
@@ -48,7 +48,11 @@ return -1; } else if (startMinutes > o.startMinutes) { return 1; - } + } else if (endMinutes < o.endMinutes) { + return -1; + } else if (endMinutes > o.endMinutes) { + return 1; + } } return 0;
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonFuzzer.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonFuzzer.java index 3a0c79b..251af9b 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonFuzzer.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonFuzzer.java
@@ -17,10 +17,8 @@ import com.google.gwt.sample.dynatablerf.domain.Person; import com.google.gwt.sample.dynatablerf.domain.Schedule; -import com.google.gwt.sample.dynatablerf.domain.TimeSlot; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Random; @@ -29,6 +27,8 @@ */ class PersonFuzzer { + public static final int MAX_PEOPLE = 100; + private static final String[] FIRST_NAMES = new String[] { "Inman", "Sally", "Omar", "Teddy", "Jimmy", "Cathy", "Barney", "Fred", "Eddie", "Carlos"}; @@ -42,16 +42,16 @@ "Basketball", "Computer Science", "Statistics", "Materials Engineering", "English Literature", "Geology"}; - private static final int CLASS_LENGTH_MINS = 50; - - private static final int MAX_PEOPLE = 100; - - private static final int MAX_SCHED_ENTRIES = 5; - - private static final int MIN_SCHED_ENTRIES = 1; - private static final int STUDENTS_PER_PROF = 5; + public static List<Schedule> collectSchedules(List<Person> randomPeople) { + List<Schedule> toReturn = new ArrayList<Schedule>(); + for (Person person : randomPeople) { + toReturn.add(person.getClassSchedule()); + } + return toReturn; + } + public static Person generatePerson() { Random rnd = new Random(); Person toReturn = generateRandomPerson(rnd); @@ -71,9 +71,7 @@ } private static Person generateRandomPerson(Random rnd) { - // 1 out of every so many people is a prof. - // - if (rnd.nextInt(STUDENTS_PER_PROF) == 1) { + if (isChosenAsProfessor(rnd)) { return generateRandomProfessor(rnd); } else { return generateRandomStudent(rnd); @@ -90,35 +88,11 @@ String subject = pickRandomString(rnd, SUBJECTS); prof.setDescription("Professor of " + subject); - generateRandomSchedule(rnd, prof.getClassSchedule()); + prof.setClassSchedule(ScheduleFuzzer.generateRandomSchedule(rnd)); return prof; } - private static void generateRandomSchedule(Random rnd, Schedule sched) { - int range = MAX_SCHED_ENTRIES - MIN_SCHED_ENTRIES + 1; - int howMany = MIN_SCHED_ENTRIES + rnd.nextInt(range); - - TimeSlot[] timeSlots = new TimeSlot[howMany]; - - for (int i = 0; i < howMany; ++i) { - int startHrs = 8 + rnd.nextInt(9); // 8 am - 5 pm - int startMins = 15 * rnd.nextInt(4); // on the hour or some quarter - int dayOfWeek = 1 + rnd.nextInt(5); // Mon - Fri - - int absStartMins = 60 * startHrs + startMins; // convert to minutes - int absStopMins = absStartMins + CLASS_LENGTH_MINS; - - timeSlots[i] = new TimeSlot(dayOfWeek, absStartMins, absStopMins); - } - - Arrays.sort(timeSlots); - - for (int i = 0; i < howMany; ++i) { - sched.addTimeSlot(timeSlots[i]); - } - } - private static Person generateRandomStudent(Random rnd) { Person student = new Person(); @@ -129,13 +103,18 @@ String subject = pickRandomString(rnd, SUBJECTS); student.setDescription("Majoring in " + subject); - generateRandomSchedule(rnd, student.getClassSchedule()); + student.setClassSchedule(ScheduleFuzzer.generateRandomSchedule(rnd)); return student; } + private static boolean isChosenAsProfessor(Random rnd) { + return rnd.nextInt(STUDENTS_PER_PROF + 1) == 0; + } + private static String pickRandomString(Random rnd, String[] a) { int i = rnd.nextInt(a.length); return a[i]; } + }
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonSource.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonSource.java index 1279342..e5e66ec 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonSource.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/PersonSource.java
@@ -19,6 +19,7 @@ import static com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory.SchoolCalendarRequest.NO_DAYS; import com.google.gwt.sample.dynatablerf.domain.Person; +import com.google.gwt.sample.dynatablerf.domain.Schedule; import java.util.ArrayList; import java.util.Collections; @@ -36,6 +37,11 @@ public abstract class PersonSource { static class Backing extends PersonSource { private Long serial = 0L; + private final ScheduleSource scheduleStore; + + public Backing(ScheduleSource scheduleStore) { + this.scheduleStore = scheduleStore; + } @Override public int countPeople() { @@ -94,6 +100,9 @@ person.setId(Long.toString(++serial)); } person.setVersion(person.getVersion() + 1); + if (person.getClassSchedule() != null) { + scheduleStore.persist(person.getClassSchedule()); + } Person existing = people.get(person.getId()); if (existing != null) { existing.copyFrom(person); @@ -105,9 +114,11 @@ static class CopyOnRead extends PersonSource { private final PersonSource backingStore; + private final ScheduleSource scheduleStore; - public CopyOnRead(PersonSource backingStore) { + public CopyOnRead(PersonSource backingStore, ScheduleSource scheduleStore) { this.backingStore = backingStore; + this.scheduleStore = scheduleStore; } @Override @@ -122,6 +133,10 @@ toReturn = backingStore.findPerson(id); if (toReturn != null) { toReturn = toReturn.makeCopy(); + + Integer scheduleKey = toReturn.getClassSchedule().getKey(); + Schedule scheduleCopy = scheduleStore.find(scheduleKey); + toReturn.setClassSchedule(scheduleCopy); } people.put(id, toReturn); } @@ -150,8 +165,8 @@ /** * Create a PersonSource that will act directly on the given list. */ - public static PersonSource of(List<Person> people) { - PersonSource backing = new Backing(); + public static PersonSource of(List<Person> people, ScheduleSource schedules) { + PersonSource backing = new Backing(schedules); for (Person person : people) { backing.persist(person); } @@ -162,8 +177,8 @@ * Create a PersonSource that will read through to the given source and make * copies of any objects that are requested. */ - public static PersonSource of(PersonSource backing) { - return new CopyOnRead(backing); + public static PersonSource of(PersonSource backing, ScheduleSource scheduleBacking) { + return new CopyOnRead(backing, scheduleBacking); } final Map<String, Person> people = new LinkedHashMap<String, Person>();
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleFuzzer.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleFuzzer.java new file mode 100644 index 0000000..148a55b --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleFuzzer.java
@@ -0,0 +1,78 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.server; + +import com.google.gwt.sample.dynatablerf.domain.Schedule; +import com.google.gwt.sample.dynatablerf.domain.TimeSlot; + +import java.util.ArrayList; +import java.util.Random; +import java.util.TreeSet; + +/** + * Generates a list of random schedules. To facilitate the UI + * TimeSlots are defined in whole hour blocks. + */ +public class ScheduleFuzzer { + + private static final int MAX_SCHED_ENTRIES = 5; + + private static final int MIN_SCHED_ENTRIES = 1; + + private static final int CLASS_LENGTH_MINS = 50; + + private static final int NUMBER_OF_SCHEDULES = PersonFuzzer.MAX_PEOPLE; + + public static Schedule generateRandomSchedule(Random rnd) { + int range = MAX_SCHED_ENTRIES - MIN_SCHED_ENTRIES + 1; + int howMany = MIN_SCHED_ENTRIES + rnd.nextInt(range); + + ArrayList<TimeSlot> timeSlots = generateTimeSlots(rnd, howMany); + + Schedule sched = new Schedule(); + for (TimeSlot timeSlot : timeSlots) { + sched.addTimeSlot(timeSlot); + } + return sched; + } + + public static Schedule[] generateSchedules() { + Random rnd = new Random(); + Schedule[] toReturn = new Schedule[NUMBER_OF_SCHEDULES]; + for (int i = 0; i < NUMBER_OF_SCHEDULES; i++) { + Schedule sched = generateRandomSchedule(rnd); + toReturn[i] = sched; + } + return toReturn; + } + + private static ArrayList<TimeSlot> generateTimeSlots(Random rnd, int howMany) { + TreeSet<TimeSlot> timeSlots = new TreeSet<TimeSlot>(); + + for (int i = 0; i < howMany; ++i) { + int startHrs = 8 + rnd.nextInt(9); // 8 am - 5 pm + int dayOfWeek = 1 + rnd.nextInt(5); // Mon - Fri + + int absStartMins = 60 * startHrs; // convert to minutes + int absStopMins = absStartMins + CLASS_LENGTH_MINS; + + timeSlots.add(new TimeSlot(dayOfWeek, absStartMins, absStopMins)); + } + + return new ArrayList<TimeSlot>(timeSlots); + } + +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleLocator.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleLocator.java new file mode 100644 index 0000000..5b3c666 --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleLocator.java
@@ -0,0 +1,70 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.server; + +import com.google.gwt.requestfactory.shared.Locator; +import com.google.gwt.sample.dynatablerf.domain.Schedule; + +/** + * This class serves as an example of implementing a Locator to allow + * RequestFactory to work with entities that don't conform to its expectations of + * static find*() methods, and getId() and getVersion() methods. In a production + * application such a Locator might be the bridge to your dependency injection + * framework, or a data access object. + * <p> + * There is a reference to this class in a {@literal @}Service annotation in + * {@link com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory} + */ +public class ScheduleLocator extends Locator<Schedule, String> { + + public static ScheduleSource getThreadLocalObject() { + return SchoolCalendarService.SCHEDULE_SOURCE.get(); + } + + @Override + public Schedule create(Class<? extends Schedule> clazz) { + return getThreadLocalObject().create(clazz); + } + + @Override + public Schedule find(Class<? extends Schedule> clazz, String id) { + return getThreadLocalObject().find(clazz, id); + } + + @Override + public Class<Schedule> getDomainType() { + return getThreadLocalObject().getDomainType(); + } + + @Override + public String getId(Schedule domainObject) { + return getThreadLocalObject().getId(domainObject); + } + + @Override + public Class<String> getIdType() { + return getThreadLocalObject().getIdType(); + } + + @Override + public Object getVersion(Schedule domainObject) { + return getThreadLocalObject().getVersion(domainObject); + } + + public void persist(Schedule domainObject) { + getThreadLocalObject().persist(domainObject); + } +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleService.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleService.java new file mode 100644 index 0000000..5b9117a --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleService.java
@@ -0,0 +1,31 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.server; + +import com.google.gwt.sample.dynatablerf.domain.TimeSlot; + +/** + * Service object for Schedule entities, used to demonstrate the use of non-static + * service objects with RequestFactory. RequestFactory finds this service via the + * {@link ScheduleServiceLocator}. + */ +public class ScheduleService { + + public TimeSlot createTimeSlot(int zeroBasedDayOfWeek, int startMinutes, int endMinutes) { + return new TimeSlot(zeroBasedDayOfWeek, startMinutes, endMinutes); + } + +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleServiceLocator.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleServiceLocator.java new file mode 100644 index 0000000..92b82eb --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleServiceLocator.java
@@ -0,0 +1,34 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.server; + +import com.google.gwt.requestfactory.shared.ServiceLocator; + +/** + * This class provides an example of implementing a ServiceLocator to allow + * RequestFactory to work with instances of service objects, instead of its default + * behavior of mapping service calls to static methods. + * <p> + * There is a reference to this class in an {@literal @}Service annotation in + * {@link com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory} + */ +public class ScheduleServiceLocator implements ServiceLocator { + + public Object getInstance(Class<?> clazz) { + return clazz.equals(ScheduleService.class) ? new ScheduleService() : null; + } + +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleSource.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleSource.java new file mode 100644 index 0000000..46230a4 --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/ScheduleSource.java
@@ -0,0 +1,189 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.server; + +import com.google.gwt.sample.dynatablerf.domain.Schedule; +import com.google.gwt.sample.dynatablerf.domain.TimeSlot; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Provides a number of Schedule objects as a demonstration datasource. Many of + * the operations in this implementation would be much more efficient in a real + * database, but are implemented is a straightforward fashion because they're + * not really important for understanding the RequestFactory framework. + */ +public abstract class ScheduleSource { + + private static int serial = 0; + + /** + * Backing store of schedule entities. + */ + static class Backing extends ScheduleSource { + + @Override + public Schedule create(Class<? extends Schedule> clazz) { + return new Schedule(); + } + + @Override + public Schedule find(Class<? extends Schedule> clazz, String id) { + if (!Schedule.class.equals(clazz)) { + return null; + } + return schedules.get(makeKey(id)); + } + + @Override + public Class<Schedule> getDomainType() { + return Schedule.class; + } + + @Override + public String getId(Schedule domainObject) { + return Integer.toString(domainObject.getKey()); + } + + @Override + public Class<String> getIdType() { + return String.class; + } + + @Override + public Object getVersion(Schedule domainObject) { + return domainObject.getRevision(); + } + + @Override + public void persist(Schedule domainObject) { + if (domainObject.getKey() == null) { + domainObject.setKey(newSerial()); + } + domainObject.setRevision(newSerial()); + Schedule existing = schedules.get(domainObject.getKey()); + if (existing == null) { + schedules.put(domainObject.getKey(), domainObject); + } else { + copyScheduleFields(domainObject, existing); + } + } + } + + /** + * Provides copy-on-read access to a ScheduleLocator. + */ + public static class CopyOnRead extends Backing { + private final ScheduleSource backingStore; + + public CopyOnRead(ScheduleSource backingStore) { + this.backingStore = backingStore; + } + + @Override + public Schedule find(Class<? extends Schedule> clazz, String id) { + if (!Schedule.class.equals(clazz)) { + return null; + } + Integer key = makeKey(id); + Schedule toReturn = schedules.get(key); + if (toReturn == null) { + Schedule original = backingStore.find(clazz, id); + if (original != null) { + toReturn = makeCopy(original); + } + schedules.put(key, toReturn); + } + return toReturn; + } + + @Override + public void persist(Schedule domainObject) { + backingStore.persist(domainObject); + } + + private Schedule makeCopy(Schedule source) { + Schedule destination = new Schedule(); + copyScheduleFields(source, destination); + return destination; + } + } + + static void copyScheduleFields(Schedule source, Schedule destination) { + destination.setKey(source.getKey()); + destination.setRevision(source.getRevision()); + destination.setTimeSlots(new ArrayList<TimeSlot>(source.getTimeSlots())); + } + + public static Backing createBacking() { + return new Backing(); + } + + public static ScheduleSource getThreadLocalObject() { + return SchoolCalendarService.SCHEDULE_SOURCE.get(); + } + + /** + * Create a ScheduleLocator that will act directly on the given list. + */ + public static ScheduleSource of(List<Schedule> schedules) { + ScheduleSource backing = createBacking(); + for (Schedule schedule : schedules) { + backing.persist(schedule); + } + return backing; + } + + /** + * Create a ScheduleLocator that will read through to the given source and make + * copies of any objects that are requested. + */ + public static ScheduleSource of(ScheduleSource backing) { + return new CopyOnRead(backing); + } + + private static Integer makeKey(String id) { + return Integer.valueOf(id); + } + + private static int newSerial() { + return ++serial; + } + + final Map<Integer, Schedule> schedules = new LinkedHashMap<Integer, Schedule>(); + + public abstract Schedule create(Class<? extends Schedule> clazz); + + public Schedule find(Integer key) { + return find(Schedule.class, key.toString()); + } + + public abstract Schedule find(Class<? extends Schedule> clazz, String id); + + public abstract Class<Schedule> getDomainType(); + + public abstract String getId(Schedule domainObject); + + public abstract Class<String> getIdType(); + + public abstract Object getVersion(Schedule domainObject); + + public abstract void persist(Schedule domainObject); + +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java index b4097cf..a55935a 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java
@@ -36,6 +36,7 @@ public class SchoolCalendarService implements Filter { private static final ThreadLocal<PersonSource> PERSON_SOURCE = new ThreadLocal<PersonSource>(); + static final ThreadLocal<ScheduleSource> SCHEDULE_SOURCE = new ThreadLocal<ScheduleSource>(); public static Person createPerson() { checkPersonSource(); @@ -74,6 +75,7 @@ } private PersonSource backingStore; + private ScheduleSource scheduleStore; public void destroy() { } @@ -81,10 +83,13 @@ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { try { - PERSON_SOURCE.set(PersonSource.of(backingStore)); + ScheduleSource scheduleBacking = ScheduleSource.of(scheduleStore); + SCHEDULE_SOURCE.set(scheduleBacking); + PERSON_SOURCE.set(PersonSource.of(backingStore, scheduleBacking)); chain.doFilter(req, resp); } finally { PERSON_SOURCE.set(null); + SCHEDULE_SOURCE.set(null); } } @@ -92,7 +97,9 @@ backingStore = (PersonSource) config.getServletContext().getAttribute( SchoolCalendarService.class.getName()); if (backingStore == null) { - backingStore = PersonSource.of(PersonFuzzer.generateRandomPeople()); + List<Person> randomPeople = PersonFuzzer.generateRandomPeople(); + scheduleStore = ScheduleSource.of(PersonFuzzer.collectSchedules(randomPeople)); + backingStore = PersonSource.of(randomPeople, scheduleStore); config.getServletContext().setAttribute( SchoolCalendarService.class.getName(), backingStore); }
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java index ce18e88..5e6c34d 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java
@@ -22,6 +22,8 @@ import com.google.gwt.requestfactory.shared.RequestFactory; import com.google.gwt.requestfactory.shared.Service; import com.google.gwt.sample.dynatablerf.domain.Person; +import com.google.gwt.sample.dynatablerf.server.ScheduleService; +import com.google.gwt.sample.dynatablerf.server.ScheduleServiceLocator; import com.google.gwt.sample.dynatablerf.server.SchoolCalendarService; import java.util.Arrays; @@ -57,9 +59,20 @@ Request<PersonProxy> getRandomPerson(); } + /** + * Source of request objects for Schedule entities. + */ + @Service(value = ScheduleService.class, locator = ScheduleServiceLocator.class) + interface ScheduleRequest extends RequestContext { + Request<TimeSlotProxy> createTimeSlot(int zeroBasedDayOfWeek, int startMinutes, + int endMinutes); + } + LoggingRequest loggingRequest(); PersonRequest personRequest(); + + ScheduleRequest scheduleRequest(); SchoolCalendarRequest schoolCalendarRequest(); }
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java index bcd5dd9..ccec247 100644 --- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java
@@ -28,6 +28,8 @@ AddressProxy getAddress(); + ScheduleProxy getClassSchedule(); + String getDescription(); PersonProxy getMentor(); @@ -36,10 +38,12 @@ String getNote(); - String getSchedule(); - + String getScheduleDescription(); + void setAddress(AddressProxy address); + void setClassSchedule(ScheduleProxy schedule); + void setDescription(String description); void setMentor(PersonProxy mentor); @@ -47,6 +51,6 @@ void setName(String name); void setNote(String note); - + EntityProxyId<PersonProxy> stableId(); }
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/ScheduleProxy.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/ScheduleProxy.java new file mode 100644 index 0000000..d7f4716 --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/ScheduleProxy.java
@@ -0,0 +1,32 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.shared; + +import com.google.gwt.requestfactory.shared.EntityProxy; +import com.google.gwt.requestfactory.shared.ProxyFor; +import com.google.gwt.sample.dynatablerf.domain.Schedule; +import com.google.gwt.sample.dynatablerf.server.ScheduleLocator; + +import java.util.List; + +/** + * Schedule DTO. + */ +@ProxyFor(value = Schedule.class, locator = ScheduleLocator.class) +public interface ScheduleProxy extends EntityProxy { + List<TimeSlotProxy> getTimeSlots(); + void setTimeSlots(List<TimeSlotProxy> slots); +}
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/TimeSlotProxy.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/TimeSlotProxy.java new file mode 100644 index 0000000..ab2beec --- /dev/null +++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/TimeSlotProxy.java
@@ -0,0 +1,38 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.sample.dynatablerf.shared; + +import com.google.gwt.requestfactory.shared.ProxyFor; +import com.google.gwt.requestfactory.shared.ValueProxy; +import com.google.gwt.sample.dynatablerf.domain.TimeSlot; + +/** + * TimeSlot DTO. + */ +@ProxyFor(TimeSlot.class) +public interface TimeSlotProxy extends ValueProxy { + int getDayOfWeek(); + + int getEndMinutes(); + + int getStartMinutes(); + + void setDayOfWeek(int zeroBasedDayOfWeek); + + void setEndMinutes(int endMinutes); + + void setStartMinutes(int startMinutes); +}