org.estatio.dom.lease.breaks.BreakOption.java Source code

Java tutorial

Introduction

Here is the source code for org.estatio.dom.lease.breaks.BreakOption.java

Source

/*
 *
 *  Copyright 2012-2014 Eurocommercial Properties NV
 *
 *
 *  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 org.estatio.dom.lease.breaks;

import java.util.List;
import javax.jdo.annotations.DiscriminatorStrategy;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.VersionStrategy;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.apache.isis.applib.annotation.CollectionLayout;
import org.apache.isis.applib.annotation.DomainObject;
import org.apache.isis.applib.annotation.Editing;
import org.apache.isis.applib.annotation.Optionality;
import org.apache.isis.applib.annotation.Parameter;
import org.apache.isis.applib.annotation.ParameterLayout;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.annotation.PropertyLayout;
import org.apache.isis.applib.annotation.Property;
import org.apache.isis.applib.annotation.RenderType;
import org.apache.isis.applib.annotation.Title;
import org.apache.isis.applib.annotation.Where;
import org.isisaddons.module.security.dom.tenancy.ApplicationTenancy;
import org.isisaddons.wicket.fullcalendar2.cpt.applib.CalendarEventable;

import org.estatio.dom.EstatioDomainObject;
import org.estatio.dom.JdoColumnLength;
import org.estatio.dom.apptenancy.WithApplicationTenancyProperty;
import org.estatio.dom.event.Event;
import org.estatio.dom.event.EventSource;
import org.estatio.dom.event.Events;
import org.estatio.dom.lease.Lease;
import org.estatio.dom.utils.JodaPeriodUtils;

/**
 * Represents a condition upon which the {@link Lease} can be terminated.
 */
@javax.jdo.annotations.PersistenceCapable(identityType = IdentityType.DATASTORE)
@javax.jdo.annotations.DatastoreIdentity(strategy = IdGeneratorStrategy.NATIVE, column = "id")
@javax.jdo.annotations.Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version")
@javax.jdo.annotations.Discriminator(strategy = DiscriminatorStrategy.CLASS_NAME, column = "discriminator")
@javax.jdo.annotations.Unique(name = "BreakOption_lease_type_exerciseDate_UNQ", members = { "lease", "type",
        "exerciseDate" })
@javax.jdo.annotations.Queries({
        @javax.jdo.annotations.Query(name = "findByLease", language = "JDOQL", value = "SELECT "
                + "FROM org.estatio.dom.lease.breaks.BreakOption " + "WHERE lease == :lease") })
@DomainObject(editing = Editing.DISABLED)
public abstract class BreakOption extends EstatioDomainObject<BreakOption>
        implements EventSource, WithApplicationTenancyProperty {

    public BreakOption() {
        super("lease, type, exerciseType, breakDate, exerciseDate");
    }

    // //////////////////////////////////////

    @PropertyLayout(named = "Application Level", describedAs = "Inherited from Lease; determines those users for whom this object is available to view and/or modify.")
    public ApplicationTenancy getApplicationTenancy() {
        return getLease().getApplicationTenancy();
    }

    // //////////////////////////////////////

    private Lease lease;

    @javax.jdo.annotations.Column(name = "leaseId", allowsNull = "false")
    @Title(sequence = "1", append = ":")
    @Property(hidden = Where.REFERENCES_PARENT)
    public Lease getLease() {
        return lease;
    }

    public void setLease(final Lease lease) {
        this.lease = lease;
    }

    // //////////////////////////////////////

    private BreakType type;

    @javax.jdo.annotations.Column(allowsNull = "false", length = JdoColumnLength.TYPE_ENUM)
    @Title(sequence = "2")
    public BreakType getType() {
        return type;
    }

    public void setType(final BreakType breakType) {
        this.type = breakType;
    }

    // //////////////////////////////////////

    @javax.jdo.annotations.Persistent
    private LocalDate exerciseDate;

    /**
     * The date on which this break option can be exercised, meaning that the
     * other party to the lease is notified (also known as <i>notification
     * date</i>).
     * 
     * <p>
     * The exact semantics depend upon the particular {@link #getType() type}
     * (subclass) of option:
     * <ul>
     * <li>
     * In the case of the {@link FixedBreakOption}, the notification date is the
     * <i>last</i> date that an option can be exercised (it can also be
     * exercised any date prior to the notification date).</li>
     * <li>
     * In the case of a {@link RollingBreakOption}, the notification date is the
     * <i>first</i> date at which a option can be exercised (it can also be
     * exercised any date after the notification date).</li>
     * </ul>
     * 
     * <p>
     * To avoid misunderstandings in the UI, both subtypes rename the property
     * (using Isis' <tt>@Named</tt> annotation).
     */
    @javax.jdo.annotations.Column(allowsNull = "false")
    @Title(prepend = " ", sequence = "3")
    public LocalDate getExerciseDate() {
        return exerciseDate;
    }

    public void setExerciseDate(final LocalDate exerciseDate) {
        this.exerciseDate = exerciseDate;
    }

    // //////////////////////////////////////

    private BreakExerciseType exerciseType;

    @javax.jdo.annotations.Column(allowsNull = "false", length = JdoColumnLength.BreakOption.EXERCISE_TYPE_ENUM)
    public BreakExerciseType getExerciseType() {
        return exerciseType;
    }

    public void setExerciseType(final BreakExerciseType breakExerciseType) {
        this.exerciseType = breakExerciseType;
    }

    // //////////////////////////////////////

    private String notificationPeriod;

    @javax.jdo.annotations.Column(allowsNull = "true", length = JdoColumnLength.DURATION)
    public String getNotificationPeriod() {
        return notificationPeriod;
    }

    public void setNotificationPeriod(final String notificationPeriod) {
        this.notificationPeriod = notificationPeriod;
    }

    /**
     * Convenience for subclasses.
     */
    protected Period getNotificationPeriodJoda() {
        return JodaPeriodUtils.asPeriod(getNotificationPeriod());
    }

    // //////////////////////////////////////

    @javax.jdo.annotations.Persistent
    private LocalDate breakDate;

    /**
     * The date when the {@link #getLease() lease} can be terminated (assuming
     * that the notice was given on or before the {@link #getNotificationDate()
     * notification date}).
     */
    @javax.jdo.annotations.Column(allowsNull = "false")
    public LocalDate getBreakDate() {
        return breakDate;
    }

    public void setBreakDate(final LocalDate breakDate) {
        this.breakDate = breakDate;
    }

    // //////////////////////////////////////

    private String description;

    @javax.jdo.annotations.Column(allowsNull = "true", length = JdoColumnLength.DESCRIPTION)
    @Property(hidden = Where.PARENTED_TABLES, optionality = Optionality.OPTIONAL)
    public String getDescription() {
        return description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    // //////////////////////////////////////

    public BreakOption change(final @ParameterLayout(named = "Type") BreakType breakType,
            final @ParameterLayout(named = "Exercise Type") BreakExerciseType breakExerciseType,
            final @ParameterLayout(named = "Description") @Parameter(optionality = Optionality.OPTIONAL) String description) {
        setType(breakType);
        setExerciseType(breakExerciseType);
        setDescription(description);

        // re-create events
        removeExistingEvents();
        createEvents();

        return this;
    }

    private void removeExistingEvents() {
        // remove existing events
        for (final Event event : findEvents()) {
            events.remove(event);
        }
    }

    public BreakType default0Change() {
        return getType();
    }

    public BreakExerciseType default1Change() {
        return getExerciseType();
    }

    public String default2Change() {
        return getDescription();
    }

    public BreakOption changeDates(final @ParameterLayout(named = "Break date") LocalDate newBreakDate,
            final @ParameterLayout(named = "Excercise date") LocalDate newExcerciseDate) {
        setBreakDate(newBreakDate);
        setExerciseDate(newExcerciseDate);

        // re-create events
        removeExistingEvents();
        createEvents();

        return this;
    }

    public LocalDate default0ChangeDates() {
        return getBreakDate();
    }

    public LocalDate default1ChangeDates() {
        return getExerciseDate();
    }

    // //////////////////////////////////////

    public Lease remove(final @ParameterLayout(named = "Reason") String reason) {
        Lease lease = getLease();
        doRemove();
        return lease;
    }

    @Programmatic
    public void doRemove() {
        for (Event event : findEvents()) {
            getContainer().remove(event);
        }
        getContainer().remove(this);
    }

    // //////////////////////////////////////

    /**
     * The date when the {@link #getLease() lease} can be terminated.
     * 
     * <p>
     * In the case of an {@link FixedBreakOption}, this is a fixed date. In the
     * case of a {@link RollingBreakOption}, this date will be fixed until the
     * {@link RollingBreakOption#getEarliestNotificationDate() notification
     * date} has been reached; thereafter it will change on a daily basis (being
     * the current date plus the {@link #getNotificationPeriod() notification
     * period}.
     */
    public abstract LocalDate getCurrentBreakDate();

    // //////////////////////////////////////

    /**
     * to display in fullcalendar2
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Programmatic
    @Override
    public ImmutableMap<String, CalendarEventable> getCalendarEvents() {
        final ImmutableMap eventsByCalendarName = Maps.uniqueIndex(findEvents(), Event.Functions.GET_CALENDAR_NAME);
        return eventsByCalendarName;
    }

    private List<Event> findEvents() {
        return events.findBySource(this);
    }

    // //////////////////////////////////////

    /**
     * For subclasses to call, eg in their <tt>persisting()</tt> callback
     * methods.
     */
    protected Event createEvent(final LocalDate date, final EventSource subject, final String subjectEventType) {
        return events.newEvent(date, subject, subjectEventType);
    }

    // //////////////////////////////////////

    public static final class Predicates {
        private Predicates() {
        }

        public static Predicate<BreakOption> whetherTypeAndBreakDate(final BreakType type,
                final LocalDate breakDate) {
            return com.google.common.base.Predicates.and(whetherType(type), whetherBreakDate(breakDate));
        }

        public static Predicate<BreakOption> whetherType(final BreakType type) {
            return new Predicate<BreakOption>() {
                @Override
                public boolean apply(final BreakOption breakOption) {
                    return Objects.equal(breakOption.getType(), type);
                }
            };
        }

        public static Predicate<BreakOption> whetherBreakDate(final LocalDate breakDate) {
            return new Predicate<BreakOption>() {
                @Override
                public boolean apply(final BreakOption breakOption) {
                    return Objects.equal(breakOption.getBreakDate(), breakDate);
                }
            };
        }
    }

    // //////////////////////////////////////

    public void persisted() {
        createEvents();
    }

    protected void createEvents() {
        throw new IllegalAccessError("Subclass must override");
    }

    // //////////////////////////////////////

    protected Events events;

    public final void injectEvents(final Events events) {
        this.events = events;
    }

}