/*
Copyright 2014 BarD Software s.r.o
This file is part of GanttProject, an opensource project management tool.
GanttProject 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.
GanttProject 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 GanttProject. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.ganttproject.calendar;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.Platform;
import org.xml.sax.Attributes;
import com.beust.jcommander.internal.Lists;
import com.google.common.collect.ImmutableList;
import net.sourceforge.ganttproject.GPLogger;
import net.sourceforge.ganttproject.io.XmlParser;
import net.sourceforge.ganttproject.parser.AbstractTagHandler;
import net.sourceforge.ganttproject.parser.HolidayTagHandler;
import net.sourceforge.ganttproject.parser.ParsingListener;
import net.sourceforge.ganttproject.parser.TagHandler;
import net.sourceforge.ganttproject.util.FileUtil;
import biz.ganttproject.core.calendar.GPCalendar;
import biz.ganttproject.core.calendar.GPCalendarCalc;
import biz.ganttproject.core.calendar.WeekendCalendarImpl;
/**
* Reads calendars in XML format from GanttProject's installation directory.
*
* @author dbarashev (Dmitry Barashev)
*/
public class GPCalendarProvider {
private static class CalendarTagHandler extends AbstractTagHandler {
private final GPCalendarCalc myCalendar;
private final HolidayTagHandler myHolidayHandler;
CalendarTagHandler(GPCalendarCalc calendar, HolidayTagHandler holidayHandler) {
super("calendar");
myCalendar = calendar;
myHolidayHandler = holidayHandler;
}
@Override
protected boolean onStartElement(Attributes attrs) {
myCalendar.setName(attrs.getValue("name"));
myCalendar.setID(attrs.getValue("id"));
myCalendar.setBaseCalendarID(attrs.getValue("base-id"));
return true;
}
@Override
protected void onEndElement() {
myHolidayHandler.onCalendarLoaded();
}
}
private static GPCalendarProvider ourInstance;
private static GPCalendar readCalendar(File resource) {
WeekendCalendarImpl calendar = new WeekendCalendarImpl();
HolidayTagHandler holidayHandler = new HolidayTagHandler(calendar);
CalendarTagHandler calendarHandler = new CalendarTagHandler(calendar, holidayHandler);
XmlParser parser = new XmlParser(
ImmutableList.<TagHandler>of(calendarHandler, holidayHandler),
ImmutableList.<ParsingListener>of());
try {
parser.parse(new BufferedInputStream(new FileInputStream(resource)));
return calendar;
} catch (IOException e) {
GPLogger.logToLogger(e);
return null;
}
}
private static List<GPCalendar> readCalendars() {
try {
URL resolved = Platform.resolve(GPCalendarProvider.class.getResource("/calendar"));
if (resolved == null) {
return Collections.emptyList();
}
File dir = new File(resolved.getFile());
if (dir.exists() && dir.isDirectory() && dir.canRead()) {
List<GPCalendar> calendars = Lists.newArrayList();
for (File f : dir.listFiles()) {
if ("calendar".equalsIgnoreCase(FileUtil.getExtension(f))) {
try {
GPCalendar calendar = readCalendar(f);
if (calendar != null) {
calendars.add(calendar);
}
} catch (Throwable e) {
GPLogger.logToLogger(String.format("Failure when reading calendar file %s", f.getAbsolutePath()));
GPLogger.logToLogger(e);
}
}
}
return calendars;
}
} catch (IOException e) {
GPLogger.logToLogger(e);
}
return Collections.emptyList();
}
public static synchronized GPCalendarProvider getInstance() {
if (ourInstance == null) {
List<GPCalendar> calendars = readCalendars();
Collections.sort(calendars, new Comparator<GPCalendar>() {
public int compare(GPCalendar o1, GPCalendar o2) {
return o1.getName().compareTo(o2.getName());
}
});
ourInstance = new GPCalendarProvider(calendars);
}
return ourInstance;
}
private final List<GPCalendar> myCalendars;
private GPCalendarProvider(List<GPCalendar> calendars) {
myCalendars = calendars;
}
public List<GPCalendar> getCalendars() {
return myCalendars;
}
}