/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package clips.delegate.shedule.individual;
import TimeTable.DayOfWeek;
import beans.shedule.individual.SheduleIndividualBean;
import beans.shedule.individual.SheduleIndividualBeanRemote;
import cli_fmw.delegate.DelegateStandart;
import cli_fmw.delegate.cache.ExtraDataManager;
import cli_fmw.main.ClipsException;
import cli_fmw.delegate.cache.CacheRestorable;
import cli_fmw.delegate.lists.DataChunkList;
import cli_fmw.utils.IteratorEditable;
import cli_fmw.utils.SelectorEditable;
import clips.delegate.directory.ro.DirectoryCollaboratorItem;
import beans.shedule.individual.SheduleIndividualWorkDetails;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
/**
* делегат, хранит данные о запланированных делах сотрудника на заданную неделю.
* Запланированные дела сотрудника они хранятся в делегате SheduleRealLocal
* Недели в данном делегате задаются как индекс недели с 1 недели 2007 года
* Итерируются работы по заданному дню.
* Делегат является уникальным в адресном пространстве клиента.
*
* @author Axe Ilshat
*/
public class SheduleIndividualLocal
extends DelegateStandart<SheduleIndividualBeanRemote> {
private DirectoryCollaboratorItem collaborator;
private HashMap<Integer, WorkList> workList = new HashMap<Integer, WorkList>();
private CacheRestorable<Integer> weekCount = new CacheRestorable<Integer>();
private ExtraDataManager ecm;
/**
* Конструктор
* @param coll
* @throws ClipsException
*/
public SheduleIndividualLocal(DirectoryCollaboratorItem coll) throws ClipsException {
super(SheduleIndividualBean.class.getSimpleName());
collaborator = coll;
initBean();
ecm = new ExtraDataManager(getBean(), this, false);
try {
weekCount.set(bean().getCollaboratorWeekPeriod(coll.getID()));
} catch (Exception ex) {
clearBean();
throw new ClipsException("Не удалось инициализировать сервис расписания", ex);
}
}
public boolean canModifyPlan() throws ClipsException {
return getBeanRights().isCommandAccessible(SheduleIndividualBean.COMMAND_MODIFY_PLAN);
}
public boolean canModifyReal() throws ClipsException {
return getBeanRights().isCommandAccessible(SheduleIndividualBean.COMMAND_MODIFY_REAL);
}
public DirectoryCollaboratorItem getCollaborator() {
return collaborator;
}
/**
* Сохраняет изменения, произошедшие в делегате
* @throws ClipsException
*/
@Override
public void save1() throws ClipsException {
if(weekCount.isDirty()) {
try {
bean().setCollaboratorWeekPeriod(collaborator.getID(), weekCount.get());
weekCount.commit();
} catch (Exception ex) {
clearBean();
throw new ClipsException("Не удалось сохранить расписание", ex);
}
}
Iterator<Integer> i = workList.keySet().iterator();
while(i.hasNext()) {
Integer weekIndex = i.next();
if(weekIndex > weekCount.get() && weekIndex <= 51) {
System.out.println("Removing week, weekindex:" + weekIndex + " weekcount " + weekCount.get());
i.remove();
} else {
System.out.println("Saving week, weekindex:" + weekIndex);
workList.get(weekIndex).save();
}
}
}
/**
* Сбрасывает изменения, произошедшие в делегате
*/
@Override
public void restore() {
weekCount.restore();
Iterator<WorkList> i = workList.values().iterator();
while(i.hasNext()) {
i.next().restore();
System.out.println("WorkList restored");
}
}
/**
* Проверяет, нуждается ли делегат в сохранении состояния
* @return boolean
*/
@Override
public boolean isDirty() {
if(weekCount.isDirty()) {
return true;
}
Iterator<WorkList> i = workList.values().iterator();
while(i.hasNext()) {
if(i.next().isDirty()) {
return true;
}
}
return false;
}
/**
* Возвращает количество недель в индивидуальном плане
* Загружает, если не загружено, количество недель в индивидуальном плане сотрудника
* @return количество недель в индивидуальном плане (1-4)
* @throws ClipsException
*/
public int getWeekCount() throws ClipsException {
return (weekCount.get() % 4) + 1;
}
/**
* Записывает, но не сохраняет, количество недель в индивидуальном расписании
* @param weekCount количество недель в индивидуальном плане (1-4)
*/
public void setWeekCount(int weekCount) {
if(weekCount < 1) {
throw new IllegalArgumentException("Week count period = 0");
}
this.weekCount.set( (weekCount-1) % 4 );
fireContentStateEvent();
}
/**
* Перезаписывает ВСЕ работы из заданого дня недели в другой день недели.
* Старые работы в перезаписываемом дне удаляются.
* @param srcWeekIndex индекс недели с 1 недели 2007 года, откуда перемещать
* @param srcDayOfWeek день недели 0-6 (monday == 0), откуда перемещать
* @param dstWeekIndex индекс недели с 1 недели 2007 года, куда перемещать
* @param dstDayOfWeek день недели 0-6 (monday == 0), куда перемещать
* @return
* @throws ClipsException
*/
public int copyWorksWithOverwrite(WeekIndex srcWeekIndex, DayOfWeek srcDayOfWeek,
WeekIndex dstWeekIndex, DayOfWeek dstDayOfWeek) throws ClipsException {
deleteWorks(dstWeekIndex, dstDayOfWeek);
return copyWorks(srcWeekIndex, srcDayOfWeek, dstWeekIndex, dstDayOfWeek);
}
/**
* Удаляет работы в заданном дне
* @param weekIndex индекс недели с 1 недели 2007 года
* @param dayOfWeek день недели 0-6 (monday == 0)
* @return
* @throws ClipsException
*/
public int deleteWorks(WeekIndex weekIndex, DayOfWeek dayOfWeek) throws ClipsException {
IteratorEditable<SheduleIndividualData> is = daySelector(weekIndex, dayOfWeek);
int count = 0;
while(is.hasNext()) {
is.next();
is.remove();
System.out.println("Work deleted");
count++;
}
if(count > 0) {
fireContentStateEvent();
}
return count;
}
/**
* Копирует ВСЕ работы из заданого дня недели в другой день недели.
* @param srcWeekIndex индекс недели с 1 недели 2007 года, откуда копировать
* @param srcDayOfWeek день недели 0-6 (monday == 0), откуда копировать
* @param dstWeekIndex индекс недели с 1 недели 2007 года, куда копировать
* @param dstDayOfWeek день недели 0-6 (monday == 0), куда копировать
* @return
* @throws ClipsException
*/
public int copyWorks(WeekIndex srcWeekIndex, DayOfWeek srcDayOfWeek,
WeekIndex dstWeekIndex, DayOfWeek dstDayOfWeek) throws ClipsException {
if(srcWeekIndex == dstWeekIndex
&& srcDayOfWeek == dstDayOfWeek) {
return 0;
}
//preload destination
IteratorEditable<SheduleIndividualData> did = daySelector(dstWeekIndex, dstDayOfWeek);
Iterator<SheduleIndividualData> dis = daySelector(srcWeekIndex, srcDayOfWeek);
int count = 0;
while(dis.hasNext()) {
SheduleIndividualData work = dis.next();
Calendar gc = GregorianCalendar.getInstance();
gc.setTime(work.getBegin());
GregorianCalendar newBeginCal = dstWeekIndex.getBegin();
newBeginCal.add(Calendar.DAY_OF_MONTH, dstDayOfWeek.getEuropean());
newBeginCal.add(Calendar.HOUR_OF_DAY, gc.get(Calendar.HOUR_OF_DAY));
newBeginCal.add(Calendar.MINUTE, gc.get(Calendar.MINUTE));
SheduleIndividualData newWork = new SheduleIndividualData(collaborator);
newWork.setBegin(newBeginCal.getTime());
newWork.setWorkDuration(work.getWorkDuration());
newWork.setDefaultServiceDuration(work.getDefaultServiceDuration());
newWork.setType(work.getType());
newWork.setCabinet(work.getCabinet());
did.append(newWork);
count++;
}
fireContentStateEvent();
return count;
}
/**
* Возвращает селектор для перебора работ заданной недели
* @param weekIndex индекс недели с 1 недели 2007 года
* @return селектор работ для заданной недели
* @throws ClipsException
*/
public SelectorEditable<SheduleIndividualData> weekSelector(WeekIndex weekIndex)
throws ClipsException {
return get(weekIndex).selector();
}
/**
* Возвращает итератор работ для заданного индекса недели
* @return итератор праздничных дней
* @throws cli_fmw.delegate.exception.ClipsException
*/
private WorkList get(WeekIndex weekIndex) throws ClipsException {
WorkList dl = workList.get(weekIndex.getIndex());
if(dl == null) {
dl = new WorkList(ecm, weekIndex);
workList.put(weekIndex.getIndex(), dl);
}
return dl;
}
class WorkList extends DataChunkList<SheduleIndividualData> {
private WeekIndex weekIndex;
public WorkList(ExtraDataManager contaner, WeekIndex weekIndex) {
super(contaner);
this.weekIndex = weekIndex;
}
@Override
protected void deleteDB(SheduleIndividualData data) throws Exception {
bean().removeWork(data.getId());
}
@Override
protected int saveDB(SheduleIndividualData data) throws Exception {
return bean().setWork(data.getDetails());
}
@Override
protected void loadDB() throws Exception {
List<SheduleIndividualWorkDetails> list =
bean().getWorkList(collaborator.getID(),
weekIndex.getBegin().getTime(), weekIndex.getEnd().getTime());
for(SheduleIndividualWorkDetails d: list) {
initByDetails(new SheduleIndividualData(d));
}
}
}
/**
* Возвращает селектор для перебора работ заданного дня
* @param weekIndex
* @param dayOfWeek
* @return
* @throws ClipsException
*/
public IteratorEditable<SheduleIndividualData> daySelector(WeekIndex weekIndex, DayOfWeek dayOfWeek)
throws ClipsException {
return new DaySelector(weekIndex, dayOfWeek);
}
/**
* HELPER CLASS
*/
class DaySelector implements IteratorEditable<SheduleIndividualData> {
private long begin;
private long end;
private int currentPosition = -1;
private int nextPosIndex;
SelectorEditable<SheduleIndividualData> items;
public DaySelector(WeekIndex weekIndex, DayOfWeek dayOfWeek) throws ClipsException {
items = get(weekIndex).selector();
GregorianCalendar gc = weekIndex.getBegin();
gc.add(Calendar.DAY_OF_YEAR, dayOfWeek.getEuropean());
begin = gc.getTimeInMillis();
gc.add(Calendar.DAY_OF_YEAR, 1);
end = gc.getTimeInMillis();
nextPosIndex = getNextPosition();
}
private int getNextPosition() {
for(int i=currentPosition+1; i<items.size(); i++) {
SheduleIndividualData item = items.get(i);
if(!isIncluded(item)) {
continue;
}
return i;
}
return -1;
}
private boolean isIncluded(SheduleIndividualData item) {
long jbeg = item.getBegin().getTime();
if(jbeg >= end
|| jbeg + item.getWorkDuration()*60*1000 <= begin) {
return false;
}
return true;
}
@Override
public boolean hasNext() {
if(nextPosIndex == -1) {
return false;
}
return true;
}
@Override
public SheduleIndividualData next() {
currentPosition = nextPosIndex;
SheduleIndividualData data = items.get(currentPosition);
nextPosIndex = getNextPosition();
return data;
}
@Override
public void remove() {
items.remove(currentPosition);
if(currentPosition>=0) {
currentPosition--;
}
if(nextPosIndex >=0) {
nextPosIndex--;
}
}
@Override
public void append(SheduleIndividualData item) {
if(!isIncluded(item)) {
throw new IllegalArgumentException("Данная работа не может быть включена в указанный день");
}
items.append(item);
}
}
}