/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cli_fmw.report;
import cli_fmw.report.SegmentedTableReporter;
import cli_fmw.report.implemenatation.SegmentedTableBuilder;
import cli_fmw.report.implemenatation.JasperCombinedReport;
import cli_fmw.report.implemenatation.JasperFormReporter;
import cli_fmw.report.implemenatation.ReportTestForm;
import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import javax.swing.table.TableModel;
import framework.utils.Converter;
/**
* Фабрика создающия классы для генерации отчетов, и возвравращает их интерфейсы.
* Обеспечивает следующие концепции:
* 1) Простота добавления распечатки множества разных форм.
* 2) Возможность изменить распечатываемый отчет без перекомпиляции проекта.
* 3) Автоматический, и стандартизованй поиск нужного файла отчета, по его имени.
* 4) Возможность распечатать несколько отчетов, по одной форме, и один отчет, из нескольких форм.
*
* Как все это работает.
*
* createFormReporter(Class formClass, int reportType) ищет в конфиги фабрики (ReporterFactory.properties)
* class.path[.reportType]=val
* Где class.path полное имя класса, reportType тип отчета (в случае если тип 0 или 1 он может опускатся)
* val - заначения свойства, если число то файл отчета будет искадся по и
* мени класса + число. Если текстовая строка, то будет поизводится
* поиск файла с таким именем. Если было переданно число ноль, и отчет
* не был найден то будет произведена попытка его генерации по переданным данным.
*
* има класса формы - форма для которой планируется распечатать отчет
* reportType - тип отчета, нужен, если одна форма распечатывает несколько отчетов
*
* например:
* clips.doctor.prescription.PanelPrescription.2=3
*
* означает что для формы PanelPrescription и типа отчета два, будут выведен отчет номер три.
*
* Если форма была найдена в конфиге, то создетется объект построителя,
* которому передается класс формы, и значение которое было в конфиге
* Примечание: в далнейшем в качестве типа отчета передается именно значение из конфига.
* Значение переданное в createFormReporter используется только для поиска строчки в конфиге.
*
* Объект построителяищет ищет фай по следующим путям. Например для PanelPrescription
* будет приизведен поиск файла отчета в следуюищх местах (в седующих):
*
* Файл в базе данных: clips.doctor.prescription.PanelPrescription.3.jasper
* Файл в ресурсах фомы PanelPrescription.3.jasper
* Файл в ресурсах фомы clips.doctor.prescription.PanelPrescription.3.jasper
* Файл в общей папке отчетов clips.doctor.prescription.PanelPrescription.3.jasper
*
* Прм. Для номера файла 1 и 0, цифра из имени файла может опускатся.
* Прм. В текуще реализации ситемы отчетов, отчеты могут лежать
* в файлах двух типов - ".jasper" и ".jrxml"
*
* Для PanelEMC (Срочка в базе выглядит как)
* clips.doctor.PanelEMC=clientEMCInfo
* буде произведен поиск следующих файлов:
* Файл в базе данных clientEMCInfo.jasper
* Файл в ресурсах фомы clientEMCInfo.jasper
* Файл в общей папке отчетов clientEMCInfo.jasper
*
* @author finder
*/
final public class ReporterFactory{
public static final int DEFAULT = 0;
public static final int BASE_REPORT = 1;
public static final int TEST_FORM = 2000000000;
private static ReporterFactory factory = null;
private Properties factoryProperties;
/**
* Преобразут переданный обект в строку, в соотведствии с внутренними
* особенностями клипса.
* @param data
* @return
*/
public static String convertDataToString(Object data){
if (data == null) {
return "";
}
else if (data instanceof Date) {
return Converter.dateToString((Date) data);
}
else if (data instanceof Boolean) {
if ((Boolean)data) {
return "да";
}
else {
return "нет";
}
}
else if (data instanceof Color) {
return "";
}
else {
return data.toString();
}
}
/**
* По классу формы или панели создает отчет
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @return
*/
public static FormReportCreator createFormReporter(Class formClass){
return createFormReporter(formClass, BASE_REPORT);
}
/**
*
* @param formClass
* @param reportType
* @return
*/
public static FormReportCreator createFormReporter(Class formClass, int reportType){
formClass = getCreatableClass(formClass, reportType);
if (formClass != null) {
return getFactory().createFormReporterImp(formClass, reportType);
}
else {
throw new RuntimeException("Не удалось создать отчет");
}
}
/**
*
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return
*/
public static CombinedReportCreator createCombinedReporter(Class formClass, int reportType){
formClass = getCreatableClass(formClass, reportType);
if (formClass != null) {
return getFactory().createCombinedReporterImp(formClass, reportType);
}
else {
throw new RuntimeException("Не удалось создать комбинированный отчет");
}
}
@Deprecated
public static void createGeneratedReport(String title, TableReportOptions ops,
Collection<Entry<String, Object>> preFields,
Collection<Entry<String, Object>> postFields,
TableModel model) {
createGeneratedReport(title, ops, preFields, postFields, model, ReporterFactory.class);
}
public static void createGeneratedReport(String title, TableReportOptions ops,
Collection<Entry<String, Object>> preFields,
Collection<Entry<String, Object>> postFields,
TableModel model, Class clazz) {
FormReportCreator creater = createFormReporter(clazz);
creater.createReport(title, ops, preFields, postFields, model);
creater.finish();
}
/**
* Создает интерфейс для печати анализов
* @param formClass - класс панели из которой был вызван
* @return интерфейс для печати анализов
*/
public static SegmentedTableReporter createAnalyseReporter(Class formClass){
return new SegmentedTableBuilder();
}
public static CombinedReportCreator getFinalCreator(){
return new CombinedReportCreator() {
@Override
public void setUpReport() {
}
@Override
public void setUpReport(Map<String, Object> extraFields) {
}
@Override
public void setUpReport(String title, CombinedReportOptions options, Collection<Entry<String, Object>> topExtraFields) {
}
@Override
public void setUpReport(String title, CombinedReportOptions options, Collection<Entry<String, Object>> topExtraFields, Collection<Entry<String, Object>> bottomExtraFields) {
}
@Override
public FormReportCreator createFormReporter(Class clazz, int type) {
return ReporterFactory.createFormReporter(clazz, type);
}
@Override
public CombinedReportCreator createCombinedReporter(Class clazz, int type) {
return ReporterFactory.createCombinedReporter(clazz, type);
}
@Override
public SegmentedTableReporter createAnalyseReporter(Class clazz) {
return ReporterFactory.createAnalyseReporter(clazz);
}
@Override
public void finish() {
}
};
}
/**
* Возвращяет указетель на уже созданную фабрику.
* @return
*/
private static ReporterFactory getFactory(){
if (factory == null) {
factory = new ReporterFactory();
}
return factory;
}
private ReporterFactory(){
InputStream is = ReporterFactory.class.getResourceAsStream(ReporterFactory.class.getSimpleName() + ".properties");
factoryProperties = new Properties();
if (is != null) {
try {
factoryProperties.load(is);
} catch (IOException ex) {
ex.printStackTrace();
factoryProperties = new Properties();
}
}
}
/**
* Ищет класс предка переданного класса, для которого заданны параметры, в свойства Factary
* Если не находит возвращаеь переданный класс
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return - первый класс предок, имя которого найдено в конфиг файле.
*/
private static Class getCreatableClass(Class formClass, int reportType){
if (formClass == null) {
throw new IllegalArgumentException("formClass == null");
}
while (formClass != null) {
if (getFactory().canCreateFormReporterImp(formClass, reportType)) {
break;
}
formClass = formClass.getSuperclass();
}
return formClass;
}
/**
* Возвращяет свойтво для конкретной формы из файла конфигурации Factory,
* ищет его по id типа и классу формы.
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return - строка содержащая текст свойства, или null
*/
String getReportPropeties(Class formClass, int reportType){
String name = formClass.getName();
String prop = factoryProperties.getProperty(name + "." + reportType);
if (prop != null) {
return prop.trim();
}
if (reportType == BASE_REPORT){
prop = factoryProperties.getProperty(name);
if (prop != null) {
return prop.trim();
}
}
return null;
}
/**
* Возвращает номер не именовоного отчета в конфиг файле, ищет его по id
* и полному имени класса формы, для которой печатается отчет.
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return номер отчета, -1 если не удалось получить
*/
private int getReportID(Class formClass, int reportType){
int reportid;
String type = getReportPropeties(formClass, reportType);
if (type != null) {
try{
reportid = Integer.parseInt(type);
return reportid;
}
catch (NumberFormatException ex){
ex.printStackTrace();
// дропается
}
}
return ReporterFactoryBaseProperties.getID(formClass, reportType);
}
/**
* Возвращяет имя, именовоного отчета, из конфиг файла фактори.
* Если пороизошла ошибка возваращяется null
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return - имя отчета, или null
*/
String getReportName(Class formClass, int reportType){
String reportName = getReportPropeties(formClass, reportType);
if (reportName != null && reportName.length() > 1) {
return reportName;
}
return ReporterFactoryBaseProperties.getName(formClass, reportType);
}
/**
* внутренняя имплементация которая проверяет, можено ли создать класс jnxtna
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return - истину если создание отчета возможено
*/
private boolean canCreateFormReporterImp(Class formClass, int reportType){
if (getReportPropeties(formClass, reportType) != null) {
return true;
}
return ReporterFactoryBaseProperties.exist(formClass, reportType);
}
/**
*
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return - интерфейс класса для создания отчетов клиетской стороны.
*/
private FormReportCreator createFormReporterImp(Class formClass, int reportType){
int id = getReportID(formClass, reportType);
if (id == TEST_FORM) {
return new ReportTestForm();
}
String name = getReportName(formClass, reportType);
if (id >= BASE_REPORT && id < TEST_FORM){
return new JasperFormReporter(formClass, id - BASE_REPORT + 1, name);
}
else if (name != null){
return new JasperFormReporter(formClass, -1, name);
}
if (id == 0){
return new JasperFormReporter(formClass, 0, null);
}
else {
return null;
}
}
/**
* Создает класс отвечающий за создание комбинированых отчетов
* (отчетов содержащик, в себе несколько подотчетов).
* @param formClass - класс формы или панели (полученный функцией getClass)
* для которого надо создать отчет.
* @param reportType - тип отчета который надо создать, например TEST_FORM,
* нужно для форм/панелей который могут создавать
* несколько типов отчетов
* @return - интерфейс класса которы создает корневой отчет.
*/
private CombinedReportCreator createCombinedReporterImp(Class formClass, int reportType) {
int id = getReportID(formClass, reportType);
String name = getReportName(formClass, reportType);
if (id >= BASE_REPORT && id < TEST_FORM){
return new JasperCombinedReport(formClass, id - BASE_REPORT + 1, name);
}
else if (name != null){
return new JasperCombinedReport(formClass, -1, name);
}
if (id == 0){
return new JasperCombinedReport(formClass, 0, null);
}
else {
return null;
}
}
}