JasperServer JFreeChart grafiko išvaizdos tobulinimas su „Customizer Class”

jfreechart

Įrašas bus apie taip, kaip gan paprastai galima pagal asmeninius poreikius pasikeisti JasperServer grafikų išvaizdą. Tikriausiai žinot, kad grafikai tiek iReport’e tiek pačiame JasperServer grafikai yra išpiešiami naudojant JFreeChart komponentą. iReport šiek tiek leidžia keisti grafiko išvaizdą, bet nepakankamai. Kažkodėl programuotojai iReport’e sukūrė tik galimybę keisti tik grafiko elementų (linijų, stulpelių ir pan.) spalvą, bet nerealizavo galimybės keisti linijų stilių, išpiešimo eiliškumą ir kitus naudingus parametrus. Yra kaip yra. Viską kitą yra gan lengvai padaroma su/per java Customizer Class.

jfreechart_2

Na apie viską iš pradžių. Turių iReport „multi axis” grafiką, kuriame stulpeliais yra išpiešiamas atvaizduojamų duomenų laiko intervalas, o linijiniu grafiku (line chart, ne XY!) yra išpiešiamas tam tikrų duomenų kitimas laike. Linijų (angl. series) iš viso yra net 15. Linijos dažnai persidengia ir linijas vaizduojant vien skirtingomis spalvomis yra labai sunku suprasti, kas kur ir kaip. Seniai žinojau, kad grafiko stilių galima keisti tam tikrais java kustomizatoriais (Customizer Class), tačiau ilgą laiką išsiversdavau ir be jų. Vieną kartą reikalas prispyrė, o nuo ko pradėti nežinojau. Ant tiesos kelio užvedė šis video: http://goo.gl/DYWAVx, kuriame šaunus indas demonstruoja nuo ko ir kaip reikia pradėti visą šį jovalą.

eclipse

Norint pradėti, pirmiausiai, reikia parsisiųsti Eclipse Luna java kompiliatorių. Bandžiau NetBeans, nepatiko. Taip pat reikės ir Java SE SDK. Viską susidiegus, reikia susikurti naują Eclipse projektą. Kadangi pats dariau viską pagal ankščiau aprašytą youtube filmuką, tad projektą pasivadinau „CustomLegendList” vardu. Kuriant naują projektą yra labai svarbu teisingai pasirinkti tinkamą JRE aplinką. Pasirinkau „CDC-1.1/Foundation-1.1. Paspaudus „next”, kompiliatorius užklaus papildomų java nustatymų.

eclipse_newproject
eclipse_javasettings

Perėjus į nustatymo lango kortelę „Libraries”, mygtuku „Add External JARs…” būtina įtraukti šiais bibliotekas: jasperreports-5.5.0.jar, jcommon-1.0.15.jar ir jfreechart-1.0.12.jar. Jas rasite savo JasperServer lib direktorijoje. Kelias iki direktorijos, mano atveju, buvo toks: „C:\Program Files\jasperreports-server-cp-5.0.0\apache-tomcat\webapps\jasperserver\WEB-INF\lib”. Kadangi mano jasperis gyvena nutolusiame serveryje, todėl visą lib direktoriją tiesiog persikopijavau į savo lokalų PC, į Eclipse direktoriją. Tiesa, jei bibliotekų projekto kūrimo stadijoje neįtrauksite, tai visada galėsite padaryti projekto savybių (angl. properties) lange:

bibliotekos

Toliau mūsų sukurtame projekte ant katalogo „src” spaudžiam dešinį pelės klavišą ir susikuriame naują paketą, kurį pavadiname „Customizer”. Paketo pavadinimas yra ypač svarbus, nes jis bus naudojamas iReport’o grafiko nustatymuose.

eclipse_newpackage
eclipse_newpackage2

Po to reikia susikurti naują klasę (angl. Class), kurią, paprastumo dėlei, irgi pavadinkime „customizer”:

eclipse_class
eclipse_class2

Atsidariusiame darbo lape jau galima rašyti mūsų customize calss’ę. Štai ką po ilgo googlinimo „pribūriau”:

package Customizer;

import java.awt.BasicStroke;
import java.awt.Color;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.ui.RectangleEdge;

import org.jfree.util.ShapeUtilities;

import net.sf.jasperreports.engine.JRChart;
import net.sf.jasperreports.engine.JRChartCustomizer;

public class customizer implements JRChartCustomizer {

public void customize(JFreeChart chart, JRChart jasperChart) {

LegendTitle legend = chart.getLegend();
legend.setPosition(RectangleEdge.BOTTOM);

CategoryPlot plot = (CategoryPlot) chart.getPlot();

//J1 - J5
plot.getRenderer().setSeriesStroke(0, new BasicStroke(3.0f));
plot.getRenderer().setSeriesStroke(1, new BasicStroke(3.0f));
plot.getRenderer().setSeriesStroke(2, new BasicStroke(3.0f));
plot.getRenderer().setSeriesStroke(3, new BasicStroke(3.0f));
plot.getRenderer().setSeriesStroke(4, new BasicStroke(3.0f));

plot.getRenderer().setSeriesShape(0, ShapeUtilities.createDiamond(6));
plot.getRenderer().setSeriesShape(1, ShapeUtilities.createDiamond(6));
plot.getRenderer().setSeriesShape(2, ShapeUtilities.createDiamond(6));
plot.getRenderer().setSeriesShape(3, ShapeUtilities.createDiamond(6));
plot.getRenderer().setSeriesShape(4, ShapeUtilities.createDiamond(6));

//J1_TP1 - J5_TP1
plot.getRenderer().setSeriesStroke(5, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(6, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(7, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(8, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(9, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f));

//J1_TP0 - T5_TP0
plot.getRenderer().setSeriesStroke(10, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(11, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(12, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(13, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f));
plot.getRenderer().setSeriesStroke(14, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f));

}
}

Kodas veikia gan paprastai. Praleidus visokių bibliotekų įtraukimus ir naudojamų metodų aprašymus lieka tik krūva eilučių su aibe funkcijų, kurios ir atlieka tam tikrą darbą:

  • .setSeriesStroke(0, new BasicStroke(3.0f)) – nustato linijos storį pasirinktai kreivei (šiuo atveju pirmai, nes kreivės yra skaičiuojamos nuo nulio).
  • .setSeriesShape(0, ShapeUtilities.createDiamond(6)) – nustato pasirinktų linijų grafinį žymėjimą, šiuo atveju pirmai kreivei yra priskiriamas deimanto simbolis.
  • .setSeriesStroke(5, new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,1.0f, new float[] {6.0f, 6.0f}, 0.0f)) – nustato pasirinktos linijos stilių, šiuo atveju šešta linija yra piešiama punktyru.

Beliko kodą susikompiliuoti. Tam ant darbo lapo customizer.java spaudžiam dešiniu klavišu ir pasirenkam „Export”:

eclipse_export

Atsidariusiame wizard’e, šuoliuojam per žingsnius, nurodome katalogą, į kurį norime padėti sukompiliuotą jar failą, kur reikia nuimame ir uždedame varneles:

eclipse_export2
eclipse_export3
eclipse_export3
eclipse_export5

Viską atlikę, ankščiau nurodytame kataloge rasite jau pilnai paruoštą ir sukompiliuotą failą (tingintiems kompliuoti, savo failo varaitą įkėliau čia: customizer.zip), ką gi dabar daryti su juo?

Pirmiausia, sukompiliuotą JAR failą reikią įtraukti į iReport ClassPath. Rekomenduoju nustatymų lange ties įtrauktu JAR failu įjungti varnelę „Reloadable”. „Reloadable” reiškia, kad konkretus JAR failas bus kiekvieną kartą iš naujo užkraunamas ataskaitos generavimo metu. Kitu atveju, JAR failas bus užkrautas tik vieną kartą, iReport paleidimo metu. „Reloadable” yra pravartu tada, kai programuojate pačia cusstomize klasę, nes nereikią kiek vieną kartą perkrauti iReport, o užtenka tik iš naujo susigeneruoti ataskaitą.

ireport_classpath

Po to, konkretaus grafiko savybių (angl. Properties) lange reikia nurodyti „Customizer Class”. Tam skirtame langelyje įrašome  paketo ir klasės pavadinimą. Mūsų atveju, t. y. „Customizer.customizer”. Toks įdomus pastebėjimas: keista, bet nurodžius klasę bendrai Multi Axis grafikui, ji yra, kažkodėl, pritaikoma tik pirmam iš eilės einančiam grafikui. Kiek bandžiau programiškai prisikasti iki kitų grafikų, man niekaip to padaryti nepavyko. Manau, kad čia yra pačio iReport niuansas arba tiesiog pats kažko nežinau… Na bet kokiu atveju, jei norite keisti tik vieno iš Multi Axis grafiko grafikų stilių, „Customizer Class” nurodykite tik jam, o ne bendrai Multi Axis grafikui. Taip tikrai viskas veiks.

ireport_chart
ireport_chart_class

Viską atlikus, iš naujo sugeneruotoje ataskaitoje grafikas turėtų įgauti naują, programiškai nustatytą stilių. Mano grafikas po pakeitimų atrodo maždaug taip:

jfreechart_1

Norint, kad pakeitimai veiktų ir JasperServer Respository gulinčiai ataskaitai, į konkrečios ataskaitos Resources katalogą reikią įkelti mūsų sukompiliuotą JAR failą. Įkeliamą failą reiktų užvadinti tuo pačiu faile naudojamu java klasės pavadinimu, pav. „Customizer”.

jasper_respository