/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cli_fmw.delegate.report;
import cli_fmw.delegate.AuditListener;
import cli_fmw.delegate.DelegateLine2;
import cli_fmw.delegate.cache.ExtraDataManager;
import cli_fmw.delegate.lists.DataChunkMapList;
import cli_fmw.utils.SelectorEditable;
import java.io.InputStream;
import framework.utils.Converter;
import framework.beans.report.FileDetails;
import framework.beans.report.ReportDetail;
import cli_fmw.main.ClipsException;
import cli_fmw.utils.MessageBox;
import framework.beans.report.ReportDefinition;
import framework.beans.HardCodedIDs;
import framework.beans.report.ReportBeanAbstract;
import framework.beans.report.ReportBeanRemote;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.jasperreports.JRCostumFileSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.util.JRLoader;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
/**
*
* @author finder
*/
public class ReportLocal extends DelegateLine2<ReportBeanRemote, ReportDetail> implements JRCostumFileSource {
private FileMapList filesList = new FileMapList(getEDM());
private ArrayList<ReportParam> params;
private ReportLocal globalReportFiles;
/**
* создает пустой отчет, перед сохранием нужно как миниум установить основной файл отчета
*/
public ReportLocal(AuditListener al){
super(al);
}
/**
* Подгружает отчет из базы по его id, загрузака ленивая
* @param initializedID - id отчета
*/
public ReportLocal(int initializedID, AuditListener al) {
super(initializedID, al);
}
public ReportLocal(ReportDetail details, AuditListener al) {
super(details, al);
}
@Override
protected ReportDetail getNewDetails() {
return new ReportDetail();
}
/**
* Возвращает дружественное к пользователю имя отчета (настоящие - это имя основного файла)
* @return
* @throws ClipsException - при ошибке базы
*/
public String getName() throws ClipsException{
return getDetails().reportName;
}
/**
* Проверяет является ли этот отчет специальным отчетом,
* специальные отчеты нельзя удалить, их нельзя вывести черех стандартный GUI
* @return
*/
public boolean isSpecialReport() {
return !HardCodedIDs.canRemove(ReportDefinition.class, getID());
}
/**
* устанавливает дружественное к пользователю имя отчета
* @param name
* @throws ClipsException
*/
public void setName(String name) throws ClipsException{
getDetails().reportName = name;
fireContentStateEvent();
}
/**
* Возвращает пользоватльски коментарри к отчету
* @return
* @throws ClipsException - при ошибке базы
*/
public String getComment() throws ClipsException{
return getDetails().reportComment;
}
/**
* Устанавливает пользоватльски коментарри к отчету
* @param comment
* @throws ClipsException - при ошибке базы
*/
public void setComment(String comment) throws ClipsException{
getDetails().reportComment = comment;
fireContentStateEvent();
}
/**
* Добавляет в отчет файл, загружая его с диска
* @throws generic.ClipsException - при ошибке чтения файла.
* @throws net.sf.jasperreports.engine.JRException - при ошибке компиляции отчета
*/
/**
*
* @param fileName
* @throws ClipsException
* @throws net.sf.jasperreports.engine.JRException
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public void addFile(File fileName) throws ClipsException, JRException, FileNotFoundException, IOException{
FileLocal file = loadFile(fileName);
if (file != null) {
addFile(file);
}
}
/**
* Добавляет в отчет файл
* @param file - файл для добавления
* @throws ClipsException
* @throws JRException
*/
public void addFile(FileLocal file) throws ClipsException, JRException{
FileLocal exensFille = filesList.get(file.getFileName());
if (exensFille != null) {
if (exensFille.getFileName().equals(getDetails().mainFile) && file.getFileTypeID() != FileDetails.TYPE_JASPER_REPORT) {
throw new ClipsException("Попытка заменить основной файл отчета на файл не являющийся отчетом");
}
exensFille.setFileData(file.getFileData());
//file = exensFille;
if (exensFille.getFileName().equals(getDetails().mainFile)){
setMainFile(exensFille);
}
}
else{
file.setReport(this);
filesList.selector().append(file);
}
fireContentStateEvent();
}
/**
* Удаляет файл из отчета.
* @param file - файл для удаления
* @throws ClipsException
*/
public void removeFile(FileLocal file) throws ClipsException{
getFilesList().remove(file);
}
public FileLocal getFile(String fileName) throws ClipsException{
FileLocal presFile = filesList.get(fileName);
return presFile;
}
@Override
public InputStream getInputStream(String fileName) {
try {
FileLocal file;
if (fileName == null) {
file = getMainFile();
}
else {
file = getFile(fileName);
}
if (file != null) {
return new ByteArrayInputStream(file.getFileCompiledData());
}
if (fileName != null) {
if (globalReportFiles == null) {
globalReportFiles = new ReportLocal(ReportDefinition.REPORT_GLOBAL_REPORTS, getAuditListener());
}
file = globalReportFiles.getFile(fileName);
if (file != null) {
return new ByteArrayInputStream(file.getFileCompiledData());
}
}
} catch (ClipsException ex) {
MessageBox.asyncShowExceptionOnly(ex, true);
}
return null;
}
/**
* Возвращает список всех добавленных файлов, включая основной файл
* @return
* @throws ClipsException
*/
public ArrayList<FileLocal> getFiles() throws ClipsException{
SelectorEditable<FileLocal> iter = getFilesList();
ArrayList<FileLocal> list = new ArrayList<FileLocal>(iter.size());
for (int i = 0; i < iter.size(); i++) {
list.add(iter.get(i));
}
return list;
}
public ArrayList<ReportParam> getParams() throws ClipsException {
if (params == null) {
readParamFromXML();
if (params == null) {
params = genParamsFromReport(getMainFile());
}
}
return new ArrayList<ReportParam>(params);
}
/**
* Загружает файл, и устанавливает его основнмым файлом отчета.
* @param fileName - имя и путь файла
*
* @throws ClipsException - при ошибке чтения файла,
* при попытке установить основным файлом не файл отчета,
* и при ошибке в отчете
* @throws net.sf.jasperreports.engine.JRException - при ошибке компиляции отчета
* @throws FileNotFoundException
* @throws IOException
*/
public void setMainFile(File fileName) throws ClipsException, JRException, FileNotFoundException, IOException{
FileLocal file = loadFile(fileName);
if (file != null) {
setMainFile(file);
}
else {
throw new ClipsException("Ошибка добавления основного файла");
}
}
/**
* устанавливает файл основным для отчета
* @param file
* @throws ClipsException
* @throws JRException - при ошибке компиляции отчета
*/
public void setMainFile(FileLocal file) throws ClipsException, JRException{
if (file == null){
getDetails().mainFile = null;
return;
}
if (file.getFileTypeID() != FileDetails.TYPE_JASPER_REPORT) {
throw new ClipsException("Основной файл отчета должен быть отчетом");
}
FileLocal presFile = filesList.get(file.getFileName());
if (presFile != file) {
addFile(file);
}
params = genParamsFromReport(file);
writeParamToXML();
getDetails().mainFile = file.getFileName();
if (getDetails().reportName == null) {
getDetails().reportName = file.getFileName();
}
fireContentStateEvent();
}
/**
* Возвращает основной файл
* @return
* @throws ClipsException
*/
public FileLocal getMainFile() throws ClipsException {
FileLocal presFile = filesList.get(getDetails().mainFile);
return presFile;
}
public JasperPrint getClientReport(Map<String, Object> params) throws ClipsException, JRException{
if (isDirty()) {
throw new ClipsException("Отчет должен быть сохранен, проед выполением");
}
InputStream stream = getInputStream(null);
if (stream != null){
try{
JasperReport jasperReport = (JasperReport)JRLoader.loadObject(stream);
HashMap<String, Object> map = new HashMap<String, Object>(params);
map.putAll(getDefaultParameters());
return JasperFillManager.fillReport(jasperReport, map);
}
finally{
try {
stream.close();
} catch (IOException ex) {
throw new ClipsException("Неизвестная ошибка при закрытии потока", ex);
}
}
}
return null;
}
/**
* Выполняет отчет на сервере, и возвращает его результат, отчет должен быть
* сохранен на сервере.
* @param params
* @return
* @throws ClipsException - отчет не сохранен, ошибка сервера
* @throws net.sf.jasperreports.engine.JRException - ошбка при постраении отчета
*/
@SuppressWarnings("unchecked")
public JasperPrint getReport(Map<String, Object> params) throws ClipsException, JRException{
if (isDirty()) {
throw new ClipsException("Отчет должен быть сохранен, проед выполением");
}
try{
return getBean().getReport(params);
}
catch (JRException ex){
throw ex;
}
catch (Exception ex){
clearBean();
throw new ClipsException("Ошибка при получения отчета", ex);
}
}
/**
* Осуществляет считыване с сервера данных файла.
* @param fileID
* @return
* @throws ClipsException
*/
protected FileDetails getFileData(int fileID) throws ClipsException{
try{
return getBean().getFileData(fileID);
}
catch (Exception ex){
clearBean();
throw new ClipsException("Не прав доступа для получения файлов", ex);
}
}
/**
* имя бина на сервере
* @return
*/
@Override
protected String getBeanName() {
return ReportBeanAbstract.class.getSimpleName();
}
/**
* Пустышка для вызова из FileLocal
*/
void fileStateChange(){
fireContentStateEvent();
}
/**
* Считывает файл в бьоект FileLocal для внутреннего использования
* @param filename
* @return
* @throws generic.ClipsException - ошибка чтения
* @throws net.sf.jasperreports.engine.JRException - ошибка компиляции отчета
*/
private FileLocal loadFile(File filename) throws ClipsException, JRException, FileNotFoundException, IOException{
return new FileLocal(filename, this);
}
/**
* Считывает параметры необходимые отчету, и заполняет возвращаесмый массив
* @param reportFile
* @return - массив с параметрами, при ошибке пустой массив
* @throws generic.ClipsException
*/
private ArrayList<ReportParam> genParamsFromReport(FileLocal reportFile) throws ClipsException{
ArrayList<ReportParam> target = new ArrayList<ReportParam>();
if (reportFile == null || reportFile.getFileTypeID() != FileDetails.TYPE_JASPER_REPORT) {
return target;
}
ByteArrayInputStream is = new ByteArrayInputStream(reportFile.getFileCompiledData());
try{
JasperReport rep = (JasperReport)JRLoader.loadObject(is);
JRParameter[] param = rep.getParameters();
for (JRParameter parameter : param) {
if (!parameter.isSystemDefined()){
target.add(new ReportParam(this,
(parameter.getDescription() == null? parameter.getName(): parameter.getDescription()),
parameter.getName(), parameter.getValueClassName()));
}
}
}
catch (Exception ex){
target.clear();
}
return target;
}
/**
* Считывае параметры основного отчета из XML сохраненной в детали,
* если xml содержыт ошибки, то пытается считать параметры из основного отчета
* @throws generic.ClipsException -
*/
@SuppressWarnings("unchecked")
private void readParamFromXML() throws ClipsException{
try {
params = new ArrayList<ReportParam>();
if (getDetails().reportParms == null || getDetails().reportParms.length() <= 3) {
params = genParamsFromReport(getMainFile());
return;
}
Document xml = Converter.stringToXml(getDetails().reportParms);
Element root = xml.getRootElement();
for (Element el: (List<Element>)root.getChildren("Param")){
String name = el.getChildText("Name");
String rname = el.getChildText("RealName");
String pclass = el.getChildText("Class");
if (name == null || rname == null || pclass == null) {
throw new ClipsException("Ошибка в хмл");
}
params.add(new ReportParam(this, name, rname, pclass));
}
} catch (JDOMException ex) {
ex.printStackTrace();
params = genParamsFromReport(getMainFile());
}
}
/**
* Записывает параметры основного отчета в XML и сограняет строку в делать
* @throws generic.ClipsException
*/
private void writeParamToXML() throws ClipsException{
if (params == null){
if (getDetails().reportParms != null && getDetails().reportParms.length() > 0) {
return;
}
else {
params = genParamsFromReport(getMainFile());
}
}
Document xml = new Document();
Element root = new Element("ReportParams");
xml.setRootElement(root);
for (ReportParam param : params) {
Element el = new Element("Param");
Element tmp;
tmp = new Element("Name");
tmp.setText(param.getUserName());
el.addContent(tmp);
tmp = new Element("RealName");
tmp.setText(param.getRealName());
el.addContent(tmp);
tmp = new Element("Class");
tmp.setText(param.getParamClass());
el.addContent(tmp);
root.addContent(el);
}
getDetails().reportParms = Converter.xmlToString(xml);
}
@Override
public String toString() {
try {
return getName();
} catch (ClipsException ex) {
ex.printStackTrace();
}
return "<Ошибка>";
}
SelectorEditable<FileLocal> getFilesList() throws ClipsException{
return filesList.selector();
}
public Map<String, Object> getDefaultParameters() throws ClipsException{
try {
return getBean().getDefaultParameters();
} catch (Exception ex) {
clearBean();
throw new ClipsException("Не удалось загрузить дефолтовые параметры", ex);
}
}
class FileMapList extends DataChunkMapList<FileLocal, String>{
public FileMapList(ExtraDataManager contaner) {
super(contaner);
}
@Override
protected void deleteDB(FileLocal data) throws Exception {
getBean().removeFile(data.getId());
}
@Override
protected int saveDB(FileLocal data) throws Exception {
return getBean().saveFile(data.getDetails());
}
@Override
protected void loadDB() throws Exception {
for (FileDetails file : getBean().getFiles()) {
initByDetails(new FileLocal(file, ReportLocal.this));
}
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ReportLocal other = (ReportLocal) obj;
if (getID() != other.getID()) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 13 * hash + getID();
return hash;
}
}