/* * Copyright 2013 McEvoy Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.bandstand.web; import com.bandstand.domain.Band; import com.bandstand.domain.BandMember; import com.bandstand.domain.Gig; import com.bandstand.domain.Musician; import com.bandstand.domain.SessionManager; import com.bandstand.util.CalUtils; import io.milton.annotations.AccessControlList; import io.milton.annotations.Calendars; import io.milton.annotations.ChildrenOf; import io.milton.annotations.CreatedDate; import io.milton.annotations.Delete; import io.milton.annotations.Get; import io.milton.annotations.ICalData; import io.milton.annotations.MakeCalendar; import io.milton.annotations.ModifiedDate; import io.milton.annotations.PutChild; import io.milton.annotations.ResourceController; import io.milton.http.annotated.AnnoResource; import io.milton.resource.AccessControlledResource; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import net.fortuna.ical4j.data.CalendarBuilder; import net.fortuna.ical4j.data.CalendarOutputter; import net.fortuna.ical4j.data.ParserException; import net.fortuna.ical4j.model.Calendar; import net.fortuna.ical4j.model.Property; import net.fortuna.ical4j.model.TimeZone; import net.fortuna.ical4j.model.TimeZoneRegistry; import net.fortuna.ical4j.model.TimeZoneRegistryFactory; import net.fortuna.ical4j.model.component.VEvent; import net.fortuna.ical4j.model.component.VTimeZone; import net.fortuna.ical4j.model.parameter.Role; import net.fortuna.ical4j.model.parameter.Rsvp; import net.fortuna.ical4j.model.parameter.TzId; import net.fortuna.ical4j.model.property.Attendee; import net.fortuna.ical4j.model.property.ProdId; import net.fortuna.ical4j.model.property.Uid; import net.fortuna.ical4j.model.property.Version; import org.hibernate.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Gig is a calendar item (ie an event), and it is inside a logical calendar, * which is itse * * @author brad */ @ResourceController public class GigController { private static final Logger log = LoggerFactory.getLogger(GigController.class); @ChildrenOf public MusicianCalendarsHome getCalendarsHomeForMusician(Musician m) { return new MusicianCalendarsHome(m); } @Calendars @ChildrenOf public List<MusicianCalendar> getCalendarsForMusician(MusicianCalendarsHome calHome) { List<MusicianCalendar> cals = new ArrayList<MusicianCalendar>(); if (calHome.musician.getBandMembers() != null) { for (BandMember bm : calHome.musician.getBandMembers()) { MusicianCalendar cal = new MusicianCalendar(calHome.musician, bm.getBand()); cals.add(cal); } } return cals; } /** * This method is just a bogus example showing that you can have ACL methods * for different objects in a hierarchy. In this case we make a rule that a band * with a name ending with 'ReadOnly' will be read-only for everyone. * * @param target * @param currentUser * @return */ @AccessControlList public List<AccessControlledResource.Priviledge> getMusicianCalendarPrivs(MusicianCalendar target, Musician currentUser) { System.out.println("getMusicianCalendarPrivs: " + currentUser); if (target.musician == currentUser) { Band band = target.band; if (band.getName().endsWith("ReadOnly")) { return AccessControlledResource.READ_BROWSE; } return AccessControlledResource.READ_WRITE; } else { return null; } } @AccessControlList public List<AccessControlledResource.Priviledge> getMusicianPrivs(Musician target, Musician currentUser) { if (target == currentUser) { return AccessControlledResource.READ_WRITE; } else { // This prevents read access to each others calendars return null; // This gives read access to each others calendars //return AccessControlledResource.READ_CONTENT; } } /** * Deletes the given Gig object. This method also takes a Musician object as * a parameter to demonstrate how it is possible to get a reference to a parent * object in the hierarchy * * @param gig * @param musician */ @Delete public void delete(Gig gig, Musician musician) { log.info("delete gig gigId=" + gig.getId() + " - musicianId=" + musician.getId()); Transaction tx = SessionManager.session().beginTransaction(); try { SessionManager.session().delete(gig); SessionManager.session().flush(); tx.commit(); } catch (Exception e) { tx.rollback(); } } @Delete public void delete(MusicianCalendar cal) { Transaction tx = SessionManager.session().beginTransaction(); try { cal.musician.removeFromBand(cal.band, SessionManager.session()); tx.commit(); } catch (Exception e) { tx.rollback(); } } @ChildrenOf public List<Gig> getGigs(MusicianCalendar cal) { return cal.getBand().getGigs(); } @PutChild public Gig uploadGig(MusicianCalendar cal, String name, byte[] arr) throws IOException, ParserException { Gig gig = cal.band.addGig(name, null); gig.setFileName(name); updateGig(gig, arr); return gig; } @PutChild public Gig updateGig(Gig gig, byte[] ical) throws IOException, ParserException { log.info("updateGig: " + gig.getDisplayName()); Transaction tx = SessionManager.session().beginTransaction(); try { CalendarBuilder builder = new CalendarBuilder(); ByteArrayInputStream bin = new ByteArrayInputStream(ical); System.out.println(bin.toString()); Calendar calendar = builder.build(bin); VEvent ev = (VEvent) calendar.getComponent("VEVENT"); gig.setStartDate(ev.getStartDate().getDate()); Date endDate = null; if (ev.getEndDate() != null) { endDate = ev.getEndDate().getDate(); } gig.setEndDate(endDate); String summary = null; if (ev.getSummary() != null) { summary = ev.getSummary().getValue(); } gig.setDisplayName(summary); gig.setModifiedDate(new Date()); SessionManager.session().save(gig); SessionManager.session().flush(); tx.commit(); System.out.println("Updated gig: " + gig.getStartDate() + " - " + gig.getEndDate()); } catch (Exception e) { tx.rollback(); } return gig; } @Get @ICalData public byte[] getIcalData(Gig gig) { net.fortuna.ical4j.model.Calendar calendar = new net.fortuna.ical4j.model.Calendar(); calendar.getProperties().add(new ProdId("-//spliffy.org//iCal4j 1.0//EN")); calendar.getProperties().add(Version.VERSION_2_0); //calendar.getProperties().add(CalScale.GREGORIAN); TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); TimeZone timezone = registry.getTimeZone("Pacific/Auckland"); VTimeZone tz = timezone.getVTimeZone(); calendar.getComponents().add(tz); net.fortuna.ical4j.model.DateTime start = CalUtils.toCalDateTime(gig.getStartDate(), timezone); net.fortuna.ical4j.model.DateTime finish = CalUtils.toCalDateTime(gig.getEndDate(), timezone); String summary = gig.getDisplayName(); VEvent vevent = new VEvent(start, finish, summary); //vevent.getProperties().add(new Uid(UUID.randomUUID().toString())); vevent.getProperties().add(new Uid(gig.getFileName())); vevent.getProperties().add(tz.getTimeZoneId()); TzId tzParam = new TzId(tz.getProperties().getProperty(Property.TZID).getValue()); vevent.getProperties().getProperty(Property.DTSTART).getParameters().add(tzParam); Attendee attendee = new Attendee(URI.create("mailto:xxx1@bradmcevoy.com")); attendee.getParameters().add(Role.REQ_PARTICIPANT);//required participants. attendee.getParameters().add(Rsvp.TRUE);//to get the status request from the attendees vevent.getProperties().add(attendee); calendar.getComponents().add(vevent); CalendarOutputter outputter = new CalendarOutputter(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); try { outputter.output(calendar, bout); } catch (Exception ex) { throw new RuntimeException(ex); } System.out.println("ical: " + bout.toString()); return bout.toByteArray(); } @ModifiedDate public Date getModifiedDate(Gig gig) { return gig.getModifiedDate(); } @CreatedDate public Date getCreatedDate(Gig gig) { return gig.getCreatedDate(); } public class MusicianCalendarsHome { private final Musician musician; public MusicianCalendarsHome(Musician musician) { this.musician = musician; } public String getName() { return "cals"; } } public class MusicianCalendar { private final Musician musician; private final Band band; public MusicianCalendar(Musician musician, Band band) { this.musician = musician; this.band = band; } public String getName() { return band.getName(); } public Musician getMusician() { return musician; } public Band getBand() { return band; } } }