📄 appointmentimpl.java
字号:
/*--------------------------------------------------------------------------*
| Copyright (C) 2006 Christopher Kohlhaas |
| |
| 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. A copy of the license has been included with |
| these distribution in the COPYING file, if not go to www.fsf.org . |
| |
| As a special exception, you are granted the permissions to link this |
| program with every library, which license fulfills the Open Source |
| Definition as published by the Open Source Initiative (OSI). |
*--------------------------------------------------------------------------*/
package org.rapla.entities.domain.internal;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.rapla.components.util.Assert;
import org.rapla.components.util.DateTools;
import org.rapla.components.util.Tools;
import org.rapla.entities.RaplaType;
import org.rapla.entities.domain.Appointment;
import org.rapla.entities.domain.AppointmentBlockArray;
import org.rapla.entities.domain.Repeating;
import org.rapla.entities.domain.Reservation;
import org.rapla.entities.storage.Mementable;
import org.rapla.entities.storage.internal.SimpleEntity;
public class AppointmentImpl extends SimpleEntity implements Appointment, Mementable,java.io.Serializable
{
// Don't forget to increase the serialVersionUID when you change the fields
private static final long serialVersionUID = 1;
private Date start;
private Date end;
private RepeatingImpl repeating;
private boolean isWholeDaysSet = false;
/** set DE (DebugDisabled) to false for debuging output. You must change in code
because this flag is final for efficience reasons.*/
public final static boolean DE = true;
public final static String BUG = null;
public static String DD = null;
final public RaplaType getRaplaType() {return TYPE;}
private AppointmentImpl() {
}
public AppointmentImpl(Date start,Date end) {
this.start = start;
this.end = end;
}
void setParent(Reservation parent) {
getReferenceHandler().put("parent",parent);
if (parent != null)
setOwner(parent.getOwner());
}
public void removeParent()
{
getReferenceHandler().removeId("parent");
setOwner( null );
}
public Date getStart() { return start;}
public Date getEnd() { return end;}
public void setReadOnly(boolean enable) {
super.setReadOnly( enable );
if ( repeating != null )
repeating.setReadOnly( enable );
}
public void move(Date newStart) {
long diff = this.end.getTime() - this.start.getTime();
move(newStart, new Date(newStart.getTime() + diff));
}
public void move(Date start,Date end) {
checkWritable();
this.start = start;
this.end = end;
}
public String toString() {
if (start != null && end != null)
return f(start.getTime(),end.getTime()) +
((repeating != null) ? (" [" + repeating.toString()) + "]": "");
else
return start + "-" + end;
}
public Reservation getReservation() {
return (Reservation)getReferenceHandler().get("parent");
}
public boolean isWholeDaysSet() {
return isWholeDaysSet;
}
public void setWholeDays(boolean enable) {
checkWritable();
if (enable) {
if (start.getTime() != DateTools.cutDate(start.getTime()))
this.start = DateTools.cutDate(this.start);
if (start.getTime() != DateTools.cutDate(end.getTime()))
this.end = DateTools.fillDate(this.end);
}
isWholeDaysSet = enable;
}
public int compareTo(Object obj) {
if (!(obj instanceof Appointment))
throw new ClassCastException ("Appointment Expected");
Appointment a2 = (Appointment) obj;
Date start2 = a2.getStart();
Date end2 = a2.getEnd();
if (start.before( start2))
return -1;
if (start.after( start2))
return 1;
if (getEnd().before( end2))
return -1;
if (getEnd().after( end2))
return 1;
return 0;
}
transient Date maxDate;
/** returns the largest date that covers the appointment
and null if the appointments repeats forever.
*/
public Date getMaxEnd() {
long end = (this.end!= null) ? this.end.getTime():0;
if (repeating != null)
if (repeating.getEnd() != null)
end = Math.max(end
,repeating.getEnd().getTime());
else
end = 0;
if (end == 0)
return null;
// cache max date object
if (maxDate == null || maxDate.getTime() != end)
maxDate = new Date(end);
return maxDate;
}
public Repeating getRepeating() {
return repeating;
}
public void setRepeatingEnabled(boolean enableRepeating) {
checkWritable();
if (this.repeating == null) {
if (enableRepeating) {
this.repeating = new RepeatingImpl(Repeating.WEEKLY,this);
}
} else {
if (!enableRepeating) {
this.repeating = null;
}
}
}
public boolean isRepeatingEnabled() {
return repeating != null;
}
public Date getFirstDifference( Appointment a2, Date maxDate ) {
AppointmentBlockArray blocks1 = new AppointmentBlockArray();
createBlocks( start, maxDate, blocks1);
AppointmentBlockArray blocks2 = new AppointmentBlockArray();
a2.createBlocks(a2.getStart(), maxDate, blocks2);
// System.out.println("block sizes " + blocks1.size() + ", " + blocks2.size() );
for ( int i = 0; i < blocks1.size(); i++ ) {
long a1Start = blocks1.getStartAt( i );
long a1End = blocks1.getEndAt( i );
if ( i >= blocks2.size() ) {
return new Date( a1Start );
}
long a2Start = blocks2.getStartAt( i );
long a2End = blocks2.getEndAt( i );
//System.out.println("a1Start " + a1Start + " a1End " + a1End);
//System.out.println("a2Start " + a2Start + " a2End " + a2End);
if ( a1Start != a2Start )
return new Date( Math.min ( a1Start, a2Start ) );
if ( a1End != a2End )
return new Date( Math.min ( a1End, a2End ) );
}
if ( blocks2.size() > blocks1.size() ) {
return new Date( blocks2.getStartAt( blocks1.size() ) );
}
return null;
}
public Date getLastDifference( Appointment a2, Date maxDate ) {
AppointmentBlockArray blocks1 = new AppointmentBlockArray();
createBlocks( start, maxDate, blocks1);
AppointmentBlockArray blocks2 = new AppointmentBlockArray();
a2.createBlocks(a2.getStart(), maxDate, blocks2);
if ( blocks2.size() > blocks1.size() ) {
return new Date( blocks2.getEndAt( blocks1.size() ) );
}
if ( blocks1.size() > blocks2.size() ) {
return new Date( blocks1.getEndAt( blocks2.size() ) );
}
for ( int i = blocks1.size() - 1 ; i >= 0; i-- ) {
long a1Start = blocks1.getStartAt( i );
long a1End = blocks1.getEndAt( i );
long a2Start = blocks2.getStartAt( i );
long a2End = blocks2.getEndAt( i );
if ( a1End != a2End )
return new Date( Math.max ( a1End, a2End ) );
if ( a1Start != a2Start )
return new Date( Math.max ( a1Start, a2Start ) );
}
return null;
}
public boolean matches(Appointment a2) {
if (!Tools.equalsOrBothNull(this.start, a2.getStart()))
return false;
if (!Tools.equalsOrBothNull(this.end, a2.getEnd()))
return false;
Repeating r1 = this.repeating;
Repeating r2 = a2.getRepeating();
// No repeatings. The two appointments match
if (r1 == null && r2 == null) {
return true;
} else if (r1 == null || r2 == null) {
// one repeating is null the other not so the appointments don't match
return false;
}
if (!r1.getType().equals(r2.getType()))
return false;
if (r1.getInterval() != r2.getInterval())
return false;
if (!Tools.equalsOrBothNull(r1.getEnd(), r2.getEnd()))
return false;
// The repeatings match regulary, so we must test the exceptions
Date[] e1 = r1.getExceptions();
Date[] e2 = r2.getExceptions();
if (e1.length != e2.length) {
//System.out.println("Exception-length don't match");
return false;
}
for (int i=0;i<e1.length;i++)
if (!e1[i].equals(e2[i])) {
//System.out.println("Exception " + e1[i] + " doesn't match " + e2[i]);
return false;
}
// Even the repeatings match, so we can return true
return true;
}
public void createBlocks(Date start,Date end,AppointmentBlockArray blocks) {
createBlocks(start,end, blocks, true);
}
public void createBlocks(Date start,Date end,AppointmentBlockArray blocks, boolean excludeExceptions) {
Assert.notNull(blocks);
Assert.notNull(start,"You must set a startDate");
Assert.notNull(end, "You must set an endDate");
processBlocks(start.getTime(), end.getTime(), blocks, excludeExceptions);
}
/* returns true if there is at least one block in an array. If the passed blocks array is not null it will contain all blocks
* that overlap the start,end period after a call.*/
private boolean processBlocks(long start,long end,AppointmentBlockArray blocks, boolean excludeExceptions) {
boolean checkOnly = (blocks == null);
long c1 = start;
long c2 = end;
long s = this.start.getTime();
long e = this.end.getTime();
// if there is no repeating
if (repeating==null) {
if (s <c2 && e>c1) {
if ( !checkOnly )
blocks.add(s,e,this, false);
return true;
}
return false;
}
DD=DE?BUG: print("s = appointmentstart, e = appointmentend, c1 = intervalstart c2 = intervalend");
DD=DE?BUG: print("s:" + n(s) + " e:" + n(e) + " c2:" + n(c2) + " c1:" + n(c1));
if (s <c2 && e>c1 && (!repeating.isException(s) || !excludeExceptions)) {
if (checkOnly) {
return true;
} else {
blocks.add(s,e,this, repeating.isException(s));
}
}
long l = repeating.getIntervalLength( s );
//System.out.println( "l in days " + l / DateTools.MILLISECONDS_PER_DAY );
Assert.isTrue(l>0);
long timeFromStart = l ;
if ( repeating.isFixedIntervalLength())
{
timeFromStart = Math.max(l,((c1-e) / l)* l);
}
int maxNumber = repeating.getNumber();
long maxEnding = Long.MAX_VALUE;
if ( maxNumber >= 0)
{
maxEnding = repeating.getEnd().getTime();
}
DD=DE?BUG: print("l = repeatingInterval (in minutes), x = stepcount");
DD=DE?BUG: print("Maxend " + f( maxEnding));
long currentPos = s + timeFromStart;
DD=DE?BUG: print( " currentPos:" + n(currentPos) + " c2-s:" + n(c2-s) + " c1-e:" + n(c1-e));
long blockLength = Math.max(0, e - s);
while (currentPos <= c2 && (maxNumber<0 || currentPos<=maxEnding)) {
DD=DE?BUG: print(" current pos:" + f(currentPos));
if (( currentPos + blockLength > c1) && ( currentPos < c2)) {
boolean isException =repeating.isException( currentPos );
if ((!isException || !excludeExceptions)) {
if ( checkOnly ) {
return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -