├── demo
├── db
│ └── pivot
│ │ ├── dbex.lck
│ │ ├── db.lck
│ │ ├── log
│ │ ├── log.ctrl
│ │ ├── log1.dat
│ │ └── logmirror.ctrl
│ │ ├── seg0
│ │ ├── c10.dat
│ │ ├── c101.dat
│ │ ├── c111.dat
│ │ ├── c121.dat
│ │ ├── c130.dat
│ │ ├── c141.dat
│ │ ├── c150.dat
│ │ ├── c161.dat
│ │ ├── c171.dat
│ │ ├── c180.dat
│ │ ├── c191.dat
│ │ ├── c1a1.dat
│ │ ├── c1b1.dat
│ │ ├── c1c0.dat
│ │ ├── c1d1.dat
│ │ ├── c1e0.dat
│ │ ├── c1f1.dat
│ │ ├── c20.dat
│ │ ├── c200.dat
│ │ ├── c211.dat
│ │ ├── c221.dat
│ │ ├── c230.dat
│ │ ├── c241.dat
│ │ ├── c251.dat
│ │ ├── c260.dat
│ │ ├── c271.dat
│ │ ├── c281.dat
│ │ ├── c290.dat
│ │ ├── c2a1.dat
│ │ ├── c2b1.dat
│ │ ├── c2c1.dat
│ │ ├── c2d0.dat
│ │ ├── c2e1.dat
│ │ ├── c2f0.dat
│ │ ├── c300.dat
│ │ ├── c31.dat
│ │ ├── c311.dat
│ │ ├── c321.dat
│ │ ├── c331.dat
│ │ ├── c340.dat
│ │ ├── c351.dat
│ │ ├── c361.dat
│ │ ├── c371.dat
│ │ ├── c380.dat
│ │ ├── c391.dat
│ │ ├── c3a1.dat
│ │ ├── c3b1.dat
│ │ ├── c3e0.dat
│ │ ├── c41.dat
│ │ ├── c51.dat
│ │ ├── c60.dat
│ │ ├── c71.dat
│ │ ├── c81.dat
│ │ ├── c90.dat
│ │ ├── ca1.dat
│ │ ├── cb1.dat
│ │ ├── cc0.dat
│ │ ├── cd1.dat
│ │ ├── ce1.dat
│ │ └── cf0.dat
│ │ └── service.properties
├── src
│ ├── main
│ │ ├── webapp
│ │ │ ├── index.html
│ │ │ ├── images
│ │ │ │ ├── glyphicons-halflings.png
│ │ │ │ └── glyphicons-halflings-white.png
│ │ │ ├── css
│ │ │ │ └── style.css
│ │ │ └── WEB-INF
│ │ │ │ └── web.xml
│ │ ├── resources
│ │ │ └── log4j.properties
│ │ └── java
│ │ │ └── ro
│ │ │ └── fortsoft
│ │ │ └── wicket
│ │ │ └── pivot
│ │ │ └── demo
│ │ │ ├── PivotPage.html
│ │ │ ├── PivotApplication.java
│ │ │ ├── PivotDataSourceHandler.java
│ │ │ ├── PivotConfigSessionStorage.java
│ │ │ └── PivotPage.java
│ └── test
│ │ └── java
│ │ └── ro
│ │ └── fortsoft
│ │ └── wicket
│ │ └── pivot
│ │ └── Start.java
├── init_derby.sql
└── pom.xml
├── wicket-pivot.png
├── .gitignore
├── wicket-pivot
├── src
│ └── main
│ │ └── java
│ │ └── ro
│ │ └── fortsoft
│ │ └── wicket
│ │ └── pivot
│ │ ├── wicket-package_de.properties
│ │ ├── web
│ │ ├── res
│ │ │ ├── sort-behavior.template.js
│ │ │ ├── pivot.js
│ │ │ ├── pivot.css
│ │ │ ├── jquery.json-2.2.min.js
│ │ │ ├── jquery.dropdown.css
│ │ │ └── jquery.dropdown.js
│ │ ├── AggregatorPanel.html
│ │ ├── PivotFieldActionsPanel.html
│ │ ├── PivotAreaPanel.html
│ │ ├── FieldCalculationPanel.html
│ │ ├── PivotTable.html
│ │ ├── PivotConfigStoragePanel.html
│ │ ├── AreaChangedEvent.java
│ │ ├── PivotPanel.html
│ │ ├── PivotResourcesBehavior.java
│ │ ├── SortableAjaxBehavior.java
│ │ ├── AggregatorPanel.java
│ │ ├── PivotConfigStoragePanel.java
│ │ ├── PivotFieldActionsPanel.java
│ │ ├── FieldCalculationPanel.java
│ │ ├── PivotSettings.java
│ │ ├── PivotAreaPanel.java
│ │ ├── PivotTable.java
│ │ └── PivotPanel.java
│ │ ├── wicket-package_ro.properties
│ │ ├── wicket-package.properties
│ │ ├── PivotFieldActionsFactory.java
│ │ ├── tree
│ │ ├── Tree.java
│ │ ├── TreeIterator.java
│ │ ├── TreeHelper.java
│ │ └── Node.java
│ │ ├── PivotUtils.java
│ │ ├── PivotDataSource.java
│ │ ├── exporter
│ │ ├── PivotExporter.java
│ │ └── PivotCsvExporter.java
│ │ ├── config
│ │ ├── IPivotConfigStorage.java
│ │ └── PivotConfig.java
│ │ ├── DefaultPivotFieldActionsFactory.java
│ │ ├── PivotModel.java
│ │ ├── ResultSetPivotDataSource.java
│ │ ├── PivotField.java
│ │ ├── FieldCalculation.java
│ │ ├── Aggregator.java
│ │ ├── PivotFieldAction.java
│ │ └── DefaultPivotModel.java
└── pom.xml
├── wicket-pivot-exporter
├── pom.xml
└── src
│ └── main
│ └── java
│ └── ro
│ └── fortsoft
│ └── wicket
│ └── pivot
│ └── exporter
│ ├── PivotExporters.java
│ └── PivotXlsExporter.java
├── pom.xml
└── README.md
/demo/db/pivot/dbex.lck:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/db/pivot/db.lck:
--------------------------------------------------------------------------------
1 | $a816c00e-0138-fbc2-5b5e-000003fd9cb0
--------------------------------------------------------------------------------
/wicket-pivot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/wicket-pivot.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .project
3 | .classpath
4 | .settings
5 | demo/data/
6 | .idea/
7 | *.iml
8 |
--------------------------------------------------------------------------------
/demo/db/pivot/log/log.ctrl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/log/log.ctrl
--------------------------------------------------------------------------------
/demo/db/pivot/log/log1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/log/log1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c10.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c10.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c101.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c101.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c111.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c111.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c121.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c121.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c130.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c130.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c141.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c141.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c150.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c150.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c161.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c161.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c171.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c171.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c180.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c180.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c191.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c191.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c1a1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c1a1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c1b1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c1b1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c1c0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c1c0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c1d1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c1d1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c1e0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c1e0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c1f1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c1f1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c20.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c20.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c200.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c200.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c211.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c211.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c221.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c221.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c230.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c230.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c241.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c241.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c251.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c251.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c260.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c260.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c271.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c271.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c281.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c281.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c290.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c290.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c2a1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c2a1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c2b1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c2b1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c2c1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c2c1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c2d0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c2d0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c2e1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c2e1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c2f0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c2f0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c300.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c300.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c31.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c31.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c311.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c311.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c321.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c321.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c331.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c331.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c340.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c340.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c351.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c351.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c361.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c361.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c371.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c371.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c380.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c380.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c391.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c391.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c3a1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c3a1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c3b1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c3b1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c3e0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c3e0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c41.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c41.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c51.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c51.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c60.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c60.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c71.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c71.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c81.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c81.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/c90.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/c90.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/ca1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/ca1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/cb1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/cb1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/cc0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/cc0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/cd1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/cd1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/ce1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/ce1.dat
--------------------------------------------------------------------------------
/demo/db/pivot/seg0/cf0.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/seg0/cf0.dat
--------------------------------------------------------------------------------
/demo/db/pivot/log/logmirror.ctrl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/db/pivot/log/logmirror.ctrl
--------------------------------------------------------------------------------
/demo/src/main/webapp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/webapp/images/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/src/main/webapp/images/glyphicons-halflings.png
--------------------------------------------------------------------------------
/demo/src/main/webapp/images/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/demo/src/main/webapp/images/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/wicket-package_de.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decebals/wicket-pivot/HEAD/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/wicket-package_de.properties
--------------------------------------------------------------------------------
/demo/src/main/webapp/css/style.css:
--------------------------------------------------------------------------------
1 | @CHARSET "ISO-8859-1";
2 |
3 | #wicketDebugLink {
4 | font-size: 10px;
5 | }
6 |
7 | div.wicket-modal div.w_caption {
8 | height: 1.7em !important;
9 | }
10 |
11 | h3.w_captionText {
12 | font-size: 13px !important;
13 | }
14 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/res/sort-behavior.template.js:
--------------------------------------------------------------------------------
1 | $('#${component}').sortable({
2 | connectWith: '.fields',
3 | forcePlaceholderSize: true,
4 | placeholder: 'pivot-placeholder',
5 | cursor: 'move',
6 | opacity: 0.5,
7 | stop: function(event, ui) {
8 | ${stopBehavior}
9 | }
10 | });
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/wicket-package_ro.properties:
--------------------------------------------------------------------------------
1 | # pivot areas
2 | row=RAND
3 | column=COLOANA
4 | data=DATE
5 | unused=NEUTILIZATE
6 |
7 | showGrandTotalForColumn=Afiseaza total general pentru coloana
8 | showGrandTotalForRow=Afiseaza total general pentru rand
9 | autoCalculate=Calcul automat
10 | showPivot=Afiseaza pivot
11 |
12 | downloadAs=Descarca ca ${}
13 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/AggregatorPanel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=INFO,Console
2 |
3 | log4j.appender.Console=org.apache.log4j.ConsoleAppender
4 | log4j.appender.Console.layout=org.apache.log4j.PatternLayout
5 | log4j.appender.Console.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n
6 |
7 | log4j.logger.org.apache.wicket=INFO
8 | log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=INFO
9 | log4j.logger.org.apache.wicket.version=INFO
10 | log4j.logger.org.apache.wicket.RequestCycle=INFO
11 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/wicket-package.properties:
--------------------------------------------------------------------------------
1 | # pivot areas
2 | row=ROW
3 | column=COLUMN
4 | data=DATA
5 | unused=UNUSED
6 |
7 | showGrandTotalForColumn=Show grand total for column
8 | showGrandTotalForRow=Show grand total for row
9 | autoCalculate=Auto calculate
10 | showPivot=Show pivot
11 |
12 | downloadAs=Download as ${}
13 |
14 | loadSaveConfiguration=Load/Save Configuration
15 | loadConfiguration=Load
16 | deleteConfiguration=Delete
17 | saveConfiguration=Save configuration
18 | savedConfigurations=Your saved configurations:
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotFieldActionsPanel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotAreaPanel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/demo/init_derby.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE STATISTIC;
2 |
3 | CREATE TABLE STATISTIC (
4 | REGION varchar(20),
5 | SALESMAN varchar(20),
6 | "YEAR" int,
7 | MONTH int,
8 | SALES int,
9 | COST int
10 | );
11 |
12 | INSERT INTO STATISTIC (REGION, SALESMAN, "YEAR", MONTH, SALES, COST) VALUES
13 | ('1', 'John', 2005, 3, 1000, 100),
14 | ('1', 'David', 2005, 3, 1300, 200),
15 | ('1', 'Sophia', 2005, 1, 312, 400),
16 | ('2', 'David', 2005, 3, 1234, 0),
17 | ('2', 'Sophia', 2006, 3, 543, 0),
18 | ('3', 'John', 2006, 4, 534, 0),
19 | ('3', 'David', 2006, 6, 423, 0),
20 | ('3', 'John', 2007, 8, 134, 0),
21 | ('4', 'Sophia', 2007, 4, 423, 0),
22 | ('4', 'David', 2007, 2, 466, 0),
23 | ('4', 'David', 2008, 4, 563, 0),
24 | ('4', 'John', 2008, 5, 222, 0),
25 | ('1', 'Oliver', 2005, 2, 0, 0)
26 |
--------------------------------------------------------------------------------
/demo/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | Pivot
9 |
10 |
11 | pivot
12 | org.apache.wicket.protocol.http.WicketFilter
13 |
14 | applicationClassName
15 | ro.fortsoft.wicket.pivot.demo.PivotApplication
16 |
17 |
18 |
19 |
20 | pivot
21 | /app/*
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/FieldCalculationPanel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/demo/src/main/java/ro/fortsoft/wicket/pivot/demo/PivotPage.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Simple wicket pivot table
16 |
A java web pivot table with SQL select as data source.
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotTable.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/res/pivot.js:
--------------------------------------------------------------------------------
1 | function serializeFieldLocations(/*areasId*/) {
2 | // console.log(areasId);
3 | var items = [];
4 | // $("#" + areasId).find("ol.fields").each(function() {
5 | $("ol.fields").each(function() {
6 | var areaId = $(this).attr("id");
7 | var areaName = areaId.substring(areaId.indexOf("-") + 1, areaId.lastIndexOf("-")); // "area--"
8 | $(this).children().each(function(i) {
9 | var fieldId = $(this).attr("id");
10 | var fieldIndex = fieldId.substring(6); // "field-"
11 | // create item object for current panel
12 | var item = {
13 | areaName : areaName,
14 | fieldIndex : fieldIndex,
15 | sortIndex : i
16 | };
17 |
18 | // push item object into items array
19 | items.push(item);
20 | });
21 | });
22 |
23 | // pass items variable to server to save state
24 | var data = $.toJSON(items);
25 |
26 | return data;
27 | }
28 |
--------------------------------------------------------------------------------
/demo/db/pivot/service.properties:
--------------------------------------------------------------------------------
1 | #/stuff/work/wicket-pivot/demo/db/pivot
2 | # ********************************************************************
3 | # *** Please do NOT edit this file. ***
4 | # *** CHANGING THE CONTENT OF THIS FILE MAY CAUSE DATA CORRUPTION. ***
5 | # ********************************************************************
6 | #Thu Aug 02 16:20:46 EEST 2012
7 | SysschemasIndex2Identifier=225
8 | SyscolumnsIdentifier=144
9 | SysconglomeratesIndex1Identifier=49
10 | SysconglomeratesIdentifier=32
11 | SyscolumnsIndex2Identifier=177
12 | SysschemasIndex1Identifier=209
13 | SysconglomeratesIndex3Identifier=81
14 | SystablesIndex2Identifier=129
15 | SyscolumnsIndex1Identifier=161
16 | derby.serviceProtocol=org.apache.derby.database.Database
17 | SysschemasIdentifier=192
18 | derby.storage.propertiesId=16
19 | SysconglomeratesIndex2Identifier=65
20 | derby.serviceLocale=en_US
21 | SystablesIdentifier=96
22 | SystablesIndex1Identifier=113
23 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotConfigStoragePanel.html:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 | Your saved configurations:
12 |
14 |
15 |
16 |
17 | Load
18 |
19 |
20 |
21 | Delete
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/PivotFieldActionsFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.util.List;
16 |
17 | /**
18 | * @author Decebal Suiu
19 | */
20 | public interface PivotFieldActionsFactory {
21 |
22 | public List createPivotFieldActions(PivotField field, PivotModel model);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/tree/Tree.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.tree;
14 |
15 | import java.io.Serializable;
16 |
17 | /**
18 | * @author Decebal Suiu
19 | */
20 | public class Tree implements Serializable {
21 |
22 | private static final long serialVersionUID = 1L;
23 |
24 | private Node root;
25 |
26 | public Tree(Node root) {
27 | this.root = root;
28 | }
29 |
30 | public Node getRoot() {
31 | return this.root;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/wicket-pivot-exporter/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ro.fortsoft.wicket.pivot
6 | wicket-pivot-parent
7 | 0.6.0-SNAPHOT
8 |
9 |
10 | 4.0.0
11 | wicket-pivot-exporter
12 | 0.6.0-SNAPHOT
13 | jar
14 | Wicket Pivot Exporter
15 | Simple web pivot table using Apache Wicket Exporter Plugins
16 |
17 |
18 |
19 |
20 | ro.fortsoft.wicket.pivot
21 | wicket-pivot
22 | ${project.version}
23 |
24 |
25 |
26 |
27 | org.apache.poi
28 | poi
29 | 4.1.1
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/AreaChangedEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import org.apache.wicket.ajax.AjaxRequestTarget;
16 |
17 | /**
18 | * @author Decebal Suiu
19 | */
20 | public class AreaChangedEvent {
21 |
22 | private final AjaxRequestTarget target;
23 |
24 | public AreaChangedEvent(AjaxRequestTarget target) {
25 | this.target = target;
26 | }
27 |
28 | public AjaxRequestTarget getAjaxRequestTarget() {
29 | return target;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/wicket-pivot-exporter/src/main/java/ro/fortsoft/wicket/pivot/exporter/PivotExporters.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.exporter;
14 |
15 | /**
16 | * Factory for the pivot exporter
17 | */
18 | public class PivotExporters {
19 | private PivotExporters() {
20 | }
21 |
22 | /**
23 | * Factory to get all existing Pivot Exporter
24 | *
25 | * @return a new List of exporter instances
26 | */
27 | public static PivotExporter[] createAllExporter() {
28 | return new PivotExporter[] { new PivotXlsExporter(), new PivotCsvExporter() };
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/PivotUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.util.List;
16 |
17 | import ro.fortsoft.wicket.pivot.FieldCalculation.FieldValueProvider;
18 |
19 | /**
20 | * @author Decebal Suiu
21 | */
22 | public class PivotUtils {
23 |
24 | public static Number getSummary(PivotField dataField, List values, FieldValueProvider fieldValueProvider) {
25 | if(dataField.getFieldCalculation() != null )
26 | return (Number)dataField.getFieldCalculation().init().calculate(fieldValueProvider);
27 | return (Number) dataField.getAggregator().init().addAll(values).getResult();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/wicket-pivot/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ro.fortsoft.wicket.pivot
6 | wicket-pivot-parent
7 | 0.6.0-SNAPHOT
8 |
9 |
10 | 4.0.0
11 | wicket-pivot
12 | 0.6.0-SNAPHOT
13 | jar
14 | Wicket Pivot
15 | Simple web pivot table using Apache Wicket
16 |
17 |
18 | 2.8.9
19 |
20 |
21 |
22 |
23 |
24 | commons-collections
25 | commons-collections
26 | 3.2.2
27 |
28 |
29 |
30 | commons-lang
31 | commons-lang
32 | 2.6
33 |
34 |
35 |
36 |
37 | com.google.code.gson
38 | gson
39 | ${gson.version}
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/PivotDataSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 |
17 | /**
18 | * @author Decebal Suiu
19 | */
20 | public interface PivotDataSource extends Serializable {
21 |
22 | public String getFieldName(int fieldIndex);
23 |
24 | public int getFieldIndex(String fieldName);
25 |
26 | public Class> getFieldType(int fieldIndex);
27 |
28 | /**
29 | * Gets number of fields in this data source.
30 | */
31 | public int getFieldCount();
32 |
33 | /**
34 | * Gets the row count.
35 | */
36 | public int getRowCount();
37 |
38 | /**
39 | * Gets the value at the specified field index and the row index.
40 | */
41 | public Object getValueAt(int rowIndex, int fieldIndex);
42 |
43 | public Object getValueAt(int rowIndex, PivotField field);
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/res/pivot.css:
--------------------------------------------------------------------------------
1 | @CHARSET "ISO-8859-1";
2 |
3 | .pivot {
4 | margin-top: 10px;
5 | }
6 |
7 | .pivot .row-header {
8 | font-weight: bold;
9 | }
10 |
11 | .pivot .grand-total {
12 | color: #3A87AD;
13 | font-weight: bold;
14 | }
15 |
16 | .areas {
17 | padding: 5px;
18 | margin: 0px 0px 10px 0px;
19 | border: 1px solid #eee;
20 | -webkit-border-radius: 4px;
21 | -moz-border-radius: 4px;
22 | border-radius: 4px;
23 | }
24 |
25 | .area .name {
26 | font-weight: bold;
27 | padding: 5px;
28 | }
29 |
30 | .area .field {
31 | float: left;
32 | padding: 5px;
33 | margin-right: 5px;
34 | border: 1px solid #eee;
35 | background-color: #336699;
36 | -webkit-border-radius: 4px;
37 | -moz-border-radius: 4px;
38 | border-radius: 4px;
39 | font-size: 11px;
40 | font-weight: bold;
41 | line-height: 14px;
42 | color: #ffffff;
43 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
44 | white-space: nowrap;
45 | vertical-align: baseline;
46 | }
47 |
48 | .area .field-number {
49 | background-color: #669966;
50 | }
51 |
52 | .area ol.fields {
53 | list-style-type: none;
54 | float: left;
55 | display: block;
56 | }
57 |
58 | .pivot-placeholder {
59 | float: left;
60 | padding: 5px;
61 | margin-right: 5px;
62 | border: 1px dashed #ddd;
63 | background-color: #f0f0f0;
64 | -webkit-border-radius: 4px;
65 | -moz-border-radius: 4px;
66 | border-radius: 4px;
67 | line-height: 14px;
68 | white-space: nowrap;
69 | vertical-align: baseline;
70 | }
71 |
72 | .pivot-config-store-button {
73 | float:right;
74 | }
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/exporter/PivotExporter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.exporter;
14 |
15 | import java.io.IOException;
16 | import java.io.OutputStream;
17 | import java.io.Serializable;
18 |
19 | import ro.fortsoft.wicket.pivot.PivotModel;
20 |
21 | /**
22 | * Interface for the pivot exporter plugins
23 | */
24 | public interface PivotExporter extends Serializable {
25 | /**
26 | * @return how is this export named? E.g. CSV
27 | */
28 | String getFormatName();
29 |
30 | /**
31 | * @return the filename extension for the download without the ".", e.g. csv
32 | * or xls
33 | */
34 | String getFilenameExtension();
35 |
36 | /**
37 | *
38 | * @return the mimetype
39 | */
40 | String getFormatMimetype();
41 |
42 | /**
43 | * Export the given PivotModel into the outputStream.
44 | */
45 | void exportPivot(PivotModel pivotModel, OutputStream outputStream) throws IOException;
46 | }
47 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/config/IPivotConfigStorage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013, 2014 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.config;
14 |
15 | import java.util.List;
16 |
17 | /**
18 | * Implementations of this interface can store and restore the current
19 | * configuration of the pivot table.
20 | *
21 | * This interface should be implemented by clients.
22 | */
23 | public interface IPivotConfigStorage {
24 | /**
25 | *
26 | * @return the list of all stored configurations
27 | */
28 | List listConfigNames();
29 |
30 | /**
31 | * Load a configuration
32 | *
33 | * @param name
34 | * @return null or the stored configuration
35 | */
36 | PivotConfig loadConfig(String name);
37 |
38 | /**
39 | * Save a configuration. If a configuration with the same name already
40 | * exists, it will be overwritten
41 | */
42 | void saveConfig(PivotConfig config);
43 |
44 | /**
45 | * Delete the configuration with this name
46 | *
47 | * @param name
48 | */
49 | void deleteConfig(String name);
50 | }
51 |
--------------------------------------------------------------------------------
/demo/src/main/java/ro/fortsoft/wicket/pivot/demo/PivotApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.demo;
14 |
15 | import org.apache.wicket.Page;
16 | import org.apache.wicket.protocol.http.WebApplication;
17 |
18 | /**
19 | * @author Decebal Suiu
20 | */
21 | public class PivotApplication extends WebApplication {
22 |
23 | public PivotApplication() {
24 | super();
25 | }
26 |
27 | @Override
28 | public void init() {
29 | super.init();
30 |
31 | // markup settings
32 | getMarkupSettings().setStripWicketTags(true);
33 | getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
34 |
35 | // exception settings
36 | getResourceSettings().setThrowExceptionOnMissingResource(false);
37 | }
38 |
39 | @Override
40 | public Class extends Page> getHomePage() {
41 | return PivotPage.class;
42 | }
43 |
44 | /*
45 | // for test locale
46 | @Override
47 | public Session newSession(Request request, Response response) {
48 | Session session = super.newSession(request, response);
49 | session.setLocale(new Locale("ro", "RO"));
50 |
51 | return session;
52 | }
53 | */
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/DefaultPivotFieldActionsFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | /**
20 | * @author Decebal Suiu
21 | */
22 | public class DefaultPivotFieldActionsFactory implements PivotFieldActionsFactory, Serializable {
23 |
24 | private static final long serialVersionUID = 1L;
25 |
26 | @Override
27 | public List createPivotFieldActions(PivotField field, PivotModel model) {
28 | List fieldActions = new ArrayList<>();
29 |
30 | // fieldActions.add(new PivotFieldAction.Delete(field));
31 | if (field.getArea().equals(PivotField.Area.DATA) && field.getAggregator() != null) {
32 | fieldActions.add(new PivotFieldAction.AggregatorAction(field));
33 | }
34 | if (field.getArea().equals(PivotField.Area.DATA)) {
35 | if (field.getFieldCalculation() != null)
36 | fieldActions.add(new PivotFieldAction.FieldCalculationAction(field, model));
37 | else
38 | fieldActions.add(new PivotFieldAction.AddNewFieldCalculationAction(field, model));
39 | }
40 | return fieldActions;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotPanel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Load/Save Configuration
6 |
9 |
27 |
28 | Show pivot
29 |
30 |
33 |
34 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/tree/TreeIterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.tree;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Iterator;
17 | import java.util.List;
18 |
19 | /**
20 | * @author Decebal Suiu
21 | */
22 | public class TreeIterator implements Iterator {
23 |
24 | private Iterator iterator;
25 |
26 | public TreeIterator(Node root) {
27 | this.iterator = getList(root).iterator();
28 | }
29 |
30 | @Override
31 | public boolean hasNext() {
32 | return iterator.hasNext();
33 | }
34 |
35 | @Override
36 | public void remove() {
37 | throw new UnsupportedOperationException();
38 | }
39 |
40 | @Override
41 | public Node next() {
42 | return iterator.next();
43 | }
44 |
45 | public Iterator getValuesIterator() {
46 | List values = new ArrayList<>();
47 | while (hasNext()) {
48 | values.add(next().getData());
49 | }
50 |
51 | return values.iterator();
52 | }
53 |
54 | private List getList(Node node) {
55 | List nodes = new ArrayList<>();
56 | nodes.add(node);
57 | for (Node value : node.getChildren()) {
58 | nodes.addAll(getList(value));
59 | }
60 |
61 | return nodes;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/PivotModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 | import java.util.List;
17 |
18 | import ro.fortsoft.wicket.pivot.PivotField.Area;
19 | import ro.fortsoft.wicket.pivot.tree.Tree;
20 |
21 | /**
22 | * @author Decebal Suiu
23 | */
24 | public interface PivotModel extends Serializable {
25 |
26 | /**
27 | * Gets all the PivotFields.
28 | */
29 | public List getFields();
30 |
31 | public List getFields(Area area);
32 |
33 | public PivotField getField(String name);
34 |
35 | public PivotField getField(int index);
36 |
37 | public PivotDataSource getDataSource();
38 |
39 | /**
40 | * Calculates the pivot data.
41 | */
42 | public void calculate();
43 |
44 | public List> getRowKeys();
45 |
46 | public List> getColumnKeys();
47 |
48 | public Object getValueAt(PivotField dataField, List rowKey, List columnKey);
49 |
50 | public boolean isShowGrandTotalForColumn();
51 |
52 | public void setShowGrandTotalForColumn(boolean showGrandTotalForColumn);
53 |
54 | public boolean isShowGrandTotalForRow();
55 |
56 | public void setShowGrandTotalForRow(boolean showGrandTotalForRow);
57 |
58 | public Tree getColumnsHeaderTree(); // ?!
59 |
60 | public Tree getRowsHeaderTree(); // ?!
61 |
62 | public boolean isAutoCalculate();
63 |
64 | public void setAutoCalculate(boolean autoCalculate);
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotResourcesBehavior.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import org.apache.wicket.Component;
16 | import org.apache.wicket.behavior.Behavior;
17 | import org.apache.wicket.markup.head.CssHeaderItem;
18 | import org.apache.wicket.markup.head.IHeaderResponse;
19 | import org.apache.wicket.markup.head.JavaScriptHeaderItem;
20 |
21 | /**
22 | * @author Decebal Suiu
23 | */
24 | public class PivotResourcesBehavior extends Behavior {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | @Override
29 | public void renderHead(Component component, IHeaderResponse response) {
30 | super.renderHead(component, response);
31 |
32 | PivotSettings settings = PivotSettings.get();
33 |
34 | if (settings.isIncludeJQuery()) {
35 | response.render(JavaScriptHeaderItem.forReference(settings.getJQueryReference()));
36 | }
37 |
38 | if (settings.isIncludeJQueryUI()) {
39 | response.render(JavaScriptHeaderItem.forReference(settings.getJQueryUIReference()));
40 | }
41 |
42 | if (settings.isIncludeJQueryJson()) {
43 | response.render(JavaScriptHeaderItem.forReference(settings.getJQueryJsonReference()));
44 | }
45 |
46 | if (settings.isIncludeJavaScript()) {
47 | response.render(JavaScriptHeaderItem.forReference(settings.getJavaScriptReference()));
48 | }
49 |
50 | if (settings.isIncludeCss()) {
51 | response.render(CssHeaderItem.forReference(settings.getCssReference()));
52 | }
53 |
54 | if (settings.isIncludeBootstrap()) {
55 | response.render(CssHeaderItem.forReference(settings.getBootstrapCssReference()));
56 | response.render(JavaScriptHeaderItem.forReference(settings.getBootstrapJavaScriptReference()));
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/res/jquery.json-2.2.min.js:
--------------------------------------------------------------------------------
1 |
2 | (function($){$.toJSON=function(o)
3 | {if(typeof(JSON)=='object'&&JSON.stringify)
4 | return JSON.stringify(o);var type=typeof(o);if(o===null)
5 | return"null";if(type=="undefined")
6 | return undefined;if(type=="number"||type=="boolean")
7 | return o+"";if(type=="string")
8 | return $.quoteString(o);if(type=='object')
9 | {if(typeof o.toJSON=="function")
10 | return $.toJSON(o.toJSON());if(o.constructor===Date)
11 | {var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
12 | hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
13 | if(o.constructor===Array)
14 | {var ret=[];for(var i=0;i listConfigNames() {
35 | @SuppressWarnings("unchecked")
36 | Map map = getStorageMap();
37 | return new ArrayList<>(map.keySet());
38 | }
39 |
40 | private Map getStorageMap() {
41 | @SuppressWarnings("unchecked")
42 | HashMap map = (HashMap) Session.get().getAttribute("PivotConfigStorageSession");
43 | if (map == null) {
44 | map = new HashMap<>();
45 | Session.get().setAttribute("PivotConfigStorageSession", map);
46 | }
47 | return map;
48 | }
49 |
50 | @Override
51 | public PivotConfig loadConfig(String name) {
52 | String str = getStorageMap().get(name);
53 | if (str == null)
54 | return null;
55 | return new Gson().fromJson(str, PivotConfig.class);
56 | }
57 |
58 | @Override
59 | public void saveConfig(PivotConfig config) {
60 | getStorageMap().put(config.getName(), new Gson().toJson(config));
61 | }
62 |
63 | @Override
64 | public void deleteConfig(String name) {
65 | getStorageMap().remove(name);
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/SortableAjaxBehavior.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.wicket.pivot.web;
2 |
3 | import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
4 | import org.apache.wicket.ajax.AjaxRequestTarget;
5 | import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
6 |
7 | import com.google.gson.Gson;
8 |
9 | /**
10 | * @author Decebal Suiu
11 | */
12 | public abstract class SortableAjaxBehavior extends AbstractDefaultAjaxBehavior {
13 |
14 | private static final long serialVersionUID = 1L;
15 |
16 | /** Sorted identifiant into the request */
17 | private static final String JSON_DATA = "data";
18 |
19 | public abstract void onSort(AjaxRequestTarget target, Item[] items);
20 |
21 | @Override
22 | protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
23 | super.updateAjaxAttributes(attributes);
24 |
25 | // String areasId = getComponent().findParent(PivotPanel.class).get("areas").getMarkupId();
26 | // System.out.println("areasId = " + areasId);
27 |
28 | StringBuilder buffer = new StringBuilder();
29 | // buffer.append("var data = serializeFieldLocations(" + areasId + ");");
30 | buffer.append("var data = serializeFieldLocations();");
31 | buffer.append("return {'" + JSON_DATA + "': data};");
32 |
33 | attributes.getDynamicExtraParameters().add(buffer);
34 | }
35 |
36 | @Override
37 | protected void respond(AjaxRequestTarget target) {
38 | String jsonData = getComponent().getRequest().getRequestParameters().getParameterValue(JSON_DATA).toString();
39 | Item[] items = getItems(jsonData);
40 | onSort(target, items);
41 | }
42 |
43 | private Item[] getItems(String jsonData) {
44 | Gson gson = new Gson();
45 | Item[] items = gson.fromJson(jsonData, Item[].class);
46 | /*
47 | System.out.println(items.length);
48 | for (Item item : items) {
49 | System.out.println(item);
50 | }
51 | */
52 |
53 | return items;
54 | }
55 |
56 | public static class Item {
57 |
58 | public String areaName;
59 | public int fieldIndex;
60 | public int sortIndex;
61 |
62 | @Override
63 | public String toString() {
64 | StringBuilder buffer = new StringBuilder();
65 | buffer.append("Item[");
66 | buffer.append("areaName = ").append(areaName);
67 | buffer.append(" fieldIndex = ").append(fieldIndex);
68 | buffer.append(" sortIndex = ").append(sortIndex);
69 | buffer.append("]");
70 |
71 | return buffer.toString();
72 | }
73 |
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/tree/TreeHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.tree;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Iterator;
17 | import java.util.List;
18 | import java.util.Objects;
19 |
20 | /**
21 | * @author Decebal Suiu
22 | */
23 | public class TreeHelper {
24 |
25 | public static List getLeafs(Node root) {
26 | List leafs = new ArrayList<>();
27 | Iterator it = new TreeIterator(root);
28 | while (it.hasNext()) {
29 | Node node = it.next();
30 | if (node.isLeaf()) {
31 | leafs.add(node);
32 | }
33 | }
34 |
35 | return leafs;
36 | }
37 |
38 | public static List> getLeafValues(Node root) {
39 | List> leafValues = new ArrayList<>();
40 | List leafs = getLeafs(root);
41 | for (Node leaf : leafs) {
42 | leafValues.add(leaf.getPathValues());
43 | }
44 |
45 | return leafValues;
46 | }
47 |
48 | public static Node getNode(Node root, List pathValues) {
49 | Node node = root;
50 | for (Object value : pathValues) {
51 | node = getChild(node, value);
52 | }
53 |
54 | return node;
55 | }
56 |
57 | public static Node getChild(Node node, Object value) {
58 | for (Node child : node.getChildren()) {
59 | Object data = child.getData();
60 | if (Objects.equals(value, data)) {
61 | return child;
62 | }
63 | }
64 |
65 | return null;
66 | }
67 |
68 |
69 | public static void printTree(Node root) {
70 | Iterator it = new TreeIterator(root);
71 | while (it.hasNext()) {
72 | Node node = it.next();
73 | int level = node.getLevel();
74 | if (level == 0) {
75 | System.out.println(String.format(node.toString() + " [%s]", getLeafs(node).size()));
76 | } else {
77 | System.out.println(String.format("%" + 3 * level + "s " + node.toString() + " [%s]", " ", getLeafs(node).size()));
78 | }
79 | }
80 | }
81 |
82 | public static void printLeafValues(Node root) {
83 | List> leafValues = getLeafValues(root);
84 | System.out.println("count > " + leafValues.size());
85 | for (List values : leafValues) {
86 | System.out.println(values);
87 | }
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/demo/src/test/java/ro/fortsoft/wicket/pivot/Start.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import org.eclipse.jetty.server.Server;
16 | import org.eclipse.jetty.server.bio.SocketConnector;
17 | import org.eclipse.jetty.webapp.WebAppContext;
18 |
19 | /**
20 | * @author Decebal Suiu
21 | */
22 | public class Start {
23 |
24 | public static void main(String[] args) throws Exception {
25 | Server server = new Server();
26 | SocketConnector connector = new SocketConnector();
27 |
28 | // Set some timeout options to make debugging easier.
29 | connector.setMaxIdleTime(1000 * 60 * 60);
30 | connector.setSoLingerTime(-1);
31 | int port = Integer.parseInt(System.getProperty("jetty.port", "8081"));
32 | connector.setPort(port);
33 | server.addConnector(connector);
34 |
35 | // the orders of handlers is very important!
36 | /*
37 | ContextHandler contextHandler = new ContextHandler();
38 | contextHandler.setContextPath("/res");
39 | contextHandler.setResourceBase("./upload/images/");
40 | contextHandler.addHandler(new ResourceHandler());
41 |
42 | server.addHandler(contextHandler);
43 | */
44 |
45 | WebAppContext webAppContext = new WebAppContext();
46 | webAppContext.setServer(server);
47 | webAppContext.setContextPath("/");
48 | webAppContext.setWar("src/main/webapp");
49 |
50 | // add virtual host but DON"T FORGET to add stores with these hosts
51 | // String[] virtualHosts = { "127.0.0.1", "127.0.0.2" };
52 | // webAppContext.setVirtualHosts(virtualHosts);
53 |
54 | server.setHandler(webAppContext);
55 |
56 | // START JMX SERVER
57 | // MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
58 | // MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
59 | // server.getContainer().addEventListener(mBeanContainer);
60 | // mBeanContainer.start();
61 |
62 | try {
63 | System.out.println(">>> STARTING EMBEDDED JETTY SERVER (" + port + "), PRESS ANY KEY TO STOP");
64 | server.start();
65 | System.in.read();
66 | System.out.println(">>> STOPPING EMBEDDED JETTY SERVER");
67 | // while (System.in.available() == 0) {
68 | // Thread.sleep(5000);
69 | // }
70 | server.stop();
71 | server.join();
72 | } catch (Exception e) {
73 | e.printStackTrace();
74 | System.exit(100);
75 | }
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/demo/src/main/java/ro/fortsoft/wicket/pivot/demo/PivotPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.demo;
14 |
15 | import org.apache.wicket.markup.html.WebPage;
16 |
17 | import ro.fortsoft.wicket.pivot.PivotDataSource;
18 | import ro.fortsoft.wicket.pivot.PivotField;
19 | import ro.fortsoft.wicket.pivot.PivotModel;
20 | import ro.fortsoft.wicket.pivot.web.PivotPanel;
21 |
22 | /**
23 | * @author Decebal Suiu
24 | */
25 | public class PivotPage extends WebPage {
26 |
27 | private static final long serialVersionUID = 1L;
28 |
29 | public PivotPage() {
30 | super();
31 |
32 | // create a pivot data source
33 | PivotDataSource pivotDataSource = PivotDataSourceHandler.getPivotDataSource();
34 | System.out.println("pivotDataSource = " + pivotDataSource);
35 | // System.out.println("fieldCount = " + pivotDataSource.getFieldCount());
36 | // System.out.println("rowCount = " + pivotDataSource.getRowCount());
37 |
38 | PivotPanel pivotPanel = new PivotPanel("pivot", pivotDataSource) {
39 |
40 | private static final long serialVersionUID = 1L;
41 |
42 | @Override
43 | protected PivotModel createPivotModel(PivotDataSource pivotDataSource) {
44 | PivotModel pivotModel = super.createPivotModel(pivotDataSource);
45 |
46 | // add some fields on some area
47 | pivotModel.getField("REGION").setArea(PivotField.Area.ROW);
48 | pivotModel.getField("SALESMAN").setArea(PivotField.Area.ROW).setAreaIndex(1);
49 | pivotModel.getField("YEAR").setArea(PivotField.Area.COLUMN);
50 | pivotModel.getField("MONTH").setArea(PivotField.Area.COLUMN).setAreaIndex(1);
51 | pivotModel.getField("SALES").setArea(PivotField.Area.DATA);
52 |
53 | // set an aggregator for a data pivot field
54 | // pivotModel.getField("SALES").setAggregator(new Aggregator.Count());
55 |
56 | // set a custom converter for a pivot field
57 | /*
58 | pivotModel.getField("SALES").setConverter(new DoubleConverter() {
59 |
60 | private static final long serialVersionUID = 1L;
61 |
62 | @Override
63 | public NumberFormat getNumberFormat(Locale locale) {
64 | NumberFormat format = super.getNumberFormat(locale);
65 | format.setMinimumFractionDigits(2);
66 |
67 | return format;
68 | }
69 |
70 | });
71 | */
72 |
73 | // show grand totals
74 | pivotModel.setShowGrandTotalForColumn(true);
75 | pivotModel.setShowGrandTotalForRow(true);
76 |
77 | return pivotModel;
78 | }
79 |
80 | };
81 | pivotPanel.setPivotConfigStorage(new PivotConfigSessionStorage());
82 | add(pivotPanel);
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/res/jquery.dropdown.css:
--------------------------------------------------------------------------------
1 | .jquery-dropdown {
2 | position: absolute;
3 | z-index: 9999999;
4 | display: none;
5 | }
6 |
7 | .jquery-dropdown .jquery-dropdown-menu,
8 | .jquery-dropdown .dropdown-panel {
9 | min-width: 160px;
10 | max-width: 360px;
11 | list-style: none;
12 | background: #FFF;
13 | border: solid 1px #DDD;
14 | border: solid 1px rgba(0, 0, 0, .2);
15 | border-radius: 6px;
16 | box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
17 | overflow: visible;
18 | padding: 4px 0;
19 | margin: 0;
20 | text-shadow: none;
21 | font-size: 13px;
22 | font-weight: normal;
23 | }
24 |
25 | .jquery-dropdown .dropdown-panel {
26 | padding: 10px;
27 | }
28 |
29 | .jquery-dropdown.dropdown-tip {
30 | margin-top: 8px;
31 | }
32 |
33 | .jquery-dropdown.dropdown-tip:before {
34 | position: absolute;
35 | top: -6px;
36 | left: 9px;
37 | content: '';
38 | border-left: 7px solid transparent;
39 | border-right: 7px solid transparent;
40 | border-bottom: 7px solid #CCC;
41 | border-bottom-color: rgba(0, 0, 0, 0.2);
42 | display: inline-block;
43 | }
44 |
45 | .jquery-dropdown.dropdown-tip.dropdown-anchor-right:before {
46 | left: auto;
47 | right: 9px;
48 | }
49 |
50 | .jquery-dropdown.dropdown-tip:after {
51 | position: absolute;
52 | top: -5px;
53 | left: 10px;
54 | content: '';
55 | border-left: 6px solid transparent;
56 | border-right: 6px solid transparent;
57 | border-bottom: 6px solid #FFF;
58 | display: inline-block;
59 | }
60 |
61 | .jquery-dropdown.dropdown-tip.dropdown-anchor-right:after {
62 | left: auto;
63 | right: 10px;
64 | }
65 |
66 |
67 | .jquery-dropdown.dropdown-scroll .jquery-dropdown-menu,
68 | .jquery-dropdown.dropdown-scroll .dropdown-panel {
69 | max-height: 358px;
70 | overflow: auto;
71 | }
72 |
73 | .jquery-dropdown .jquery-dropdown-menu LI {
74 | list-style: none;
75 | padding: 0 0;
76 | margin: 0;
77 | line-height: 18px;
78 | }
79 |
80 | .jquery-dropdown .jquery-dropdown-menu LI > A,
81 | .jquery-dropdown .jquery-dropdown-menu LABEL {
82 | display: block;
83 | color: #555;
84 | text-decoration: none;
85 | line-height: 18px;
86 | padding: 3px 15px;
87 | white-space: nowrap;
88 | }
89 |
90 | .jquery-dropdown .jquery-dropdown-menu LI > A:hover,
91 | .jquery-dropdown .jquery-dropdown-menu LABEL:hover {
92 | background-color: #08C;
93 | color: #FFF;
94 | cursor: pointer;
95 | }
96 |
97 | .jquery-dropdown .jquery-dropdown-menu .dropdown-divider {
98 | font-size: 1px;
99 | border-top: solid 1px #E5E5E5;
100 | padding: 0;
101 | margin: 5px 0;
102 | }
103 |
104 | /* Icon Examples - icons courtesy of http://p.yusukekamiyamane.com/ */
105 | .jquery-dropdown.has-icons LI > A {
106 | padding-left: 30px;
107 | background-position: 8px center;
108 | background-repeat: no-repeat;
109 | }
110 |
111 | .jquery-dropdown .undo A { background-image: url(icons/arrow-curve-180-left.png); }
112 | .jquery-dropdown .redo A { background-image: url(icons/arrow-curve.png); }
113 | .jquery-dropdown .cut A { background-image: url(icons/scissors.png); }
114 | .jquery-dropdown .copy A { background-image: url(icons/document-copy.png); }
115 | .jquery-dropdown .paste A { background-image: url(icons/clipboard.png); }
116 | .jquery-dropdown .delete A { background-image: url(icons/cross-script.png); }
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/exporter/PivotCsvExporter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.exporter;
14 |
15 | import java.io.IOException;
16 | import java.io.OutputStream;
17 | import java.io.OutputStreamWriter;
18 | import java.nio.charset.Charset;
19 | import java.util.HashMap;
20 | import java.util.Map;
21 |
22 | import ro.fortsoft.wicket.pivot.PivotModel;
23 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel;
24 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.RenderCell;
25 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.RenderRow;
26 |
27 | /**
28 | * Basic CSV exporter
29 | */
30 | public class PivotCsvExporter implements PivotExporter {
31 | private static final long serialVersionUID = 1L;
32 | private String seperator = ";";
33 |
34 | @Override
35 | public void exportPivot(PivotModel pivotModel, OutputStream outputStream) throws IOException {
36 | PivotTableRenderModel renderModel = PivotTableRenderModel.create(pivotModel);
37 |
38 | OutputStreamWriter out = new OutputStreamWriter(outputStream, Charset.forName("UTF-8"));
39 | Map rowSpanMap = new HashMap<>();
40 |
41 | for (RenderRow row : renderModel.getAllRenderRows()) {
42 | int col = 0;
43 | for (RenderCell cell : row.getRenderCells()) {
44 | /*
45 | * Check if we currently have a rowspan at this column from the
46 | * parent row. We only support a colspan of 1 at the moment
47 | * here, if rowspan > 1
48 | */
49 | Integer rowSpan = rowSpanMap.get(col);
50 | if (rowSpan != null) {
51 | rowSpan--;
52 | if (rowSpan == 0)
53 | rowSpanMap.remove(col);
54 | else
55 | rowSpanMap.put(col, rowSpan);
56 | col++;
57 | out.append(seperator);
58 | }
59 |
60 | /*
61 | * Output the Value
62 | */
63 | Object rawValue = cell.getRawValue();
64 | if (rawValue != null)
65 | out.append(String.valueOf(rawValue));
66 | out.append(seperator);
67 | if (cell.getRowspan() > 1)
68 | rowSpanMap.put(col, cell.getRowspan() - 1);
69 | col++;
70 |
71 | /*
72 | * We only support colspan _OR_ rowspan. The current PivotTable
73 | * also doesnt have rowspan and colspan at the same time.
74 | */
75 | for (int i = 1; i < cell.getColspan(); i++) {
76 | out.append(seperator);
77 | col++;
78 | }
79 | }
80 | out.append("\n");
81 | }
82 | out.flush();
83 | }
84 |
85 | public void setSeperator(String seperator) {
86 | this.seperator = seperator;
87 | }
88 |
89 | @Override
90 | public String getFormatName() {
91 | return "CSV";
92 | }
93 |
94 | @Override
95 | public String getFormatMimetype() {
96 | return "text/csv";
97 | }
98 |
99 | @Override
100 | public String getFilenameExtension() {
101 | return ".csv";
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/AggregatorPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | import org.apache.wicket.ajax.AjaxRequestTarget;
19 | import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
20 | import org.apache.wicket.ajax.markup.html.AjaxLink;
21 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
22 | import org.apache.wicket.markup.html.form.ChoiceRenderer;
23 | import org.apache.wicket.markup.html.form.DropDownChoice;
24 | import org.apache.wicket.markup.html.panel.GenericPanel;
25 | import org.apache.wicket.model.IModel;
26 | import org.apache.wicket.model.PropertyModel;
27 |
28 | import ro.fortsoft.wicket.pivot.Aggregator;
29 | import ro.fortsoft.wicket.pivot.PivotField;
30 |
31 | /**
32 | * @author Decebal Suiu
33 | */
34 | public class AggregatorPanel extends GenericPanel {
35 |
36 | private static final long serialVersionUID = 1L;
37 |
38 | private Aggregator aggregator;
39 | private boolean okPressed;
40 |
41 | public AggregatorPanel(String id, IModel model) {
42 | super(id, model);
43 |
44 | okPressed = false;
45 |
46 | aggregator = getModelObject().getAggregator();
47 |
48 | List aggregators = new ArrayList<>();
49 | aggregators.add(Aggregator.get(Aggregator.SUM));
50 | aggregators.add(Aggregator.get(Aggregator.AVG));
51 | aggregators.add(Aggregator.get(Aggregator.MIN));
52 | aggregators.add(Aggregator.get(Aggregator.MAX));
53 | aggregators.add(Aggregator.get(Aggregator.COUNT));
54 | final DropDownChoice aggregatorDownChoice = new DropDownChoice<>("aggregator",
55 | new PropertyModel<>(this, "aggregator"), aggregators,
56 | new ChoiceRenderer("function") {
57 |
58 | private static final long serialVersionUID = 1L;
59 |
60 | @Override
61 | public Object getDisplayValue(Aggregator object) {
62 | return ((String) super.getDisplayValue(object)).toUpperCase();
63 | }
64 |
65 | });
66 | aggregatorDownChoice.add(new OnChangeAjaxBehavior() {
67 |
68 | private static final long serialVersionUID = 1L;
69 |
70 | @Override
71 | protected void onUpdate(AjaxRequestTarget target) {
72 | }
73 |
74 | });
75 | aggregatorDownChoice.setOutputMarkupId(true);
76 | add(aggregatorDownChoice);
77 |
78 | add(new AjaxLink("ok") {
79 |
80 | private static final long serialVersionUID = 1L;
81 |
82 | @Override
83 | public void onClick(AjaxRequestTarget target) {
84 | okPressed = true;
85 | ModalWindow.closeCurrent(target);
86 |
87 | }
88 |
89 | });
90 | }
91 |
92 | public boolean isOkPressed() {
93 | return okPressed;
94 | }
95 |
96 | public Aggregator getAggregator() {
97 | return aggregator;
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotConfigStoragePanel.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.wicket.pivot.web;
2 |
3 | import org.apache.wicket.ajax.AjaxRequestTarget;
4 | import org.apache.wicket.ajax.markup.html.AjaxLink;
5 | import org.apache.wicket.ajax.markup.html.form.AjaxButton;
6 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
7 | import org.apache.wicket.markup.html.basic.Label;
8 | import org.apache.wicket.markup.html.form.Form;
9 | import org.apache.wicket.markup.html.form.TextField;
10 | import org.apache.wicket.markup.html.list.ListItem;
11 | import org.apache.wicket.markup.html.list.ListView;
12 | import org.apache.wicket.markup.html.panel.Panel;
13 | import org.apache.wicket.model.Model;
14 | import ro.fortsoft.wicket.pivot.PivotModel;
15 | import ro.fortsoft.wicket.pivot.config.IPivotConfigStorage;
16 | import ro.fortsoft.wicket.pivot.config.PivotConfig;
17 |
18 | import java.util.ArrayList;
19 |
20 | public class PivotConfigStoragePanel extends Panel {
21 | private static final long serialVersionUID = 1L;
22 | private IPivotConfigStorage pivotConfigStorage;
23 | private Model> configNameModel;
24 | private ListView configListView;
25 |
26 | public PivotConfigStoragePanel(String id, final PivotModel pivotModel, final IPivotConfigStorage pivotConfigStorage) {
27 | super(id);
28 | this.pivotConfigStorage = pivotConfigStorage;
29 |
30 | Form form = new Form<>("form");
31 | final TextField configStoreName = new TextField<>("configStoreName", new Model<>(""));
32 | form.add(configStoreName);
33 |
34 | AjaxButton saveButton = new AjaxButton("save") {
35 | private static final long serialVersionUID = 1L;
36 |
37 | @Override
38 | protected void onSubmit(AjaxRequestTarget target) {
39 | String value = configStoreName.getValue();
40 | if (value == null || value.isEmpty())
41 | return;
42 | PivotConfig config = new PivotConfig();
43 | config.setName(value);
44 | config.storeModelState(pivotModel);
45 | pivotConfigStorage.saveConfig(config);
46 | ModalWindow.closeCurrent(target);
47 | }
48 | };
49 | form.add(saveButton);
50 | add(form);
51 |
52 | configNameModel = new Model<>();
53 | configListView = new ListView("configs", configNameModel) {
54 | private static final long serialVersionUID = 1L;
55 |
56 | @Override
57 | protected void populateItem(final ListItem item) {
58 | item.add(new Label("name", new Model<>(item.getModelObject())));
59 | item.add(new AjaxLink("load") {
60 | private static final long serialVersionUID = 1L;
61 |
62 | @Override
63 | public void onClick(AjaxRequestTarget target) {
64 | PivotConfig config = pivotConfigStorage.loadConfig(item.getModelObject());
65 | if (config == null) {
66 | refreshList(target);
67 | return;
68 | }
69 | config.restoreModelState(pivotModel);
70 | ModalWindow.closeCurrent(target);
71 | }
72 | });
73 | item.add(new AjaxLink("delete") {
74 | private static final long serialVersionUID = 1L;
75 |
76 | @Override
77 | public void onClick(AjaxRequestTarget target) {
78 | pivotConfigStorage.deleteConfig(item.getModelObject());
79 | refreshList(target);
80 | }
81 | });
82 | }
83 | };
84 | setOutputMarkupId(true);
85 | add(configListView);
86 | refreshList(null);
87 | }
88 |
89 | private void refreshList(AjaxRequestTarget target) {
90 | configNameModel.setObject(new ArrayList<>(pivotConfigStorage.listConfigNames()));
91 | if (target != null)
92 | target.add(this);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/ResultSetPivotDataSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.sql.ResultSet;
16 | import java.sql.ResultSetMetaData;
17 | import java.sql.SQLException;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | /**
22 | * @author Decebal Suiu
23 | */
24 | public class ResultSetPivotDataSource implements PivotDataSource {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | private List> data;
29 | private List columnNames;
30 | private List> columnTypes;
31 | private int rowCount;
32 | private int columnCount;
33 |
34 | public ResultSetPivotDataSource(ResultSet resultSet) throws SQLException {
35 | data = new ArrayList<>();
36 | columnNames = new ArrayList<>();
37 | columnTypes = new ArrayList<>();
38 |
39 | populate(resultSet);
40 | }
41 |
42 | @Override
43 | public String getFieldName(int fieldIndex) {
44 | return columnNames.get(fieldIndex);
45 | }
46 |
47 | @Override
48 | public int getFieldIndex(String fieldName) {
49 | for (int i = 0; i < columnNames.size(); i++) {
50 | if (columnNames.get(i).equals(fieldName)) {
51 | return i;
52 | }
53 | }
54 |
55 | return -1;
56 | }
57 |
58 | @Override
59 | public Class> getFieldType(int fieldIndex) {
60 | return columnTypes.get(fieldIndex);
61 | }
62 |
63 | @Override
64 | public int getFieldCount() {
65 | return columnCount;
66 | }
67 |
68 | @Override
69 | public int getRowCount() {
70 | return rowCount;
71 | }
72 |
73 | @Override
74 | public Object getValueAt(int rowIndex, int fieldIndex) {
75 | return data.get(rowIndex).get(fieldIndex);
76 | }
77 |
78 | @Override
79 | public Object getValueAt(int rowIndex, PivotField field) {
80 | int fieldIndex = getFieldIndex(field.getName());
81 | return data.get(rowIndex).get(fieldIndex);
82 | }
83 |
84 | private void populate(ResultSet resultSet) throws SQLException {
85 | boolean firstRow = true;
86 | while (resultSet.next()) {
87 | if (firstRow) {
88 | firstRow = false;
89 | ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
90 | columnCount = resultSetMetaData.getColumnCount();
91 | for (int i = 0; i < columnCount; i++) {
92 | columnNames.add(resultSetMetaData.getColumnLabel(i + 1));
93 | try {
94 | columnTypes.add(Class.forName(resultSetMetaData.getColumnClassName(i + 1)));
95 | } catch (ClassNotFoundException e) {
96 | // TODO Auto-generated catch block
97 | e.printStackTrace();
98 | }
99 | }
100 | // System.out.println(columnNames);
101 | // System.out.println(columnTypes);
102 | }
103 |
104 | List row = new ArrayList<>(columnCount);
105 | for (int i = 0; i < columnCount; i++) {
106 | row.add(resultSet.getObject(i + 1));
107 | }
108 | data.add(row);
109 |
110 | rowCount++;
111 | }
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/tree/Node.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.tree;
14 |
15 | import java.io.Serializable;
16 | import java.util.ArrayList;
17 | import java.util.Collections;
18 | import java.util.List;
19 |
20 | /**
21 | * @author Decebal Suiu
22 | */
23 | public class Node implements Serializable {
24 |
25 | private static final long serialVersionUID = 1L;
26 |
27 | private Node parent;
28 | private Object data;
29 | private List children;
30 |
31 | public Node() {
32 | children = new ArrayList<>();
33 | }
34 |
35 | public Node(Object data) {
36 | this.data = data;
37 | children = new ArrayList<>();
38 | }
39 |
40 | public Node getParent() {
41 | return parent;
42 | }
43 |
44 | public boolean isRoot() {
45 | return parent == null;
46 | }
47 |
48 | public int getLevel() {
49 | int level = 0;
50 | Node p = parent;
51 | while (p != null) {
52 | ++level;
53 | p = p.parent;
54 | }
55 |
56 | return level;
57 | }
58 |
59 | public boolean isLeaf() {
60 | return children.isEmpty();
61 | }
62 |
63 | public Object getData() {
64 | return data;
65 | }
66 |
67 | public void setData(Object data) {
68 | this.data = data;
69 | }
70 |
71 | public List getChildren() {
72 | // return new ArrayList(children); /* return a shallow copy */
73 | return children;
74 | }
75 |
76 | public void addChild(Node child) {
77 | child.parent = this;
78 | children.add(child);
79 | }
80 |
81 | public void insert(Object data) {
82 | addChild(new Node(data));
83 | }
84 |
85 | public List getPathValues() {
86 | if (isRoot()) {
87 | return Collections.emptyList();
88 | }
89 |
90 | List pathValues = new ArrayList<>();
91 | pathValues.add(getData());
92 | Node parent = getParent();
93 | while (parent != null) {
94 | pathValues.add(parent.getData());
95 | parent = parent.getParent();
96 | }
97 | pathValues.remove(pathValues.size() - 1); // remove root
98 | Collections.reverse(pathValues);
99 |
100 | return pathValues;
101 | }
102 |
103 | @Override
104 | public int hashCode() {
105 | final int prime = 31;
106 | int result = 1;
107 | result = prime * result + ((data == null) ? 0 : data.hashCode());
108 | return result;
109 | }
110 |
111 | @Override
112 | public boolean equals(Object obj) {
113 | if (this == obj) {
114 | return true;
115 | }
116 |
117 | if (obj == null) {
118 | return false;
119 | }
120 |
121 | if (getClass() != obj.getClass()) {
122 | return false;
123 | }
124 |
125 | Node other = (Node) obj;
126 | if (data == null) {
127 | if (other.data != null) {
128 | return false;
129 | }
130 | } else if (!data.equals(other.data)) {
131 | return false;
132 | }
133 |
134 | return true;
135 | }
136 |
137 | @Override
138 | public String toString() {
139 | return (data == null) ? "null" : data.toString();
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotFieldActionsPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import java.util.List;
16 |
17 | import org.apache.wicket.markup.head.CssHeaderItem;
18 | import org.apache.wicket.markup.head.IHeaderResponse;
19 | import org.apache.wicket.markup.head.JavaScriptHeaderItem;
20 | import org.apache.wicket.markup.html.WebMarkupContainer;
21 | import org.apache.wicket.markup.html.basic.Label;
22 | import org.apache.wicket.markup.html.link.AbstractLink;
23 | import org.apache.wicket.markup.html.list.ListItem;
24 | import org.apache.wicket.markup.html.list.ListView;
25 | import org.apache.wicket.markup.html.panel.GenericPanel;
26 | import org.apache.wicket.model.IModel;
27 | import org.apache.wicket.model.LoadableDetachableModel;
28 | import org.apache.wicket.request.resource.PackageResourceReference;
29 | import org.apache.wicket.resource.JQueryPluginResourceReference;
30 |
31 | import ro.fortsoft.wicket.pivot.PivotField;
32 | import ro.fortsoft.wicket.pivot.PivotFieldAction;
33 | import ro.fortsoft.wicket.pivot.PivotModel;
34 |
35 | /**
36 | * @author Decebal Suiu
37 | */
38 | public class PivotFieldActionsPanel extends GenericPanel {
39 |
40 | private static final long serialVersionUID = 1L;
41 |
42 | private IModel> actionsModel;
43 |
44 |
45 | public PivotFieldActionsPanel(String id, IModel model, final IModel pivotModel) {
46 | super(id, model);
47 |
48 | WebMarkupContainer dropDownContainer = new WebMarkupContainer("dropdown");
49 | dropDownContainer.setOutputMarkupId(true);
50 | add(dropDownContainer);
51 |
52 | actionsModel = new LoadableDetachableModel>() {
53 |
54 | private static final long serialVersionUID = 1L;
55 |
56 | @Override
57 | protected List load() {
58 | PivotPanel pivotPanel = findParent(PivotPanel.class);
59 | return pivotPanel.getPivotFieldActionsFactory().createPivotFieldActions(getPivotField(), pivotModel.getObject());
60 | }
61 |
62 | };
63 | ListView actionsView = new ListView("action", actionsModel) {
64 |
65 | private static final long serialVersionUID = 1L;
66 |
67 | @Override
68 | protected void populateItem(ListItem item) {
69 | PivotFieldAction action = item.getModelObject();
70 | AbstractLink link = action.getLink("link");
71 | // link.add(new Image("image", action.getImage()));
72 | // link.add(AttributeModifier.replace("title", action.getTooltip()));
73 | link.add(new Label("name", action.getName()));
74 | item.add(link);
75 | }
76 |
77 | };
78 | dropDownContainer.add(actionsView);
79 | }
80 |
81 | @Override
82 | protected void onInitialize() {
83 | super.onInitialize();
84 |
85 | setVisible(!actionsModel.getObject().isEmpty());
86 | }
87 |
88 | @Override
89 | public void renderHead(IHeaderResponse response) {
90 | super.renderHead(response);
91 |
92 | response.render(JavaScriptHeaderItem.forReference(new JQueryPluginResourceReference(PivotAreaPanel.class, "res/jquery.dropdown.js")));
93 | response.render(CssHeaderItem.forReference(new PackageResourceReference(PivotAreaPanel.class, "res/jquery.dropdown.css")));
94 | }
95 |
96 | private PivotField getPivotField() {
97 | return getModelObject();
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ro.fortsoft.wicket.pivot
6 | wicket-pivot-parent
7 | 0.6.0-SNAPHOT
8 |
9 |
10 | 4.0.0
11 | wicket-pivot-demo
12 | 0.6.0-SNAPHOT
13 | war
14 | Wicket Pivot Demo
15 |
16 |
17 | 8.1.16.v20140903
18 | 1.6.4
19 | 1.2.16
20 |
21 |
22 |
23 |
24 |
25 | org.mortbay.jetty
26 | jetty-maven-plugin
27 | ${jetty.version}
28 |
29 |
30 |
31 | 8081
32 | 3600000
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-war-plugin
41 | 2.1.1
42 |
43 | root
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | ro.fortsoft.wicket.pivot
53 | wicket-pivot
54 | ${project.version}
55 |
56 |
57 | ro.fortsoft.wicket.pivot
58 | wicket-pivot-exporter
59 | ${project.version}
60 |
61 |
62 |
63 |
64 | org.apache.derby
65 | derby
66 | 10.9.1.0
67 |
68 |
69 |
70 |
71 | log4j
72 | log4j
73 | ${log4j.version}
74 |
75 |
76 |
77 | org.slf4j
78 | slf4j-api
79 | ${slf4j.version}
80 |
81 |
82 |
83 | org.slf4j
84 | slf4j-log4j12
85 | ${slf4j.version}
86 |
87 |
88 |
89 | com.google.code.gson
90 | gson
91 | 2.8.9
92 |
93 |
94 |
95 |
96 | junit
97 | junit
98 | 4.13.1
99 | test
100 |
101 |
102 |
103 |
104 | org.eclipse.jetty.aggregate
105 | jetty-all-server
106 | ${jetty.version}
107 | test
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/res/jquery.dropdown.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery dropdown: A simple dropdown plugin
3 | *
4 | * Inspired by Bootstrap: http://twitter.github.com/bootstrap/javascript.html#dropdowns
5 | *
6 | * Copyright 2013 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/)
7 | *
8 | * Dual licensed under the MIT / GPL Version 2 licenses
9 | *
10 | */
11 | if (jQuery) (function ($) {
12 |
13 | $.extend($.fn, {
14 | dropdown: function (method, data) {
15 |
16 | switch (method) {
17 | case 'show':
18 | show(null, $(this));
19 | return $(this);
20 | case 'hide':
21 | hide();
22 | return $(this);
23 | case 'attach':
24 | return $(this).attr('data-dropdown', data);
25 | case 'detach':
26 | hide();
27 | return $(this).removeAttr('data-dropdown');
28 | case 'disable':
29 | return $(this).addClass('dropdown-disabled');
30 | case 'enable':
31 | hide();
32 | return $(this).removeClass('dropdown-disabled');
33 | }
34 |
35 | }
36 | });
37 |
38 | function show(event, object) {
39 |
40 | var trigger = event ? $(this) : object,
41 | dropdown = $(trigger.attr('data-dropdown')),
42 | isOpen = trigger.hasClass('dropdown-open');
43 |
44 | // In some cases we don't want to show it
45 | if (event) {
46 | if ($(event.target).hasClass('dropdown-ignore')) return;
47 |
48 | event.preventDefault();
49 | event.stopPropagation();
50 | } else {
51 | if (trigger !== object.target && $(object.target).hasClass('dropdown-ignore')) return;
52 | }
53 | hide();
54 |
55 | if (isOpen || trigger.hasClass('dropdown-disabled')) return;
56 |
57 | // Show it
58 | trigger.addClass('dropdown-open');
59 | dropdown
60 | .data('dropdown-trigger', trigger)
61 | .show();
62 |
63 | // Position it
64 | position();
65 |
66 | // Trigger the show callback
67 | dropdown
68 | .trigger('show', {
69 | dropdown: dropdown,
70 | trigger: trigger
71 | });
72 |
73 | }
74 |
75 | function hide(event) {
76 |
77 | // In some cases we don't hide them
78 | var targetGroup = event ? $(event.target).parents().addBack() : null;
79 |
80 | // Are we clicking anywhere in a dropdown?
81 | if (targetGroup && targetGroup.is('.jquery-dropdown')) {
82 | // Is it a dropdown menu?
83 | if (targetGroup.is('.jquery-dropdown-menu')) {
84 | // Did we click on an option? If so close it.
85 | if (!targetGroup.is('A')) return;
86 | } else {
87 | // Nope, it's a panel. Leave it open.
88 | return;
89 | }
90 | }
91 |
92 | // Hide any dropdown that may be showing
93 | $(document).find('.jquery-dropdown:visible').each(function () {
94 | var dropdown = $(this);
95 | dropdown
96 | .hide()
97 | .removeData('dropdown-trigger')
98 | .trigger('hide', { dropdown: dropdown });
99 | });
100 |
101 | // Remove all dropdown-open classes
102 | $(document).find('.dropdown-open').removeClass('dropdown-open');
103 |
104 | }
105 |
106 | function position() {
107 |
108 | var dropdown = $('.jquery-dropdown:visible').eq(0),
109 | trigger = dropdown.data('dropdown-trigger'),
110 | hOffset = trigger ? parseInt(trigger.attr('data-horizontal-offset') || 0, 10) : null,
111 | vOffset = trigger ? parseInt(trigger.attr('data-vertical-offset') || 0, 10) : null;
112 |
113 | if (dropdown.length === 0 || !trigger) return;
114 |
115 | // Position the dropdown relative-to-parent...
116 | if (dropdown.hasClass('dropdown-relative')) {
117 | dropdown.css({
118 | left: dropdown.hasClass('dropdown-anchor-right') ?
119 | trigger.position().left - (dropdown.outerWidth(true) - trigger.outerWidth(true)) - parseInt(trigger.css('margin-right')) + hOffset :
120 | trigger.position().left + parseInt(trigger.css('margin-left')) + hOffset,
121 | top: trigger.position().top + trigger.outerHeight(true) - parseInt(trigger.css('margin-top')) + vOffset
122 | });
123 | } else {
124 | // ...or relative to document
125 | dropdown.css({
126 | left: dropdown.hasClass('dropdown-anchor-right') ?
127 | trigger.offset().left - (dropdown.outerWidth() - trigger.outerWidth()) + hOffset : trigger.offset().left + hOffset,
128 | top: trigger.offset().top + trigger.outerHeight() + vOffset
129 | });
130 | }
131 | }
132 |
133 | $(document).on('click.dropdown', '[data-dropdown]', show);
134 | $(document).on('click.dropdown', hide);
135 | $(window).on('resize', position);
136 |
137 | })(jQuery);
138 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/PivotField.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | import org.apache.wicket.util.convert.IConverter;
20 |
21 | /**
22 | * @author Decebal Suiu
23 | */
24 | public class PivotField implements Serializable, Comparable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | public static final int SORT_ORDER_UNSORTED = 0;
29 | public static final int SORT_ORDER_ASCENDING = 1;
30 | public static final int SORT_ORDER_DESCENDING = 2;
31 |
32 | private String name;
33 | private String title;
34 | private Area area;
35 | private int index;
36 | private int areaIndex;
37 | private Class> type;
38 | private Aggregator aggregator;
39 | private FieldCalculation fieldCalculation;
40 | private IConverter> converter;
41 | private int sortOrder;
42 |
43 | public PivotField(String name, int index) {
44 | this.name = name;
45 | this.index = index;
46 |
47 | sortOrder = SORT_ORDER_ASCENDING;
48 | aggregator = Aggregator.get(Aggregator.SUM);
49 | }
50 |
51 | public String getName() {
52 | return name;
53 | }
54 |
55 | public int getIndex() {
56 | return index;
57 | }
58 |
59 | public String getTitle() {
60 | return title;
61 | }
62 |
63 | public PivotField setTitle(String title) {
64 | this.title = title;
65 | return this;
66 | }
67 |
68 | public Area getArea() {
69 | return area;
70 | }
71 |
72 | public PivotField setArea(Area area) {
73 | this.area = area;
74 | return this;
75 | }
76 |
77 | public int getAreaIndex() {
78 | return areaIndex;
79 | }
80 |
81 | public PivotField setAreaIndex(int areaIndex) {
82 | this.areaIndex = areaIndex;
83 | return this;
84 | }
85 |
86 | public Class> getType() {
87 | return type;
88 | }
89 |
90 | public PivotField setType(Class> valueType) {
91 | this.type = valueType;
92 | return this;
93 | }
94 |
95 | public String getCalculationDescription() {
96 | if( getFieldCalculation() != null)
97 | return getFieldCalculation().getDescription();
98 | return getAggregator().getFunction().toUpperCase();
99 | }
100 |
101 | public Aggregator getAggregator() {
102 | return aggregator;
103 | }
104 |
105 | public void setAggregator(Aggregator aggregator) {
106 | this.aggregator = aggregator;
107 | }
108 |
109 | public boolean isNumber() {
110 | return Number.class.isAssignableFrom(type);
111 | }
112 |
113 | public IConverter> getConverter() {
114 | return converter;
115 | }
116 |
117 | public void setConverter(IConverter> converter) {
118 | this.converter = converter;
119 | }
120 |
121 | public int getSortOrder() {
122 | return sortOrder;
123 | }
124 |
125 | public void setSortOrder(int sortOrder) {
126 | this.sortOrder = sortOrder;
127 | }
128 |
129 | @Override
130 | public int compareTo(PivotField o) {
131 | return areaIndex - o.areaIndex;
132 | }
133 |
134 | @Override
135 | public String toString() {
136 | return "PivotField [name=" + name + ", title=" + title + ", area="
137 | + area + ", index=" + index + ", areaIndex=" + areaIndex + "]";
138 | }
139 |
140 | /**
141 | *Area of pivot field, which indicates whether the field is a column field, row field, or data field.
142 | */
143 | public enum Area {
144 |
145 | ROW("row"),
146 | COLUMN("column"),
147 | DATA("data"),
148 | UNUSED("unused");
149 |
150 | private String name;
151 |
152 | private Area(String name) {
153 | this.name = name;
154 | }
155 |
156 | public String getName() {
157 | return name;
158 | }
159 |
160 | public static List getValues() {
161 | List values = new ArrayList<>();
162 | values.add(ROW);
163 | values.add(COLUMN);
164 | values.add(DATA);
165 | values.add(UNUSED);
166 |
167 | return values;
168 | }
169 |
170 | public static Area getValue(String name) {
171 | for (Area area : getValues()) {
172 | if (area.name.equals(name)) {
173 | return area;
174 | }
175 | }
176 |
177 | return null;
178 | }
179 |
180 | }
181 |
182 | /**
183 | * @internal Reset the calculation state
184 | */
185 | void resetCalculation() {
186 | if (getAggregator() != null)
187 | getAggregator().init();
188 | if (getFieldCalculation() != null)
189 | getFieldCalculation().init();
190 | }
191 |
192 | public FieldCalculation getFieldCalculation() {
193 | return fieldCalculation;
194 | }
195 |
196 | public void setFieldCalculation(FieldCalculation fieldCalculation) {
197 | this.fieldCalculation = fieldCalculation;
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/FieldCalculationPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import org.apache.wicket.ajax.AjaxRequestTarget;
16 | import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
17 | import org.apache.wicket.ajax.markup.html.AjaxLink;
18 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
19 | import org.apache.wicket.markup.html.form.ChoiceRenderer;
20 | import org.apache.wicket.markup.html.form.DropDownChoice;
21 | import org.apache.wicket.markup.html.form.TextField;
22 | import org.apache.wicket.markup.html.panel.GenericPanel;
23 | import org.apache.wicket.model.IModel;
24 | import org.apache.wicket.model.PropertyModel;
25 | import ro.fortsoft.wicket.pivot.FieldCalculation;
26 | import ro.fortsoft.wicket.pivot.PivotField;
27 | import ro.fortsoft.wicket.pivot.PivotModel;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 |
32 | public class FieldCalculationPanel extends GenericPanel {
33 | private final static class OnChangeAjaxBehaviorExtension extends OnChangeAjaxBehavior {
34 | private static final long serialVersionUID = 1L;
35 |
36 | @Override
37 | protected void onUpdate(AjaxRequestTarget target) {
38 | // We just want the field content to be pushed to the server
39 | }
40 | }
41 |
42 | private static final class PivotFieldChoiceRenderer extends ChoiceRenderer {
43 | private static final long serialVersionUID = 1L;
44 |
45 | @Override
46 | public Object getDisplayValue(PivotField object) {
47 | return object.getTitle() + " (" + object.getCalculationDescription() + ")";
48 | }
49 | }
50 |
51 | private static final long serialVersionUID = 1L;
52 |
53 | private FieldCalculation fieldCalculation;
54 | private PivotField fieldA;
55 | private PivotField fieldB;
56 | private String title = "Calculation";
57 | private boolean okPressed;
58 |
59 | public FieldCalculationPanel(String id, IModel model, IModel pivotModel) {
60 | super(id, model);
61 |
62 | okPressed = false;
63 |
64 | setFieldCalculation(getModelObject().getFieldCalculation());
65 | if (fieldCalculation != null) {
66 | fieldA = fieldCalculation.getFieldA();
67 | fieldB = fieldCalculation.getFieldB();
68 | }
69 | List fieldCalculations = new ArrayList<>();
70 | for (String name : FieldCalculation.FUNCTIONS)
71 | fieldCalculations.add(FieldCalculation.get(name));
72 |
73 | final DropDownChoice fieldCalculationDropDown = new DropDownChoice<>(
74 | "fieldCalcluation", new PropertyModel<>(this, "fieldCalculation"), fieldCalculations,
75 | new ChoiceRenderer("function") {
76 | private static final long serialVersionUID = 1L;
77 |
78 | @Override
79 | public Object getDisplayValue(FieldCalculation object) {
80 | return object == null ? "" : object.getDescription();
81 | }
82 | });
83 | fieldCalculationDropDown.setOutputMarkupId(true);
84 | fieldCalculationDropDown.add(new OnChangeAjaxBehaviorExtension());
85 | add(fieldCalculationDropDown);
86 |
87 | List fields = new ArrayList<>();
88 | for (PivotField field : pivotModel.getObject().getFields()) {
89 | if (field.getAggregator() != null && field.getFieldCalculation() == null && field.isNumber())
90 | fields.add(field);
91 | }
92 | final DropDownChoice fieldADropDown = new DropDownChoice<>("fieldA",
93 | new PropertyModel<>(this, "fieldA"), fields, new PivotFieldChoiceRenderer());
94 | fieldADropDown.setOutputMarkupId(true);
95 | fieldADropDown.add(new OnChangeAjaxBehaviorExtension());
96 | add(fieldADropDown);
97 |
98 | final DropDownChoice fieldBDropDown = new DropDownChoice<>("fieldB",
99 | new PropertyModel<>(this, "fieldB"), fields, new PivotFieldChoiceRenderer());
100 | fieldBDropDown.setOutputMarkupId(true);
101 | fieldBDropDown.add(new OnChangeAjaxBehaviorExtension());
102 | add(fieldBDropDown);
103 |
104 | add(new TextField<>("title", new PropertyModel<>(this, "title"))
105 | .add(new OnChangeAjaxBehaviorExtension()));
106 |
107 | add(new AjaxLink("ok") {
108 | private static final long serialVersionUID = 1L;
109 |
110 | @Override
111 | public void onClick(AjaxRequestTarget target) {
112 | if (fieldCalculation != null) {
113 | okPressed = true;
114 | fieldCalculation.setFieldA(fieldA);
115 | fieldCalculation.setFieldB(fieldB);
116 | }
117 | ModalWindow.closeCurrent(target);
118 | }
119 | });
120 | }
121 |
122 | public boolean isOkPressed() {
123 | return okPressed;
124 | }
125 |
126 | public FieldCalculation getFieldCalculation() {
127 | return fieldCalculation;
128 | }
129 |
130 | public void setFieldCalculation(FieldCalculation fieldCalculation) {
131 | this.fieldCalculation = fieldCalculation;
132 | }
133 |
134 | public PivotField getFieldA() {
135 | return fieldA;
136 | }
137 |
138 | public void setFieldA(PivotField fieldA) {
139 | this.fieldA = fieldA;
140 | }
141 |
142 | public PivotField getFieldB() {
143 | return fieldB;
144 | }
145 |
146 | public void setFieldB(PivotField fieldB) {
147 | this.fieldB = fieldB;
148 | }
149 |
150 | public String getTitle() {
151 | return title;
152 | }
153 |
154 | public void setTitle(String title) {
155 | this.title = title;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | org.sonatype.oss
6 | oss-parent
7 | 7
8 |
9 |
10 | 4.0.0
11 | ro.fortsoft.wicket.pivot
12 | wicket-pivot-parent
13 | 0.6.0-SNAPHOT
14 | pom
15 | Wicket Pivot Parent
16 | Simple web pivot table using Apache Wicket
17 |
18 |
19 |
20 | The Apache Software License, Version 2.0
21 | http://www.apache.org/licenses/LICENSE-2.0.txt
22 | repo
23 |
24 |
25 |
26 |
27 | scm:git:https://github.com/decebals/wicket-pivot.git
28 | scm:git:https://github.com/decebals/wicket-pivot.git
29 | git@github.com/decebals/wicket-pivot.git
30 | HEAD
31 |
32 |
33 |
34 | UTF-8
35 | 8.12.0
36 |
37 |
38 |
39 |
40 |
41 | false
42 | src/main/java
43 |
44 | **/*.java
45 |
46 |
47 |
48 | src/main/resources
49 |
50 |
51 |
52 |
53 |
54 | org.apache.maven.plugins
55 | maven-compiler-plugin
56 | 3.8.0
57 |
58 | 1.8
59 | 1.8
60 | true
61 |
62 |
63 |
64 |
65 | org.apache.maven.plugins
66 | maven-javadoc-plugin
67 |
68 |
69 |
70 | jar
71 |
72 |
73 |
74 |
75 |
76 |
77 | org.apache.maven.plugins
78 | maven-source-plugin
79 |
80 |
81 |
82 | jar
83 |
84 |
85 |
86 |
87 |
88 |
89 | org.apache.maven.plugins
90 | maven-release-plugin
91 | 2.3.2
92 |
93 | deploy
94 | true
95 | release-@{project.version}
96 |
97 |
98 |
99 |
100 | maven-resources-plugin
101 | 2.4.3
102 |
103 |
104 |
105 | maven-jar-plugin
106 | 3.1.2
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | org.apache.wicket
115 | wicket-core
116 | ${wicket.version}
117 |
118 |
119 |
120 | org.apache.wicket
121 | wicket-extensions
122 | ${wicket.version}
123 |
124 |
125 |
126 |
127 | wicket-pivot
128 | wicket-pivot-exporter
129 | demo
130 |
131 |
132 |
133 |
134 | release-sign-artifacts
135 |
136 |
137 | performRelease
138 | true
139 |
140 |
141 |
142 |
143 |
144 | org.apache.maven.plugins
145 | maven-gpg-plugin
146 |
147 |
148 | sign-artifacts
149 | verify
150 |
151 | sign
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/FieldCalculation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 | import java.util.Arrays;
17 | import java.util.Collections;
18 | import java.util.List;
19 |
20 | public abstract class FieldCalculation implements Serializable {
21 | private static final long serialVersionUID = 1L;
22 | public static final String PERCENT_OF = "percentOf";
23 | public static final String SUBTRACT = "subtract";
24 | public static final String ADDITION = "addition";
25 |
26 | public static final List FUNCTIONS = Collections.unmodifiableList(Arrays.asList(PERCENT_OF, SUBTRACT,
27 | ADDITION));
28 | private PivotField fieldA;
29 | private PivotField fieldB;
30 |
31 | public static List getFunctions() {
32 | return FUNCTIONS;
33 | }
34 |
35 | public static FieldCalculation get(String function) {
36 | if (function.equalsIgnoreCase(PERCENT_OF)) {
37 | return new PercentOf();
38 | } else if (function.equalsIgnoreCase(SUBTRACT)) {
39 | return new Substract();
40 | } else if (function.equalsIgnoreCase(ADDITION)) {
41 | return new Addition();
42 | }
43 | return null;
44 | }
45 |
46 | /**
47 | * Provide
48 | */
49 | @FunctionalInterface
50 | public interface FieldValueProvider {
51 | /**
52 | * @param field
53 | * can be null
54 | *
55 | * @return the current value of the pivot field
56 | */
57 | Object getFieldValue(PivotField field);
58 | }
59 |
60 | public abstract FieldCalculation init();
61 |
62 | public abstract String getFunction();
63 |
64 | public abstract String getDescription();
65 |
66 | public abstract Object calculate(FieldValueProvider fieldValueProvider);
67 |
68 | protected String getFieldDescription(PivotField field) {
69 | if (field == null)
70 | return "";
71 | return field.getTitle() + " (" + field.getCalculationDescription() + ")";
72 | }
73 |
74 | public static class PercentOf extends FieldCalculation {
75 | private static final long serialVersionUID = 1L;
76 |
77 | @Override
78 | public FieldCalculation init() {
79 | return this;
80 | }
81 |
82 | @Override
83 | public String getFunction() {
84 | return PERCENT_OF;
85 | }
86 |
87 | @Override
88 | public Object calculate(FieldValueProvider fieldValueProvider) {
89 | Object valueA = fieldValueProvider.getFieldValue(getFieldA());
90 | Object valueB = fieldValueProvider.getFieldValue(getFieldB());
91 | if (valueA instanceof Number && valueB instanceof Number) {
92 | Number numberA = (Number) valueA;
93 | Number numberB = (Number) valueB;
94 | if (Math.abs(numberB.doubleValue()) > 0.000001)
95 | return 100.0 / numberB.doubleValue() * numberA.doubleValue();
96 | }
97 | return 0;
98 | }
99 |
100 | @Override
101 | public String getDescription() {
102 | return "% " + getFieldDescription(getFieldA()) + " of " + getFieldDescription(getFieldB());
103 | }
104 | }
105 |
106 | public static class Substract extends FieldCalculation {
107 | private static final long serialVersionUID = 1L;
108 |
109 | @Override
110 | public FieldCalculation init() {
111 | return this;
112 | }
113 |
114 | @Override
115 | public String getFunction() {
116 | return SUBTRACT;
117 | }
118 |
119 | @Override
120 | public Object calculate(FieldValueProvider fieldValueProvider) {
121 | Object valueA = fieldValueProvider.getFieldValue(getFieldA());
122 | Object valueB = fieldValueProvider.getFieldValue(getFieldB());
123 | if (valueA instanceof Number && valueB instanceof Number) {
124 | Number numberA = (Number) valueA;
125 | Number numberB = (Number) valueB;
126 | return numberA.doubleValue() - numberB.doubleValue();
127 | }
128 | return 0;
129 | }
130 |
131 | @Override
132 | public String getDescription() {
133 | return getFieldDescription(getFieldA()) + " - " + getFieldDescription(getFieldB());
134 | }
135 | }
136 |
137 | public static class Addition extends FieldCalculation {
138 | private static final long serialVersionUID = 1L;
139 |
140 | @Override
141 | public FieldCalculation init() {
142 | return this;
143 | }
144 |
145 | @Override
146 | public String getFunction() {
147 | return ADDITION;
148 | }
149 |
150 | @Override
151 | public Object calculate(FieldValueProvider fieldValueProvider) {
152 | Object valueA = fieldValueProvider.getFieldValue(getFieldA());
153 | Object valueB = fieldValueProvider.getFieldValue(getFieldB());
154 | if (valueA instanceof Number && valueB instanceof Number) {
155 | Number numberA = (Number) valueA;
156 | Number numberB = (Number) valueB;
157 | return numberA.doubleValue() + numberB.doubleValue();
158 | }
159 | return 0;
160 | }
161 |
162 | @Override
163 | public String getDescription() {
164 | return getFieldDescription(getFieldA()) + " + " + getFieldDescription(getFieldB());
165 | }
166 | }
167 |
168 | @Override
169 | public boolean equals(Object obj) {
170 | if (obj instanceof FieldCalculation) {
171 | String tmp = ((FieldCalculation) obj).getFunction();
172 | return getFunction().equals(tmp);
173 | }
174 |
175 | return false;
176 | }
177 |
178 | @Override
179 | public int hashCode() {
180 | return getFunction().hashCode();
181 | }
182 |
183 | public PivotField getFieldA() {
184 | return fieldA;
185 | }
186 |
187 | public void setFieldA(PivotField fieldA) {
188 | this.fieldA = fieldA;
189 | }
190 |
191 | public PivotField getFieldB() {
192 | return fieldB;
193 | }
194 |
195 | public void setFieldB(PivotField fieldB) {
196 | this.fieldB = fieldB;
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotSettings.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import org.apache.wicket.Application;
16 | import org.apache.wicket.MetaDataKey;
17 | import org.apache.wicket.request.resource.PackageResourceReference;
18 | import org.apache.wicket.request.resource.ResourceReference;
19 |
20 | /**
21 | * @author Decebal Suiu
22 | */
23 | public class PivotSettings {
24 |
25 | @SuppressWarnings("serial")
26 | private static final MetaDataKey KEY = new MetaDataKey() {};
27 |
28 | private ResourceReference javaScriptReference = new PackageResourceReference(
29 | PivotSettings.class, "res/pivot.js");
30 | private ResourceReference cssReference = new PackageResourceReference(
31 | PivotSettings.class, "res/pivot.css");
32 | private ResourceReference jqueryReference = new PackageResourceReference(
33 | PivotSettings.class, "res/jquery-1.8.3.min.js");
34 | private ResourceReference jqueryUIReference = new PackageResourceReference(
35 | PivotSettings.class, "res/jquery-ui-1.9.2.min.js");
36 | private ResourceReference jqueryJsonReference = new PackageResourceReference(
37 | PivotSettings.class, "res/jquery.json-2.2.min.js");
38 | private ResourceReference bootstrapJavaScriptReference = new PackageResourceReference(
39 | PivotSettings.class, "res/bootstrap.js");
40 | private ResourceReference bootstrapCssReference = new PackageResourceReference(
41 | PivotSettings.class, "res/bootstrap.css");
42 |
43 | private boolean includeJQuery = false;
44 | private boolean includeJQueryUI = true;
45 | private boolean includeJQueryJson = true;
46 | private boolean includeJavaScript = true;
47 | private boolean includeCss = true;
48 | private boolean includeBootstrap = true;
49 |
50 | /**
51 | * Private constructor, use {@link #get()} instead.
52 | */
53 | private PivotSettings() {
54 | }
55 |
56 | public boolean isIncludeJQuery() {
57 | return includeJQuery;
58 | }
59 |
60 | public PivotSettings setIncludeJQuery(boolean includeJQuery) {
61 | this.includeJQuery = includeJQuery;
62 | return this;
63 | }
64 |
65 | public boolean isIncludeJQueryUI() {
66 | return includeJQueryUI;
67 | }
68 |
69 | public PivotSettings setIncludeJQueryUI(boolean includeJQueryUI) {
70 | this.includeJQueryUI = includeJQueryUI;
71 | return this;
72 | }
73 |
74 | public boolean isIncludeJQueryJson() {
75 | return includeJQueryJson;
76 | }
77 |
78 | public void setIncludeJQueryJson(boolean includeJQueryJson) {
79 | this.includeJQueryJson = includeJQueryJson;
80 | }
81 |
82 | public boolean isIncludeJavaScript() {
83 | return includeJavaScript;
84 | }
85 |
86 | public PivotSettings setIncludeJavascript(boolean includeJavaScript) {
87 | this.includeJavaScript = includeJavaScript;
88 | return this;
89 | }
90 |
91 | public boolean isIncludeCss() {
92 | return includeCss;
93 | }
94 |
95 | public PivotSettings setIncludeCss(boolean includeCss) {
96 | this.includeCss = includeCss;
97 | return this;
98 | }
99 |
100 | public boolean isIncludeBootstrap() {
101 | return includeBootstrap;
102 | }
103 |
104 | public PivotSettings setIncludeBootstrap(boolean includeBootstrap) {
105 | this.includeBootstrap = includeBootstrap;
106 | return this;
107 | }
108 |
109 | public ResourceReference getJQueryReference() {
110 | return jqueryReference;
111 | }
112 |
113 | public PivotSettings setJQueryReference(ResourceReference jqueryReference) {
114 | this.jqueryReference = jqueryReference;
115 | return this;
116 | }
117 |
118 | public ResourceReference getJQueryUIReference() {
119 | return jqueryUIReference;
120 | }
121 |
122 | public PivotSettings setJQueryUIReference(ResourceReference jqueryUIReference) {
123 | this.jqueryUIReference = jqueryUIReference;
124 | return this;
125 | }
126 |
127 | public ResourceReference getJQueryJsonReference() {
128 | return jqueryJsonReference;
129 | }
130 |
131 | public PivotSettings setJQueryJsonReference(ResourceReference jqueryJsonReference) {
132 | this.jqueryJsonReference = jqueryJsonReference;
133 | return this;
134 | }
135 |
136 | public ResourceReference getJavaScriptReference() {
137 | return javaScriptReference;
138 | }
139 |
140 | public PivotSettings setJavaScriptReference(ResourceReference javaScriptReference) {
141 | this.javaScriptReference = javaScriptReference;
142 | return this;
143 | }
144 |
145 | public ResourceReference getCssReference() {
146 | return cssReference;
147 | }
148 |
149 | public PivotSettings setCssReference(ResourceReference cssReference) {
150 | this.cssReference = cssReference;
151 | return this;
152 | }
153 |
154 | public ResourceReference getBootstrapJavaScriptReference() {
155 | return bootstrapJavaScriptReference;
156 | }
157 |
158 | public PivotSettings setBootstrapJavaScriptReference(ResourceReference bootstrapJavaScriptReference) {
159 | this.bootstrapJavaScriptReference = bootstrapJavaScriptReference;
160 | return this;
161 | }
162 |
163 | public ResourceReference getBootstrapCssReference() {
164 | return bootstrapCssReference;
165 | }
166 |
167 | public PivotSettings setBootstrapCssReference(ResourceReference bootstrapCssReference) {
168 | this.bootstrapCssReference = bootstrapCssReference;
169 | return this;
170 | }
171 |
172 | /**
173 | * Retrieves the instance of settings object.
174 | *
175 | * @return settings instance
176 | */
177 | public static PivotSettings get() {
178 | Application application = Application.get();
179 | PivotSettings settings = application.getMetaData(KEY);
180 | if (settings == null) {
181 | synchronized (application) {
182 | settings = application.getMetaData(KEY);
183 | if (settings == null) {
184 | settings = new PivotSettings();
185 | application.setMetaData(KEY, settings);
186 | }
187 | }
188 | }
189 |
190 | return application.getMetaData(KEY);
191 | }
192 |
193 | }
194 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Simple wicket pivot table
2 | =====================
3 | A pivot table is a data summarization tool found in data visualization programs such as spreadsheets or business intelligence software.
4 | For more information what it's a pivot table see http://en.wikipedia.org/wiki/Pivot_table.
5 |
6 | Current build status: [](https://buildhive.cloudbees.com/job/decebals/job/wicket-pivot/)
7 |
8 | 
9 |
10 | Components
11 | -------------------
12 | - **PivotDataSource** is the data source for pivot table (pivot's fields). The data can be fetched from a sql ResultSet (see ResultSetPivotDataSource)
13 | or other non sql sources.
14 | - **PivotModel** is the place where I put the pivot configuration, here I can specify what fields are on each area (ROW, COLUMN, DATA)
15 | and what is their ordering. Also, here I can mention if I want a grand total on rows and/or columns.
16 | - **PivotTable** is the component that displays the pivot and it takes a PivotModel object as parameter.
17 | - **PivotField** is the object that can be put on a pivot's area. This object has a name and an index.
18 | As a constraint, on pivot's data area must be minimum one field and minimum one field on row or column areas.
19 | Also on aria DATA you can put only fields with Number type.
20 | The pivot fields allow several types of aggregations including sum, average, min, max, count.
21 | - **PivotExporter** is the interface for the pivot exporter plugins (builtin support for Csv and Xls)
22 |
23 | Artifacts
24 | -------------------
25 | - Wicket Pivot `wicket-pivot` (jar)
26 | - Wicket Pivot Demo `wicket-pivot-demo` (war)
27 |
28 | Using Maven
29 | -------------------
30 | In your pom.xml you must define the dependencies to Wicket Pivot artifacts with:
31 |
32 | ```xml
33 |
34 | ro.fortsoft.wicket.pivot
35 | wicket-pivot
36 | ${wicket-pivot.version}
37 |
38 | ```
39 |
40 | where ${wicket-pivot.version} is the last wicket-pivot version.
41 |
42 | You may want to check for the latest released version using [Maven Search](http://search.maven.org/#search%7Cga%7C1%7Cwicket-pivot)
43 |
44 | How to use
45 | -------------------
46 | It's very simple to add a pivot table in your wicket application.
47 |
48 | ```java
49 | PivotDataSource pivotDataSource = ...;
50 | add(new PivotPanel("pivot", pivotDataSource));
51 | ```
52 |
53 | First of all you must create a PivotDataSource and secondly add the pivot panel in your page.
54 |
55 | If you want to add programmatically some fields on the pivot areas
56 |
57 | ```java
58 | pivotModel.getField("REGION").setArea(PivotField.Area.ROW);
59 | pivotModel.getField("SALESMAN").setArea(PivotField.Area.ROW).setAreaIndex(1);
60 | pivotModel.getField("YEAR").setArea(PivotField.Area.COLUMN);
61 | pivotModel.getField("MONTH").setArea(PivotField.Area.COLUMN).setAreaIndex(1);
62 | pivotModel.getField("SALES").setArea(PivotField.Area.DATA);
63 | ```
64 |
65 | You can specify an aggregator for a data pivot field
66 |
67 | ```java
68 | pivotModel.getField("SALES").setAggregator(Aggregator.get(Aggregator.COUNT));
69 | ```
70 |
71 | or
72 |
73 | ```java
74 | pivotModel.getField("MONEY").setAggregator(new Aggregator.Count());
75 | ```
76 |
77 | You can specify a custom converter (wicket `IConverter`) for a field
78 |
79 | ```java
80 | pivotModel.getField("SALES").setConverter(new DoubleConverter() {
81 |
82 | @Override
83 | public NumberFormat getNumberFormat(Locale locale) {
84 | NumberFormat format = super.getNumberFormat(locale);
85 | format.setMinimumFractionDigits(2);
86 |
87 | return format;
88 | }
89 |
90 | });
91 | ```
92 |
93 | If you don't set a converter for a field then this field (the values) will be rendered
94 | with a converter supplied by wicket according to the field type.
95 |
96 | If you want to display programmatically a grand total on rows and/or columns
97 |
98 | ```java
99 | pivotModel.setShowGrandTotalForColumn(true);
100 | pivotModel.setShowGrandTotalForRow(true);
101 | ```
102 |
103 | Also, Wicket Pivot has support for Field calculations, e.g:
104 |
105 | - % fieldA of fieldB (PercentOf); when you need to display how much % are the costs from the revenue. I.e. how much % of our revenue do we give to Google
106 | - field A + fieldB (Addition)
107 | - fieldA - fieldB (Substract)
108 |
109 | Another nice feature is auto calculate (a check box component). When you check this feature than on each pivot modifications (area, aggregation, etc) you can see the result in real time.
110 |
111 | Internationalization
112 | -------------------
113 | Wicket-pivot has support for internationalization.
114 | Supported languages:
115 | - English
116 | - German
117 | - Romanian
118 |
119 | If you want support for another languages please create and send a pull request (or an email) with the translation of [wicket-package.properties](https://github.com/decebals/wicket-pivot/blob/master/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/wicket-package.properties).
120 |
121 | Demo
122 | -------------------
123 | I have a tiny demo application with a demo apache derby embedded database. The demo application is in demo package.
124 | To run the demo application use:
125 |
126 | ```bash
127 | mvn install
128 | cd demo
129 | mvn jetty:run
130 | ```
131 |
132 | In the internet browser type http://localhost:8081/.
133 |
134 | In demo pivot page put some fields on the areas (for example "REGION", "SALESMAN" on ROW area, "YEAR", "MONTH"
135 | on COLUMN area and "SALES" on DATA area) and press the "Show pivot" button.
136 |
137 | You can see a screenshot from demo application in [wiki page] (https://github.com/decebals/wicket-pivot/wiki).
138 |
139 | Versioning
140 | ------------
141 | Wicket-pivot will be maintained under the Semantic Versioning guidelines as much as possible.
142 |
143 | Releases will be numbered with the follow format:
144 |
145 | `..`
146 |
147 | And constructed with the following guidelines:
148 |
149 | * Breaking backward compatibility bumps the major
150 | * New additions without breaking backward compatibility bumps the minor
151 | * Bug fixes and misc changes bump the patch
152 |
153 | For more information on SemVer, please visit http://semver.org/.
154 |
155 | License
156 | --------------
157 | Copyright 2012 Decebal Suiu
158 |
159 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
160 | the License. You may obtain a copy of the License in the LICENSE file, or at:
161 |
162 | http://www.apache.org/licenses/LICENSE-2.0
163 |
164 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
165 | an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
166 | specific language governing permissions and limitations under the License.
167 |
--------------------------------------------------------------------------------
/wicket-pivot-exporter/src/main/java/ro/fortsoft/wicket/pivot/exporter/PivotXlsExporter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.exporter;
14 |
15 | import org.apache.poi.hssf.usermodel.HSSFCellStyle;
16 | import org.apache.poi.hssf.usermodel.HSSFWorkbook;
17 | import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
18 | import org.apache.poi.ss.usermodel.*;
19 | import org.apache.poi.ss.util.CellRangeAddress;
20 | import ro.fortsoft.wicket.pivot.PivotModel;
21 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel;
22 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.*;
23 |
24 | import java.awt.*;
25 | import java.io.IOException;
26 | import java.io.OutputStream;
27 | import java.util.HashMap;
28 | import java.util.Map;
29 |
30 | /**
31 | * Basic XLS exporter
32 | */
33 | public class PivotXlsExporter implements PivotExporter {
34 | private static final long serialVersionUID = 1L;
35 |
36 | private static class StyleContext {
37 | private CellStyle headerStyle;
38 | private CellStyle dataHeaderStyle;
39 | private HSSFCellStyle grandTotalStyle;
40 |
41 | StyleContext(HSSFWorkbook wb) {
42 | headerStyle = wb.createCellStyle();
43 |
44 | headerStyle.setBorderTop(BorderStyle.MEDIUM);
45 | headerStyle.setBorderLeft(BorderStyle.MEDIUM);
46 | headerStyle.setBorderRight(BorderStyle.MEDIUM);
47 | headerStyle.setBorderBottom(BorderStyle.MEDIUM);
48 | headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
49 | headerStyle.setFillForegroundColor(HSSFColorPredefined.GREY_25_PERCENT.getIndex());
50 |
51 | dataHeaderStyle = wb.createCellStyle();
52 | dataHeaderStyle.setBorderTop(BorderStyle.MEDIUM);
53 | dataHeaderStyle.setBorderLeft(BorderStyle.MEDIUM);
54 | dataHeaderStyle.setBorderRight(BorderStyle.MEDIUM);
55 | dataHeaderStyle.setBorderBottom(BorderStyle.MEDIUM);
56 | dataHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
57 | dataHeaderStyle.setFillForegroundColor(HSSFColorPredefined.GREY_25_PERCENT.getIndex());
58 |
59 | grandTotalStyle = wb.createCellStyle();
60 | grandTotalStyle.setBorderTop(BorderStyle.MEDIUM);
61 | grandTotalStyle.setBorderLeft(BorderStyle.MEDIUM);
62 | grandTotalStyle.setBorderRight(BorderStyle.MEDIUM);
63 | grandTotalStyle.setBorderBottom(BorderStyle.MEDIUM);
64 | grandTotalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
65 | grandTotalStyle.setFillForegroundColor(HSSFColorPredefined.LIGHT_TURQUOISE.getIndex());
66 | }
67 | }
68 |
69 | @Override
70 | public void exportPivot(PivotModel pivotModel, OutputStream outputStream) throws IOException {
71 | PivotTableRenderModel renderModel = PivotTableRenderModel.create(pivotModel);
72 |
73 | HSSFWorkbook wb = new HSSFWorkbook();
74 | Sheet sheetData = wb.createSheet("Pivot");
75 |
76 | Map rowSpanMap = new HashMap<>();
77 | StyleContext styleContext = new StyleContext(wb);
78 |
79 | int rowNumber = 0;
80 | int maxColNum = 0;
81 | for (RenderRow row : renderModel.getAllRenderRows()) {
82 | int col = 0;
83 | Row poiRow = sheetData.createRow(rowNumber);
84 | for (RenderCell cell : row.getRenderCells()) {
85 | maxColNum = Math.max(maxColNum, col);
86 |
87 | /*
88 | * Check if we currently have a rowspan at this column from the
89 | * parent row. We only support a colspan of 1 at the moment
90 | * here, if rowspan > 1
91 | */
92 | Integer rowSpan = rowSpanMap.get(col);
93 | if (rowSpan != null) {
94 | rowSpan--;
95 | if (rowSpan == 0)
96 | rowSpanMap.remove(col);
97 | else
98 | rowSpanMap.put(col, rowSpan);
99 | col++;
100 | }
101 |
102 | Cell poiCell = poiRow.createCell(col);
103 |
104 | /*
105 | * Output the Value
106 | */
107 | Object rawValue = cell.getRawValue();
108 | if (rawValue != null) {
109 | if (rawValue instanceof Double) {
110 | poiCell.setCellValue((Double) rawValue);
111 | } else {
112 | poiCell.setCellValue(String.valueOf(rawValue));
113 | }
114 | }
115 |
116 | styleCell(poiCell, cell, styleContext);
117 |
118 | if (cell.getRowspan() > 1) {
119 | rowSpanMap.put(col, cell.getRowspan() - 1);
120 | sheetData.addMergedRegion(new CellRangeAddress(rowNumber, rowNumber + cell.getRowspan() - 1, col,
121 | col));
122 | }
123 |
124 | /*
125 | * We only support colspan _OR_ rowspan. The current PivotTable
126 | * also doesnt have rowspan and colspan at the same time.
127 | */
128 | if (cell.getColspan() > 1) {
129 | sheetData.addMergedRegion(new CellRangeAddress(rowNumber, rowNumber, col, col + cell.getColspan()
130 | - 1));
131 | }
132 |
133 | col++;
134 | for (int i = 1; i < cell.getColspan(); i++) {
135 | col++;
136 | }
137 | }
138 | rowNumber++;
139 | }
140 |
141 | autoSizeColumns(sheetData, maxColNum);
142 |
143 | wb.write(outputStream);
144 | outputStream.flush();
145 | }
146 |
147 | private void styleCell(Cell poiCell, RenderCell cell, StyleContext styleContext) {
148 | if (cell instanceof HeaderRenderCell)
149 | poiCell.setCellStyle(styleContext.headerStyle);
150 | if (cell instanceof GrandTotalHeaderRenderCell)
151 | poiCell.setCellStyle(styleContext.grandTotalStyle);
152 | if( cell instanceof GrandTotalValueRenderCell)
153 | poiCell.setCellStyle(styleContext.grandTotalStyle);
154 | if (cell instanceof DataHeaderRenderCell)
155 | poiCell.setCellStyle(styleContext.dataHeaderStyle);
156 | }
157 |
158 | private void autoSizeColumns(Sheet sheetData, int maxColNum) {
159 | try {
160 | // Autosize columns
161 | int width = 0;
162 | for (int col = 0; col < maxColNum; col++) {
163 | sheetData.autoSizeColumn(col);
164 | int cwidth = sheetData.getColumnWidth(col);
165 | cwidth += 500;
166 | sheetData.setColumnWidth(col, cwidth);
167 | width += cwidth;
168 | }
169 |
170 | // calculate zoom factor
171 | int nominator = 45000 * 100 / width;
172 | if (nominator < 100)
173 | sheetData.setZoom(nominator);
174 |
175 | } catch (HeadlessException he) {
176 | // No UI, no autosize :(
177 | }
178 | }
179 |
180 | @Override
181 | public String getFormatName() {
182 | return "XLS";
183 | }
184 |
185 | @Override
186 | public String getFormatMimetype() {
187 | return "application/vnd.ms-excel";
188 | }
189 |
190 | @Override
191 | public String getFilenameExtension() {
192 | return "xls";
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotAreaPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import java.io.IOException;
16 | import java.util.HashMap;
17 | import java.util.List;
18 | import java.util.Map;
19 |
20 | import org.apache.wicket.AttributeModifier;
21 | import org.apache.wicket.Component;
22 | import org.apache.wicket.ajax.AjaxRequestTarget;
23 | import org.apache.wicket.event.Broadcast;
24 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
25 | import org.apache.wicket.markup.head.IHeaderResponse;
26 | import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
27 | import org.apache.wicket.markup.html.WebMarkupContainer;
28 | import org.apache.wicket.markup.html.basic.Label;
29 | import org.apache.wicket.markup.html.list.ListItem;
30 | import org.apache.wicket.markup.html.list.ListView;
31 | import org.apache.wicket.markup.html.panel.EmptyPanel;
32 | import org.apache.wicket.markup.html.panel.Panel;
33 | import org.apache.wicket.model.AbstractReadOnlyModel;
34 | import org.apache.wicket.model.IModel;
35 | import org.apache.wicket.model.LoadableDetachableModel;
36 | import org.apache.wicket.model.Model;
37 | import org.apache.wicket.model.ResourceModel;
38 | import org.apache.wicket.util.template.PackageTextTemplate;
39 |
40 | import ro.fortsoft.wicket.pivot.PivotField;
41 | import ro.fortsoft.wicket.pivot.PivotModel;
42 |
43 | /**
44 | * @author Decebal Suiu
45 | */
46 | public class PivotAreaPanel extends Panel {
47 |
48 | private static final long serialVersionUID = 1L;
49 |
50 | private SortableAjaxBehavior sortableAjaxBehavior;
51 | private ListView fieldsView;
52 | private PivotField.Area area;
53 | private ModalWindow modal;
54 |
55 | public PivotAreaPanel(String id, PivotField.Area area) {
56 | super(id);
57 |
58 | this.area = area;
59 |
60 | modal = new ModalWindow("modal");
61 | modal.setAutoSize(true);
62 | add(modal);
63 |
64 | add(new Label("name", new ResourceModel(area.getName())));
65 |
66 | WebMarkupContainer fieldsContainer = new WebMarkupContainer("fieldsContainer");
67 | fieldsContainer.setOutputMarkupId(true);
68 | fieldsContainer.setMarkupId("area-" + area.getName() + "-" + getSession().nextSequenceValue());
69 | add(fieldsContainer);
70 |
71 | fieldsView = new ListView("fields") {
72 |
73 | private static final long serialVersionUID = 1L;
74 |
75 | @Override
76 | protected void populateItem(ListItem item) {
77 | final IModel itemModel = item.getModel();
78 | final PivotField pivotField = itemModel.getObject();
79 | final PivotField.Area area = PivotAreaPanel.this.area;
80 | Label fieldLabel = new Label("field", new AbstractReadOnlyModel() {
81 |
82 | private static final long serialVersionUID = 1L;
83 |
84 | @Override
85 | public String getObject() {
86 | String title = pivotField.getTitle();
87 | if (area.equals(PivotField.Area.DATA)) {
88 | title += " (" + pivotField.getCalculationDescription() + ")";
89 | }
90 |
91 | return title;
92 | }
93 |
94 | });
95 | if (pivotField.isNumber()) {
96 | item.add(AttributeModifier.append("class", "field-number"));
97 | }
98 |
99 | // add field actions panel
100 | if (!area.equals(PivotField.Area.UNUSED)) {
101 | PivotFieldActionsPanel pivotFieldActionsPanel = new PivotFieldActionsPanel("dropDownPanel", Model.of(pivotField), Model.of(getPivotModel()));
102 | pivotFieldActionsPanel.setRenderBodyOnly(true);
103 | item.add(pivotFieldActionsPanel);
104 | String markupId = "dropdown-" + pivotField.getIndex();
105 | pivotFieldActionsPanel.get("dropdown").setMarkupId(markupId);
106 | fieldLabel.add(AttributeModifier.append("data-dropdown", "#" + markupId));
107 | } else {
108 | item.add(new EmptyPanel("dropDownPanel").setVisible(false));
109 | }
110 |
111 | item.add(fieldLabel);
112 | item.setOutputMarkupId(true);
113 | item.setMarkupId("field-" + pivotField.getIndex());
114 | }
115 | };
116 | fieldsView.setOutputMarkupPlaceholderTag(true);
117 | fieldsContainer.add(fieldsView);
118 |
119 | setOutputMarkupId(true);
120 | }
121 |
122 | @Override
123 | protected void onBeforeRender() {
124 | IModel> model = new LoadableDetachableModel>() {
125 |
126 | private static final long serialVersionUID = 1L;
127 |
128 | @Override
129 | protected List load() {
130 | return getPivotModel().getFields(area);
131 | }
132 |
133 | };
134 |
135 | fieldsView.setModel(model);
136 |
137 | super.onBeforeRender();
138 | }
139 |
140 | @Override
141 | protected void onInitialize() {
142 | super.onInitialize();
143 |
144 | addSortableBehavior(get("fieldsContainer"));
145 | }
146 |
147 | public PivotField.Area getArea() {
148 | return area;
149 | }
150 |
151 | public ModalWindow getModal() {
152 | return modal;
153 | }
154 |
155 | @Override
156 | public void renderHead(IHeaderResponse response) {
157 | super.renderHead(response);
158 |
159 | CharSequence script = sortableAjaxBehavior.getCallbackFunctionBody();
160 |
161 | Map vars = new HashMap<>();
162 | vars.put("component", get("fieldsContainer").getMarkupId());
163 | vars.put("stopBehavior", script.toString());
164 |
165 | PackageTextTemplate template = new PackageTextTemplate(PivotAreaPanel.class, "res/sort-behavior.template.js");
166 | template.interpolate(vars);
167 |
168 | response.render(OnDomReadyHeaderItem.forScript(template.getString()));
169 | try {
170 | template.close();
171 | } catch(IOException e) {
172 | throw new RuntimeException(e);
173 | }
174 | }
175 |
176 | public ListView getFieldsView() {
177 | return fieldsView;
178 | }
179 |
180 | private void addSortableBehavior(Component component) {
181 | sortableAjaxBehavior = new SortableAjaxBehavior() {
182 |
183 | private static final long serialVersionUID = 1L;
184 |
185 | @Override
186 | public void onSort(AjaxRequestTarget target, Item[] items) {
187 | PivotModel pivotModel = getPivotModel();
188 | for (Item item : items) {
189 | PivotField pivotField = pivotModel.getField(item.fieldIndex);
190 | pivotField.setArea(PivotField.Area.getValue(item.areaName));
191 | pivotField.setAreaIndex(item.sortIndex);
192 | }
193 | send(getPage(), Broadcast.BREADTH, new AreaChangedEvent(target));
194 | }
195 |
196 | };
197 | component.add(sortableAjaxBehavior);
198 | }
199 |
200 | private PivotModel getPivotModel() {
201 | return findParent(PivotPanel.class).getPivotModel();
202 | }
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/Aggregator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 | import java.util.Arrays;
17 | import java.util.Collection;
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | /**
22 | * @author Decebal Suiu
23 | */
24 | public abstract class Aggregator implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | public static final String SUM = "sum";
29 | public static final String AVG = "avg";
30 | public static final String MIN = "min";
31 | public static final String MAX = "max";
32 | public static final String COUNT = "count";
33 |
34 | public static final List FUNCTIONS = Collections.unmodifiableList(Arrays.asList(SUM, AVG, MIN, MAX, COUNT));
35 |
36 | public static List getFunctions() {
37 | return FUNCTIONS;
38 | }
39 |
40 | public static Aggregator get(String function) {
41 | if (function.equalsIgnoreCase(SUM)) {
42 | return new Sum();
43 | } else if (function.equalsIgnoreCase(AVG)) {
44 | return new Average();
45 | } else if (function.equalsIgnoreCase(MIN)) {
46 | return new Minimum();
47 | } else if (function.equalsIgnoreCase(MAX)) {
48 | return new Maximum();
49 | } else if (function.equalsIgnoreCase(COUNT)) {
50 | return new Count();
51 | }
52 |
53 | return null;
54 | }
55 |
56 | public abstract Aggregator init();
57 |
58 | public abstract Aggregator add(Object value);
59 |
60 | public abstract Object getResult();
61 |
62 | public abstract String getFunction();
63 |
64 | public Aggregator addAll(Collection values) {
65 | for (Object value : values) {
66 | add(value);
67 | }
68 |
69 | return this;
70 | }
71 |
72 | @Override
73 | public boolean equals(Object obj) {
74 | if (obj instanceof Aggregator) {
75 | String tmp = ((Aggregator) obj).getFunction();
76 | return getFunction().equals(tmp);
77 | }
78 |
79 | return false;
80 | }
81 |
82 | @Override
83 | public int hashCode() {
84 | return getFunction().hashCode();
85 | }
86 |
87 | public static class Sum extends Aggregator {
88 |
89 | private static final long serialVersionUID = 1L;
90 |
91 | private double total;
92 |
93 | @Override
94 | public Aggregator init() {
95 | total = 0.0;
96 |
97 | return this;
98 | }
99 |
100 | @Override
101 | public Aggregator add(Object value) {
102 | if (value instanceof Number) {
103 | total += ((Number) value).doubleValue();
104 | }
105 |
106 | return this;
107 | }
108 |
109 | @Override
110 | public Object getResult() {
111 | return total;
112 | }
113 |
114 | @Override
115 | public String getFunction() {
116 | return SUM;
117 | }
118 |
119 | }
120 |
121 | public static class Average extends Aggregator {
122 |
123 | private static final long serialVersionUID = 1L;
124 |
125 | private double total;
126 | private double count;
127 |
128 | @Override
129 | public Aggregator init() {
130 | total = 0.0;
131 | count = 0.0;
132 |
133 | return this;
134 | }
135 |
136 | @Override
137 | public Aggregator add(Object value) {
138 | if (value instanceof Number) {
139 | total += ((Number) value).doubleValue();
140 | count++;
141 | }
142 |
143 | return this;
144 | }
145 |
146 | @Override
147 | public Object getResult() {
148 | if (count == 0.0) {
149 | return null;
150 | }
151 |
152 | return total / count;
153 | }
154 |
155 | @Override
156 | public String getFunction() {
157 | return AVG;
158 | }
159 |
160 | }
161 |
162 | public static class Minimum extends Aggregator {
163 |
164 | private static final long serialVersionUID = 1L;
165 |
166 | private Object min;
167 |
168 | @Override
169 | public Aggregator init() {
170 | min = null;
171 |
172 | return this;
173 | }
174 |
175 | @Override
176 | @SuppressWarnings("unchecked")
177 | public Aggregator add(Object value) {
178 | if (value != null) {
179 | if (min == null) {
180 | min = value;
181 | } else if (value instanceof Comparable) {
182 | if (((Comparable) value).compareTo(min) < 0) {
183 | min = value;
184 | }
185 | }
186 | }
187 |
188 | return this;
189 | }
190 |
191 | @Override
192 | public Object getResult() {
193 | return min;
194 | }
195 |
196 | @Override
197 | public String getFunction() {
198 | return MIN;
199 | }
200 |
201 | }
202 |
203 | public static class Maximum extends Aggregator {
204 |
205 | private static final long serialVersionUID = 1L;
206 |
207 | private Object max;
208 |
209 | @Override
210 | public Aggregator init() {
211 | max = null;
212 |
213 | return this;
214 | }
215 |
216 | @Override
217 | @SuppressWarnings("unchecked")
218 | public Aggregator add(Object value) {
219 | if (value != null) {
220 | if (max == null) {
221 | max = value;
222 | } else if (value instanceof Comparable) {
223 | if (((Comparable) value).compareTo(max) > 0) {
224 | max = value;
225 | }
226 | }
227 | }
228 |
229 | return this;
230 | }
231 |
232 | @Override
233 | public Object getResult() {
234 | return max;
235 | }
236 |
237 | @Override
238 | public String getFunction() {
239 | return MAX;
240 | }
241 |
242 | }
243 |
244 | public static class Count extends Aggregator {
245 |
246 | private static final long serialVersionUID = 1L;
247 |
248 | private int count;
249 |
250 | @Override
251 | public Aggregator init() {
252 | count = 0;
253 |
254 | return this;
255 | }
256 |
257 | @Override
258 | public Aggregator add(Object value) {
259 | if (value != null) {
260 | count++;
261 | }
262 |
263 | return this;
264 | }
265 |
266 | @Override
267 | public Object getResult() {
268 | return count;
269 | }
270 |
271 | @Override
272 | public String getFunction() {
273 | return COUNT;
274 | }
275 |
276 | }
277 |
278 | }
279 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/PivotFieldAction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import java.io.Serializable;
16 |
17 | import org.apache.wicket.AttributeModifier;
18 | import org.apache.wicket.Component;
19 | import org.apache.wicket.ajax.AjaxRequestTarget;
20 | import org.apache.wicket.ajax.markup.html.AjaxLink;
21 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
22 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.WindowClosedCallback;
23 | import org.apache.wicket.markup.html.link.AbstractLink;
24 | import org.apache.wicket.model.Model;
25 |
26 | import ro.fortsoft.wicket.pivot.PivotField.Area;
27 | import ro.fortsoft.wicket.pivot.web.AggregatorPanel;
28 | import ro.fortsoft.wicket.pivot.web.FieldCalculationPanel;
29 | import ro.fortsoft.wicket.pivot.web.PivotAreaPanel;
30 | import ro.fortsoft.wicket.pivot.web.PivotPanel;
31 |
32 | /**
33 | * @author Decebal Suiu
34 | */
35 | public abstract class PivotFieldAction implements Serializable {
36 |
37 | private static final long serialVersionUID = 1L;
38 |
39 | protected PivotField field;
40 | protected String name;
41 |
42 | // protected IResource image;
43 | // protected String tooltip;
44 |
45 | public PivotFieldAction(PivotField field) {
46 | this.field = field;
47 | }
48 |
49 | public abstract AbstractLink getLink(String id);
50 |
51 | public String getName() {
52 | return name;
53 | }
54 |
55 | /*
56 | * public IResource getImage() { return image; }
57 | *
58 | * public String getTooltip() { return tooltip; }
59 | */
60 |
61 | public static class Delete extends PivotFieldAction {
62 |
63 | private static final long serialVersionUID = 1L;
64 |
65 | public Delete(PivotField field) {
66 | super(field);
67 |
68 | name = "Delete";
69 | // image = new ContextRelativeResource("images/delete.gif");
70 | // tooltip = "Delete";
71 | }
72 |
73 | @Override
74 | public AbstractLink getLink(String id) {
75 | return new AjaxLink(id) {
76 |
77 | private static final long serialVersionUID = 1L;
78 |
79 | @Override
80 | public void onClick(AjaxRequestTarget target) {
81 | // TODO: implement
82 | }
83 |
84 | };
85 | }
86 |
87 | }
88 |
89 | public static class FieldCalculationAction extends PivotFieldAction {
90 |
91 | private PivotModel pivotModel;
92 |
93 | public FieldCalculationAction(PivotField field, PivotModel pivotModel) {
94 | super(field);
95 | this.pivotModel = pivotModel;
96 | name = "Calculation...";
97 | }
98 |
99 | private PivotModel getPivotModel(Component webComponent) {
100 | return webComponent.findParent(PivotPanel.class).getPivotModel();
101 | }
102 |
103 | private static final long serialVersionUID = 1L;
104 |
105 | private void openFieldCalculationDialog(final AjaxLink ajaxLink, AjaxRequestTarget target) {
106 | ModalWindow modal = ajaxLink.findParent(PivotAreaPanel.class).getModal();
107 | modal.setTitle("Calculation");
108 | final FieldCalculationPanel panel = new FieldCalculationPanel(modal.getContentId(), Model.of(field),
109 | Model.of(pivotModel));
110 | panel.setTitle(field.getTitle());
111 | panel.add(AttributeModifier.append("style", "padding: 10px;"));
112 | modal.setContent(panel);
113 | modal.setAutoSize(true);
114 | modal.setResizable(false);
115 | modal.show(target);
116 | modal.setWindowClosedCallback(new WindowClosedCallback() {
117 |
118 | private static final long serialVersionUID = 1L;
119 |
120 | @Override
121 | public void onClose(AjaxRequestTarget target) {
122 | if (!panel.isOkPressed()) {
123 | return;
124 | }
125 |
126 | target.add(ajaxLink.findParent(PivotAreaPanel.class));
127 |
128 | PivotModel pivotModel = getPivotModel(ajaxLink);
129 | PivotField pivotField = pivotModel.getField(field.getName());
130 | pivotField.setFieldCalculation(panel.getFieldCalculation());
131 | pivotField.setTitle(panel.getTitle());
132 | if (pivotModel.isAutoCalculate()) {
133 | ajaxLink.findParent(PivotPanel.class).compute(target);
134 | }
135 | }
136 | });
137 | }
138 |
139 | @Override
140 | public AbstractLink getLink(String id) {
141 | return new AjaxLink(id) {
142 |
143 | private static final long serialVersionUID = 1L;
144 |
145 | @Override
146 | public void onClick(AjaxRequestTarget target) {
147 | openFieldCalculationDialog(this, target);
148 | }
149 |
150 | };
151 | }
152 | }
153 |
154 | public static class AddNewFieldCalculationAction extends PivotFieldAction {
155 | private static final long serialVersionUID = 1L;
156 | private PivotModel model;
157 |
158 | public AddNewFieldCalculationAction(PivotField field, PivotModel model) {
159 | super(field);
160 | this.model = model;
161 | name = "Add calculation ...";
162 | }
163 |
164 | @Override
165 | public AbstractLink getLink(String id) {
166 | return new AjaxLink(id) {
167 | private static final long serialVersionUID = 1L;
168 |
169 | @Override
170 | public void onClick(AjaxRequestTarget target) {
171 | PivotField newField = new PivotField("", model.getFields().size());
172 | newField.setArea(Area.DATA);
173 | newField.setType(Double.class);
174 | newField.setTitle("Calculation");
175 | newField.setAggregator(null);
176 | newField.setFieldCalculation(FieldCalculation.get(FieldCalculation.PERCENT_OF));
177 | newField.getFieldCalculation().setFieldA(field);
178 | newField.getFieldCalculation().setFieldB(field);
179 | model.getFields().add(newField);
180 | new FieldCalculationAction(newField, model).openFieldCalculationDialog(this, target);
181 | }
182 | };
183 | }
184 | }
185 |
186 | public static class AggregatorAction extends PivotFieldAction {
187 |
188 | private static final long serialVersionUID = 1L;
189 |
190 | public AggregatorAction(PivotField field) {
191 | super(field);
192 |
193 | name = "Aggregator...";
194 | // image = new ContextRelativeResource("images/agregator.gif");
195 | // tooltip = "Delete";
196 | }
197 |
198 | @Override
199 | public AbstractLink getLink(String id) {
200 | return new AjaxLink(id) {
201 |
202 | private static final long serialVersionUID = 1L;
203 |
204 | @Override
205 | public void onClick(AjaxRequestTarget target) {
206 | ModalWindow modal = findParent(PivotAreaPanel.class).getModal();
207 | modal.setTitle("Aggregator");
208 | final AggregatorPanel panel = new AggregatorPanel(modal.getContentId(), Model.of(field));
209 | panel.add(AttributeModifier.append("style", "padding: 10px;"));
210 | modal.setContent(panel);
211 | modal.setAutoSize(true);
212 | modal.setResizable(false);
213 | modal.show(target);
214 | modal.setWindowClosedCallback(new WindowClosedCallback() {
215 |
216 | private static final long serialVersionUID = 1L;
217 |
218 | @Override
219 | public void onClose(AjaxRequestTarget target) {
220 | if (!panel.isOkPressed()) {
221 | return;
222 | }
223 |
224 | target.add(findParent(PivotAreaPanel.class));
225 | PivotModel pivotModel = getPivotModel();
226 | pivotModel.getField(field.getName()).setAggregator(panel.getAggregator());
227 | if (pivotModel.isAutoCalculate()) {
228 | findParent(PivotPanel.class).compute(target);
229 | }
230 |
231 | }
232 | });
233 | }
234 |
235 | private PivotModel getPivotModel() {
236 | return findParent(PivotPanel.class).getPivotModel();
237 | }
238 |
239 | };
240 | }
241 |
242 | }
243 |
244 | }
245 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotTable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import java.io.Serializable;
16 |
17 | import org.apache.wicket.AttributeModifier;
18 | import org.apache.wicket.Component;
19 | import org.apache.wicket.markup.html.WebMarkupContainer;
20 | import org.apache.wicket.markup.html.basic.Label;
21 | import org.apache.wicket.markup.html.panel.GenericPanel;
22 | import org.apache.wicket.markup.repeater.RepeatingView;
23 | import org.apache.wicket.model.Model;
24 | import org.apache.wicket.util.convert.IConverter;
25 |
26 | import ro.fortsoft.wicket.pivot.PivotField;
27 | import ro.fortsoft.wicket.pivot.PivotModel;
28 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel;
29 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.DataHeaderRenderCell;
30 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.DataRenderRow;
31 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.DataValueRenderCell;
32 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.GrandTotalHeaderRenderCell;
33 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.GrandTotalRenderRow;
34 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.GrandTotalRowHeaderRenderCell;
35 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.GrandTotalValueRenderCell;
36 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.HeaderRenderCell;
37 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.HeaderRenderRow;
38 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.HeaderValueRenderCell;
39 | import ro.fortsoft.wicket.pivot.PivotTableRenderModel.RenderCell;
40 |
41 | /**
42 | * @author Decebal Suiu
43 | */
44 | public class PivotTable extends GenericPanel {
45 |
46 | private static final long serialVersionUID = 1L;
47 |
48 | public PivotTable(String id, PivotModel pivotModel) {
49 | super(id, Model.of(pivotModel));
50 | }
51 |
52 | private Component applyRowColSpan(RenderCell cell, Component tmp) {
53 | if (cell.getColspan() > 1)
54 | tmp.add(AttributeModifier.append("colspan", cell.getColspan()));
55 | if (cell.getRowspan() > 1)
56 | tmp.add(AttributeModifier.append("rowspan", cell.getRowspan()));
57 | return tmp;
58 | }
59 |
60 | @Override
61 | protected void onInitialize() {
62 | super.onInitialize();
63 |
64 | PivotModel pivotModel = getModelObject();
65 | PivotTableRenderModel renderModel = PivotTableRenderModel.create(pivotModel);
66 |
67 | // rendering header
68 | RepeatingView column = new RepeatingView("header");
69 | add(column);
70 |
71 | Component tmp = null;
72 | for (HeaderRenderRow row : renderModel.getHeaderRows()) {
73 | // rendering row header (first columns)
74 | WebMarkupContainer tr = new WebMarkupContainer(column.newChildId());
75 | column.add(tr);
76 | RepeatingView rowHeader = new RepeatingView("rowHeader");
77 | tr.add(rowHeader);
78 |
79 | for (HeaderRenderCell cell : row.getRowHeader()) {
80 | if (cell.getPivotField() == null) {
81 | // rendering an empty cell
82 | tmp = new Label(rowHeader.newChildId(), "");
83 | tmp.add(AttributeModifier.append("class", "empty"));
84 | applyRowColSpan(cell, tmp);
85 | rowHeader.add(tmp);
86 | } else {
87 | // rendering row field
88 | tmp = createTitleLabel(rowHeader.newChildId(), cell.getPivotField());
89 | applyRowColSpan(cell, tmp);
90 | rowHeader.add(tmp);
91 | }
92 | }
93 |
94 | // rendering column keys
95 | RepeatingView value = new RepeatingView("value");
96 | tr.add(value);
97 | for (RenderCell cell : row.getValueCells()) {
98 | if (cell instanceof HeaderValueRenderCell) {
99 | HeaderValueRenderCell headerValueRenderCell = (HeaderValueRenderCell) cell;
100 | tmp = createValueLabel(value.newChildId(), headerValueRenderCell.getRawValue(),
101 | headerValueRenderCell.getPivotField());
102 | applyRowColSpan(cell, tmp);
103 | value.add(tmp);
104 | } else {
105 | HeaderRenderCell headerRenderCell = (HeaderRenderCell) cell;
106 | tmp = createTitleLabel(value.newChildId(), headerRenderCell.getPivotField());
107 | applyRowColSpan(cell, tmp);
108 | value.add(tmp);
109 | }
110 | }
111 |
112 | // rendering grand total column
113 | RepeatingView grandTotalColumn = new RepeatingView("grandTotalColumn");
114 | for (RenderCell cell : row.getGrandTotalColumn()) {
115 | if (cell instanceof GrandTotalHeaderRenderCell) {
116 | GrandTotalHeaderRenderCell grandTotalHeaderRenderCell = (GrandTotalHeaderRenderCell) cell;
117 | if (grandTotalHeaderRenderCell.getRawValue() != null) {
118 | tmp = new Label(grandTotalColumn.newChildId(), grandTotalHeaderRenderCell.getRawValue()
119 | .toString());
120 | applyRowColSpan(cell, tmp);
121 | grandTotalColumn.add(tmp);
122 | } else {
123 | tmp = new WebMarkupContainer(grandTotalColumn.newChildId());
124 | applyRowColSpan(cell, tmp);
125 | tmp.add(AttributeModifier.append("class", "empty"));
126 | grandTotalColumn.add(tmp);
127 | }
128 | } else {
129 | HeaderRenderCell headerCell = (HeaderRenderCell) cell;
130 | tmp = createTitleLabel(value.newChildId(), headerCell.getPivotField());
131 | applyRowColSpan(cell, tmp);
132 | grandTotalColumn.add(tmp);
133 | }
134 | }
135 | grandTotalColumn.setVisible(row.getGrandTotalColumn().size() > 0);
136 | tr.add(grandTotalColumn);
137 | }
138 |
139 | // rendering rows
140 | RepeatingView row = new RepeatingView("row");
141 | add(row);
142 | for (DataRenderRow renderRow : renderModel.getValueRows()) {
143 | WebMarkupContainer tr = new WebMarkupContainer(row.newChildId());
144 | row.add(tr);
145 | RepeatingView rowHeader = new RepeatingView("rowHeader");
146 | tr.add(rowHeader);
147 |
148 | for (DataHeaderRenderCell cell : renderRow.getRowHeader()) {
149 | tmp = createValueLabel(rowHeader.newChildId(), cell.getRawValue(), cell.getPivotField());
150 | applyRowColSpan(cell, tmp);
151 | rowHeader.add(tmp);
152 | }
153 |
154 | RepeatingView value = new RepeatingView("value");
155 | tr.add(value);
156 |
157 | for (RenderCell cell : renderRow.getValue()) {
158 | if (cell instanceof DataValueRenderCell) {
159 | tmp = createValueLabel(value.newChildId(), cell.getRawValue(), cell.getPivotField());
160 | applyRowColSpan(cell, tmp);
161 | value.add(tmp);
162 | } else {
163 | GrandTotalValueRenderCell grandTotalCell = (GrandTotalValueRenderCell) cell;
164 | tmp = createGrandTotalLabel(value.newChildId(), grandTotalCell.getRawValue(), grandTotalCell.isForRow());
165 | applyRowColSpan(cell, tmp);
166 | tmp.add(AttributeModifier.append("class", "grand-total"));
167 | value.add(tmp);
168 | }
169 | }
170 | }
171 |
172 | WebMarkupContainer grandTotalRow = new WebMarkupContainer("grandTotalRow");
173 | grandTotalRow.setVisible(renderModel.getGrandTotalRows().size() > 0);
174 | add(grandTotalRow);
175 | /*
176 | * We currently expect exactly one GrantTotalRenderRow, therefor we dont
177 | * need a repeating viewer
178 | */
179 | for (GrandTotalRenderRow grantTotalRenderRow : renderModel.getGrandTotalRows()) {
180 | for (GrandTotalRowHeaderRenderCell cell : grantTotalRenderRow.getRowHeader()) {
181 | Label grandTotalRowHeader = new Label("rowHeader", "Grand Total");
182 | applyRowColSpan(cell, grandTotalRowHeader);
183 | grandTotalRow.add(grandTotalRowHeader);
184 | }
185 |
186 | RepeatingView value = new RepeatingView("value");
187 | grandTotalRow.add(value);
188 | for (GrandTotalValueRenderCell cell : grantTotalRenderRow.getValue()) {
189 | tmp = createGrandTotalLabel(value.newChildId(), cell.getRawValue(), cell.isForRow());
190 | value.add(tmp);
191 | }
192 | }
193 | }
194 |
195 | /**
196 | * Retrieves a name that display the pivot table title (for fields on ROW
197 | * and DATA areas)
198 | */
199 | protected Label createTitleLabel(String id, PivotField pivotField) {
200 | String title = pivotField.getTitle();
201 | if (pivotField.getArea().equals(PivotField.Area.DATA)) {
202 | title += " (" + pivotField.getCalculationDescription() + ")";
203 | }
204 |
205 | return new Label(id, title);
206 | }
207 |
208 | protected Label createValueLabel(String id, Object value, final PivotField pivotField) {
209 | return new Label(id, Model.of((Serializable) value)) {
210 | private static final long serialVersionUID = 1L;
211 |
212 | @SuppressWarnings("unchecked")
213 | @Override
214 | public IConverter getConverter(Class type) {
215 | IConverter converter = (IConverter) pivotField.getConverter();
216 | if (converter != null) {
217 | return converter;
218 | }
219 |
220 | return super.getConverter(type);
221 | }
222 |
223 | };
224 | }
225 |
226 | protected Label createGrandTotalLabel(String id, Object value, boolean forRow) {
227 | return new Label(id, Model.of((Serializable) value));
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/config/PivotConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, 2013, 2014 Decebal Suiu, Emmeran Seehuber
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.config;
14 |
15 | import ro.fortsoft.wicket.pivot.Aggregator;
16 | import ro.fortsoft.wicket.pivot.FieldCalculation;
17 | import ro.fortsoft.wicket.pivot.PivotField;
18 | import ro.fortsoft.wicket.pivot.PivotField.Area;
19 | import ro.fortsoft.wicket.pivot.PivotModel;
20 |
21 | import java.io.Serializable;
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | /**
26 | * A stored pivot table configuration. The structure of this class and its child
27 | * PivotConfigField is guaranteed to be stable across releases. Serialize this
28 | * class using the Java serializers or whatever you like (e.g. GSON)
29 | *
30 | */
31 | public class PivotConfig implements Serializable {
32 | private static final long serialVersionUID = 1L;
33 |
34 | /**
35 | * Name of the configuration, to show in the UI.
36 | */
37 | private String name;
38 | private boolean showGrandTotalForColumn;
39 | private boolean showGrandTotalForRow;
40 | private boolean autoCalculate;
41 |
42 | /**
43 | * The fields are stored as an array - so that this can be correctly be
44 | * stored/restored with GSON
45 | */
46 | private PivotConfigField[] pivotConfigFields = new PivotConfigField[0];
47 |
48 | /**
49 | * Represents the configuration state of a PivotField
50 | */
51 | public static class PivotConfigField implements Serializable {
52 | private static final long serialVersionUID = 1L;
53 | private String name;
54 | private String title;
55 | private Area area;
56 | private int areaIndex;
57 | private String aggreatorFunction;
58 | private String fieldCalculationFunction;
59 | private String[] fieldCalculationFields;
60 | private int sortOrder;
61 |
62 | public String getName() {
63 | return name;
64 | }
65 |
66 | public void setName(String name) {
67 | this.name = name;
68 | }
69 |
70 | public Area getArea() {
71 | return area;
72 | }
73 |
74 | public void setArea(Area area) {
75 | this.area = area;
76 | }
77 |
78 | public int getAreaIndex() {
79 | return areaIndex;
80 | }
81 |
82 | public void setAreaIndex(int areaIndex) {
83 | this.areaIndex = areaIndex;
84 | }
85 |
86 | public String getAggreatorFunction() {
87 | return aggreatorFunction;
88 | }
89 |
90 | public void setAggreatorFunction(String aggreatorFunction) {
91 | this.aggreatorFunction = aggreatorFunction;
92 | }
93 |
94 | public String getFieldCalculationFunction() {
95 | return fieldCalculationFunction;
96 | }
97 |
98 | public void setFieldCalculationFunction(String fieldCalculationFunction) {
99 | this.fieldCalculationFunction = fieldCalculationFunction;
100 | }
101 |
102 | public String[] getFieldCalculationFields() {
103 | return fieldCalculationFields;
104 | }
105 |
106 | public void setFieldCalculationFields(String[] fieldCalculationFields) {
107 | this.fieldCalculationFields = fieldCalculationFields;
108 | }
109 |
110 | public int getSortOrder() {
111 | return sortOrder;
112 | }
113 |
114 | public void setSortOrder(int sortOrder) {
115 | this.sortOrder = sortOrder;
116 | }
117 |
118 | public String getTitle() {
119 | return title;
120 | }
121 |
122 | public void setTitle(String title) {
123 | this.title = title;
124 | }
125 |
126 | /**
127 | * Store the state of the of the pivot field in this instance
128 | *
129 | * @param field
130 | */
131 | public void storeFieldState(PivotField field) {
132 | /* Plain Fields */
133 | this.name = field.getName();
134 | this.title = field.getTitle();
135 | this.area = field.getArea();
136 | this.areaIndex = field.getAreaIndex();
137 | this.aggreatorFunction = null;
138 | this.fieldCalculationFunction = null;
139 | this.fieldCalculationFields = null;
140 | this.sortOrder = field.getSortOrder();
141 |
142 | /* Functions */
143 | if (field.getAggregator() != null)
144 | this.aggreatorFunction = field.getAggregator().getFunction();
145 | if (field.getFieldCalculation() != null) {
146 | this.fieldCalculationFunction = field.getFieldCalculation().getFunction();
147 | this.fieldCalculationFields = new String[] { getFieldName(field.getFieldCalculation().getFieldA()),
148 | getFieldName(field.getFieldCalculation().getFieldB()) };
149 | }
150 | }
151 |
152 | private static String getFieldName(PivotField pivotField) {
153 | if (pivotField == null)
154 | return null;
155 | return pivotField.getName();
156 | }
157 |
158 | /**
159 | * Restore the state of the pivot field from this instance.
160 | *
161 | * The name *MUST* be equal!
162 | */
163 | public void restoreFieldState(PivotField field, PivotModel pivotModel) {
164 | if (!field.getName().equals(name))
165 | throw new IllegalArgumentException(field.getName() + " != " + name);
166 | /* Plain Properties */
167 | field.setTitle(this.title);
168 | field.setArea(this.getArea());
169 | field.setAreaIndex(this.getAreaIndex());
170 | field.setAggregator(null);
171 | field.setFieldCalculation(null);
172 | field.setSortOrder(this.getSortOrder());
173 |
174 | /* Functions */
175 | if (this.aggreatorFunction != null)
176 | field.setAggregator(Aggregator.get(this.aggreatorFunction));
177 | if (this.fieldCalculationFunction != null) {
178 | FieldCalculation fieldCalculation = FieldCalculation.get(this.fieldCalculationFunction);
179 | field.setFieldCalculation(fieldCalculation);
180 | fieldCalculation.setFieldA(findField(this.fieldCalculationFields, 0, pivotModel));
181 | fieldCalculation.setFieldB(findField(this.fieldCalculationFields, 1, pivotModel));
182 | }
183 | }
184 |
185 | private static PivotField findField(String[] fieldCalculationFields, int index, PivotModel pivotModel) {
186 | if (fieldCalculationFields == null)
187 | return null;
188 | if (index >= fieldCalculationFields.length)
189 | return null;
190 | String fieldName = fieldCalculationFields[index];
191 | if (fieldName == null)
192 | return null;
193 | return pivotModel.getField(fieldName);
194 | }
195 | }
196 |
197 | public String getName() {
198 | return name;
199 | }
200 |
201 | public void setName(String name) {
202 | this.name = name;
203 | }
204 |
205 | /*
206 | * @internal Only for the serializers
207 | */
208 | public PivotConfigField[] getPivotConfigFields() {
209 | return pivotConfigFields;
210 | }
211 |
212 | /*
213 | * @internal Only for the serializers
214 | */
215 | public void setPivotConfigFields(PivotConfigField[] pivotConfigFields) {
216 | this.pivotConfigFields = pivotConfigFields;
217 | }
218 |
219 | public boolean isShowGrandTotalForColumn() {
220 | return showGrandTotalForColumn;
221 | }
222 |
223 | public void setShowGrandTotalForColumn(boolean showGrandTotalForColumn) {
224 | this.showGrandTotalForColumn = showGrandTotalForColumn;
225 | }
226 |
227 | public boolean isShowGrandTotalForRow() {
228 | return showGrandTotalForRow;
229 | }
230 |
231 | public void setShowGrandTotalForRow(boolean showGrandTotalForRow) {
232 | this.showGrandTotalForRow = showGrandTotalForRow;
233 | }
234 |
235 | public boolean isAutoCalculate() {
236 | return autoCalculate;
237 | }
238 |
239 | public void setAutoCalculate(boolean autoCalculate) {
240 | this.autoCalculate = autoCalculate;
241 | }
242 |
243 | /**
244 | * Store the model state in this configuration instance
245 | *
246 | * @param model
247 | */
248 | public void storeModelState(PivotModel model) {
249 | this.showGrandTotalForColumn = model.isShowGrandTotalForColumn();
250 | this.showGrandTotalForRow = model.isShowGrandTotalForRow();
251 | this.autoCalculate = model.isAutoCalculate();
252 |
253 | List fields = new ArrayList<>();
254 | for (PivotField field : model.getFields()) {
255 | /* We don't store unused fields */
256 | if (field.getArea() == Area.UNUSED)
257 | continue;
258 |
259 | PivotConfigField configField = new PivotConfigField();
260 | configField.storeFieldState(field);
261 | fields.add(configField);
262 | }
263 | pivotConfigFields = fields.toArray(new PivotConfigField[fields.size()]);
264 | }
265 |
266 | public void restoreModelState(PivotModel model) {
267 | /*
268 | * Global model state
269 | */
270 | model.setShowGrandTotalForColumn(this.showGrandTotalForColumn);
271 | model.setShowGrandTotalForRow(this.showGrandTotalForRow);
272 | model.setAutoCalculate(this.autoCalculate);
273 |
274 | /*
275 | * We set all fields to unused, as we don't save unused fields, so thats
276 | * the default value
277 | */
278 | List fieldsToDelete = new ArrayList<>();
279 | for (PivotField field : model.getFields()) {
280 | /*
281 | * We must delete all field calculations, as this are additional
282 | * fields, which the user can add. Otherwise they will grow when we
283 | * load the same configuration with field calculations again and
284 | * again
285 | */
286 | if (field.getFieldCalculation() != null)
287 | fieldsToDelete.add(field);
288 | field.setArea(Area.UNUSED);
289 | }
290 |
291 | /*
292 | * Now delete all field calculation fields
293 | */
294 | for (PivotField field : fieldsToDelete)
295 | model.getFields().remove(field);
296 |
297 | /*
298 | * And restore the fields
299 | */
300 | for (PivotConfigField configField : this.pivotConfigFields) {
301 | PivotField field = null;
302 | if (configField.getFieldCalculationFunction() != null) {
303 | /*
304 | * Special field for field calculation
305 | */
306 | field = new PivotField("", model.getFields().size());
307 | field.setType(Double.class);
308 | model.getFields().add(field);
309 | } else
310 | field = model.getField(configField.getName());
311 |
312 | /*
313 | * Has the field been delete from the model?
314 | */
315 | if (field == null)
316 | /*
317 | * Yes, ignore it
318 | */
319 | continue;
320 | configField.restoreFieldState(field, model);
321 | }
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/DefaultPivotModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot;
14 |
15 | import org.apache.commons.collections.CollectionUtils;
16 | import org.apache.commons.collections.map.MultiKeyMap;
17 | import ro.fortsoft.wicket.pivot.tree.Node;
18 | import ro.fortsoft.wicket.pivot.tree.Tree;
19 | import ro.fortsoft.wicket.pivot.tree.TreeHelper;
20 |
21 | import java.util.*;
22 |
23 | /**
24 | * @author Decebal Suiu
25 | */
26 | public class DefaultPivotModel implements PivotModel {
27 |
28 | private static final long serialVersionUID = 1L;
29 |
30 | private PivotDataSource dataSource;
31 | private List fields;
32 | private Tree columnsHeaderTree;
33 | private Tree rowsHeaderTree;
34 | private List calculatedData; // or use a MultiValueMap from apache commons
35 |
36 | private boolean showGrandTotalForColumn;
37 | private boolean showGrandTotalForRow;
38 | private boolean autoCalculate;
39 |
40 | public DefaultPivotModel(PivotDataSource dataSource) {
41 | this.dataSource = dataSource;
42 |
43 | // init fields
44 | int count = dataSource.getFieldCount();
45 | fields = new ArrayList<>(count);
46 | for (int i = 0; i < count; i++) {
47 | PivotField field = new PivotField(dataSource.getFieldName(i), i);
48 | field.setTitle(field.getName());
49 | field.setArea(PivotField.Area.UNUSED);
50 | field.setType(dataSource.getFieldType(i));
51 | fields.add(field);
52 | }
53 | }
54 |
55 | @Override
56 | public List getFields() {
57 | return fields;
58 | }
59 |
60 | @Override
61 | public PivotField getField(String name) {
62 | for (PivotField field : fields) {
63 | if (field.getName().equals(name)) {
64 | return field;
65 | }
66 | }
67 |
68 | return null;
69 | }
70 |
71 | @Override
72 | public PivotField getField(int index) {
73 | for (PivotField field : fields) {
74 | if (field.getIndex() == index) {
75 | return field;
76 | }
77 | }
78 |
79 | return null;
80 | }
81 |
82 | @Override
83 | public List getFields(PivotField.Area area) {
84 | List areaFields = new ArrayList<>();
85 | List fields = getFields();
86 | for (PivotField field : fields) {
87 | if (field.getArea().equals(area)) {
88 | areaFields.add(field);
89 | }
90 | }
91 | Collections.sort(areaFields);
92 |
93 | return areaFields;
94 | }
95 |
96 | @Override
97 | public PivotDataSource getDataSource() {
98 | return dataSource;
99 | }
100 |
101 | @Override
102 | public void calculate() {
103 | long start = System.currentTimeMillis();
104 | rowsHeaderTree = null;
105 | columnsHeaderTree = null;
106 | getRowsHeaderTree();
107 | long t1 = System.currentTimeMillis();
108 | System.out.println("created rowsHeaderTree in " + (t1 - start));
109 | getColumnsHeaderTree();
110 | long t2 = System.currentTimeMillis();
111 | System.out.println("created columnsHeaderTree in " + (t2 - t1));
112 |
113 | t1 = System.currentTimeMillis();
114 | List dataFields = getFields(PivotField.Area.DATA);
115 | calculatedData = new ArrayList<>();
116 | for (PivotField field : dataFields) {
117 | field.resetCalculation();
118 | calculatedData.add(getData(field));
119 | }
120 | t2 = System.currentTimeMillis();
121 | System.out.println("filled calculatedData in " + (t2 - t1));
122 | long stop = System.currentTimeMillis();
123 | System.out.println("calculated in " + (stop- start));
124 | System.out.println("calculatedData = " + calculatedData);
125 | // getValues(field, filter)
126 | }
127 |
128 | /*
129 | * TODO: trebuie imbunatatita metoda asta. Am facut un test pe un tabel
130 | * cu 4500 inregistrari si 7 coloane (nextreports downloads). Am observat ca
131 | * la 86 chei pe row si 212 chei pe column am 18.232 (86 x 212) combinatii.
132 | * Daca in getValues se sta 3,25 ms (cum am obtinut) rezulta un total de
133 | * 5576 ms. Cred ca ar trebuii sa parcurg o singura data inregistrarile din baza.
134 | */
135 | private MultiKeyMap getData(PivotField dataField) {
136 | MultiKeyMap data = new MultiKeyMap();
137 | List> rowKeys = getRowKeys();
138 | System.out.println("rowKeys.size() = " + rowKeys.size());
139 | List> columnKeys = getColumnKeys();
140 | System.out.println("columnKeys.size() = " + columnKeys.size());
141 |
142 | List rowFields = getFields(PivotField.Area.ROW);
143 | List columnFields = getFields(PivotField.Area.COLUMN);
144 | for (List rowKey : rowKeys) {
145 | for (List columnKey : columnKeys) {
146 | Map rowFilter = getFilter(rowFields, rowKey);
147 | Map columnFilter = getFilter(columnFields, columnKey);
148 | final Map filter = new HashMap<>(rowFilter);
149 | filter.putAll(columnFilter);
150 | List values = getValues(dataField, filter);
151 | if (!CollectionUtils.isEmpty(values) || dataField.getFieldCalculation()!=null) {
152 | /*
153 | System.out.println("filter = " + filter);
154 | System.out.println("values = " + values);
155 | System.out.println(values.size());
156 | */
157 | Object summary = PivotUtils.getSummary(dataField, values, field -> {
158 | List fieldValues = getValues(field, filter);
159 | return field.getAggregator().init().addAll(fieldValues).getResult();
160 | });
161 | // System.out.println("summary = " + summary);
162 | data.put(rowKey, columnKey, summary);
163 | }
164 | }
165 | }
166 |
167 | return data;
168 | }
169 |
170 | @Override
171 | public Tree getColumnsHeaderTree() {
172 | if (columnsHeaderTree == null) {
173 | Node root = new Node();
174 | insertChildren(root, getFields(PivotField.Area.COLUMN));
175 | columnsHeaderTree = new Tree(root);
176 | }
177 |
178 | return columnsHeaderTree;
179 | }
180 |
181 | @Override
182 | public Tree getRowsHeaderTree() {
183 | if (rowsHeaderTree == null) {
184 | Node root = new Node();
185 | insertChildren(root, getFields(PivotField.Area.ROW));
186 | rowsHeaderTree = new Tree(root);
187 | }
188 |
189 | return rowsHeaderTree;
190 | }
191 |
192 | @Override
193 | public List> getRowKeys() {
194 | return TreeHelper.getLeafValues(getRowsHeaderTree().getRoot());
195 | }
196 |
197 | @Override
198 | public List> getColumnKeys() {
199 | return TreeHelper.getLeafValues(getColumnsHeaderTree().getRoot());
200 | }
201 |
202 | @Override
203 | public Object getValueAt(PivotField dataField, List rowKey, List columnKey) {
204 | int index = getFields(PivotField.Area.DATA).indexOf(dataField);
205 | return calculatedData.get(index).get(rowKey, columnKey);
206 | }
207 |
208 | @Override
209 | public boolean isShowGrandTotalForColumn() {
210 | return showGrandTotalForColumn;
211 | }
212 |
213 | @Override
214 | public void setShowGrandTotalForColumn(boolean showGrandTotalForColumn) {
215 | this.showGrandTotalForColumn = showGrandTotalForColumn;
216 | }
217 |
218 | @Override
219 | public boolean isShowGrandTotalForRow() {
220 | return showGrandTotalForRow;
221 | }
222 |
223 | @Override
224 | public void setShowGrandTotalForRow(boolean showGrandTotalForRow) {
225 | this.showGrandTotalForRow = showGrandTotalForRow;
226 | }
227 |
228 | @Override
229 | public boolean isAutoCalculate() {
230 | return autoCalculate;
231 | }
232 |
233 | @Override
234 | public void setAutoCalculate(boolean autoCalculate) {
235 | this.autoCalculate = autoCalculate;
236 | }
237 |
238 | @Override
239 | public String toString() {
240 | return "DefaultPivotModel [fields=" + fields + "]";
241 | }
242 |
243 | private void insertChildren(Node node, List fields) {
244 | // System.out.println("DefaultPivotModel.insertChildren()");
245 | Set values = getPossibleChildrenValues(node, fields);
246 | if (CollectionUtils.isEmpty(values)) {
247 | return;
248 | }
249 |
250 | for (Object value : values) {
251 | node.insert(value);
252 | }
253 |
254 | for (Node child : node.getChildren()) {
255 | insertChildren(child, fields);
256 | }
257 | }
258 |
259 | private Set getPossibleChildrenValues(Node node, List fields) {
260 | int level = node.getLevel();
261 | // System.out.println("level = " + level);
262 | // System.out.println("fields.size = " + fields.size());
263 | if (fields.size() <= level) {
264 | return null;
265 | }
266 |
267 | PivotField nextField = fields.get(level);
268 | // System.out.println("nextField = " + nextField);
269 | Map filter = getFilter(fields, node.getPathValues());
270 | // System.out.println("filter = " + filter);
271 | Set values = getUniqueValues(nextField, filter);
272 | // System.out.println("values = " + values);
273 |
274 | return values;
275 | }
276 |
277 | /*
278 | * Retrieves the values for a data field using a filter.
279 | */
280 | private List getValues(PivotField field, Map filter) {
281 | if (field.getFieldCalculation() != null)
282 | return Collections.emptyList();
283 | // long start = System.currentTimeMillis();
284 | List values = new ArrayList<>();
285 | final int fieldIndex = field.getIndex();
286 | final int rowCount = dataSource.getRowCount();
287 |
288 | if (filter.isEmpty()) {
289 | /*
290 | * No filter -> Just add the values
291 | */
292 | for (int i = 0; i < rowCount; i++) {
293 | values.add(dataSource.getValueAt(i, fieldIndex));
294 | }
295 | }
296 | else {
297 | /*
298 | * Add all values matching the filter
299 | */
300 | for (int i = 0; i < rowCount; i++) {
301 | if (acceptValue(i, filter)) {
302 | values.add(dataSource.getValueAt(i, fieldIndex));
303 | }
304 | }
305 | }
306 | // long stop = System.currentTimeMillis();
307 | // System.out.println("getValues in " + (stop - start));
308 |
309 | return values;
310 | }
311 |
312 | /*
313 | * Retrieves a filter for filtering data source (raw data). The size of fields must be equals with
314 | * the size of values. The key in map is the field index.
315 | */
316 | private Map getFilter(List fields, List values) {
317 | // long start = System.currentTimeMillis();
318 | Map filter = new HashMap<>();
319 | for (int i = 0; i < values.size(); i++) {
320 | int fieldIndex = fields.get(i).getIndex();
321 | // System.out.println(fieldIndex);
322 | filter.put(fieldIndex, values.get(i));
323 | }
324 | // long stop = System.currentTimeMillis();
325 | // System.out.println("getFilter in " + (stop - start));
326 |
327 | return filter;
328 | }
329 |
330 | private Set getUniqueValues(PivotField field, Map filter) {
331 | List values = getValues(field, filter);
332 |
333 | int sortOrder = field.getSortOrder();
334 | if (sortOrder != PivotField.SORT_ORDER_UNSORTED) {
335 | /*
336 | * We need to get the value set and sort it. We can not use a
337 | * TreeSet here as it does not allow null values.
338 | */
339 | Set valueSet = new HashSet<>(values);
340 | List valuesToOrder = new ArrayList<>(valueSet);
341 | final int sign = sortOrder == PivotField.SORT_ORDER_ASCENDING ? 1
342 | : sortOrder == PivotField.SORT_ORDER_DESCENDING ? -1 : 1;
343 | valuesToOrder.sort((o1, o2) -> {
344 | if (o1 == o2)
345 | return 0;
346 | if (o1 == null)
347 | return sign * -1;
348 | if (o2 == null)
349 | return sign;
350 | return sign * ((Comparable) o1).compareTo(o2);
351 | });
352 |
353 | return new LinkedHashSet<>(valuesToOrder);
354 | }
355 |
356 | return new LinkedHashSet<>(values);
357 | }
358 |
359 | private boolean acceptValue(int row, Map filter) {
360 | boolean accept = true;
361 | Set keys = filter.keySet();
362 | Object value = null;
363 | for (int index : keys) {
364 | value = dataSource.getValueAt(row, fields.get(index));
365 | Object filterValue = filter.get(index);
366 | if (!Objects.equals(filterValue, value)) {
367 | return false;
368 | }
369 | }
370 |
371 | return accept;
372 | }
373 |
374 | }
375 |
--------------------------------------------------------------------------------
/wicket-pivot/src/main/java/ro/fortsoft/wicket/pivot/web/PivotPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Decebal Suiu
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
5 | * the License. You may obtain a copy of the License in the LICENSE file, or at:
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package ro.fortsoft.wicket.pivot.web;
14 |
15 | import java.io.ByteArrayOutputStream;
16 | import java.io.IOException;
17 | import java.util.List;
18 |
19 | import org.apache.wicket.AttributeModifier;
20 | import org.apache.wicket.ajax.AjaxRequestTarget;
21 | import org.apache.wicket.ajax.markup.html.AjaxLink;
22 | import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
23 | import org.apache.wicket.event.IEvent;
24 | import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
25 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
26 | import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.WindowClosedCallback;
27 | import org.apache.wicket.markup.html.WebMarkupContainer;
28 | import org.apache.wicket.markup.html.basic.Label;
29 | import org.apache.wicket.markup.html.link.Link;
30 | import org.apache.wicket.markup.html.panel.GenericPanel;
31 | import org.apache.wicket.markup.repeater.RepeatingView;
32 | import org.apache.wicket.model.AbstractReadOnlyModel;
33 | import org.apache.wicket.model.IModel;
34 | import org.apache.wicket.model.Model;
35 | import org.apache.wicket.model.PropertyModel;
36 | import org.apache.wicket.model.StringResourceModel;
37 | import org.apache.wicket.request.cycle.RequestCycle;
38 | import org.apache.wicket.request.handler.resource.ResourceRequestHandler;
39 | import org.apache.wicket.request.resource.ByteArrayResource;
40 |
41 | import ro.fortsoft.wicket.pivot.DefaultPivotFieldActionsFactory;
42 | import ro.fortsoft.wicket.pivot.DefaultPivotModel;
43 | import ro.fortsoft.wicket.pivot.PivotDataSource;
44 | import ro.fortsoft.wicket.pivot.PivotField;
45 | import ro.fortsoft.wicket.pivot.PivotFieldActionsFactory;
46 | import ro.fortsoft.wicket.pivot.PivotModel;
47 | import ro.fortsoft.wicket.pivot.config.IPivotConfigStorage;
48 | import ro.fortsoft.wicket.pivot.exporter.PivotCsvExporter;
49 | import ro.fortsoft.wicket.pivot.exporter.PivotExporter;
50 |
51 | /**
52 | * @author Decebal Suiu
53 | */
54 | public class PivotPanel extends GenericPanel {
55 |
56 | private final class ButtonCssClassModel extends AbstractReadOnlyModel {
57 | private static final long serialVersionUID = 1L;
58 |
59 | @Override
60 | public String getObject() {
61 | return verify() ? "btn-success" : "btn-success disabled";
62 | }
63 | }
64 |
65 | private static final long serialVersionUID = 1L;
66 |
67 | private WebMarkupContainer areasContainer;
68 | private PivotModel pivotModel;
69 | private PivotTable pivotTable;
70 | private AjaxLink computeLink;
71 | private WebMarkupContainer downloadContainer;
72 | private PivotExporter[] pivotExporters = new PivotExporter[] { new PivotCsvExporter() };
73 | // TODO: requires Serializable?!
74 | private PivotFieldActionsFactory pivotFieldActionsFactory;
75 | private String pivotExportFilename = "pivottable";
76 | private IPivotConfigStorage pivotConfigStorage;
77 |
78 | private ModalWindow modal;
79 |
80 | public PivotPanel(String id, PivotDataSource pivotDataSource) {
81 | super(id, Model.of(pivotDataSource));
82 | }
83 |
84 | @Override
85 | protected void onInitialize() {
86 | super.onInitialize();
87 |
88 | // create a pivot model
89 | pivotModel = createPivotModel(getModelObject());
90 |
91 | // create pivot field action factory
92 | pivotFieldActionsFactory = createPivotFieldActionsFactory();
93 |
94 | pivotModel.calculate();
95 |
96 | areasContainer = new WebMarkupContainer("areas");
97 | areasContainer.setOutputMarkupId(true);
98 | add(areasContainer);
99 |
100 | RepeatingView areaRepeater = new RepeatingView("area");
101 | areasContainer.add(areaRepeater);
102 | List areas = PivotField.Area.getValues();
103 | for (PivotField.Area area : areas) {
104 | areaRepeater.add(new PivotAreaPanel(areaRepeater.newChildId(), area));
105 | }
106 |
107 | pivotTable = createPivotTabel("pivotTable", pivotModel);
108 | add(pivotTable);
109 |
110 | modal = new ModalWindow("modal");
111 | modal.setAutoSize(true);
112 | add(modal);
113 |
114 | AjaxLink configStoreButton = new AjaxLink("configStoreButton") {
115 | private static final long serialVersionUID = 1L;
116 |
117 | @Override
118 | public void onClick(AjaxRequestTarget target) {
119 | modal.setTitle("Configuration");
120 | modal.setContent(new PivotConfigStoragePanel(ModalWindow.CONTENT_ID, pivotModel, pivotConfigStorage));
121 | modal.setAutoSize(true);
122 | modal.show(target);
123 | modal.setWindowClosedCallback(new WindowClosedCallback() {
124 | private static final long serialVersionUID = 1L;
125 |
126 | @Override
127 | public void onClose(AjaxRequestTarget target) {
128 | target.add(PivotPanel.this);
129 | if (pivotModel.isAutoCalculate())
130 | compute(target);
131 | computeLink.setVisible(!pivotModel.isAutoCalculate());
132 | }
133 | });
134 | }
135 |
136 | @Override
137 | public boolean isVisible() {
138 | return super.isVisible() && pivotConfigStorage != null;
139 | }
140 | };
141 | add(configStoreButton);
142 |
143 | AjaxCheckBox showGrandTotalForColumnCheckBox = new AjaxCheckBox("showGrandTotalForColumn",
144 | new PropertyModel<>(this, "pivotModel.showGrandTotalForColumn")) {
145 |
146 | private static final long serialVersionUID = 1L;
147 |
148 | @Override
149 | protected void onUpdate(AjaxRequestTarget target) {
150 | if (pivotModel.isAutoCalculate()) {
151 | compute(target);
152 | }
153 | }
154 |
155 | };
156 | add(showGrandTotalForColumnCheckBox);
157 |
158 | AjaxCheckBox showGrandTotalForRowCheckBox = new AjaxCheckBox("showGrandTotalForRow",
159 | new PropertyModel<>(this, "pivotModel.showGrandTotalForRow")) {
160 |
161 | private static final long serialVersionUID = 1L;
162 |
163 | @Override
164 | protected void onUpdate(AjaxRequestTarget target) {
165 | if (pivotModel.isAutoCalculate()) {
166 | compute(target);
167 | }
168 | }
169 |
170 | };
171 | add(showGrandTotalForRowCheckBox);
172 |
173 | AjaxCheckBox autoCalculateCheckBox = new AjaxCheckBox("autoCalculate", new PropertyModel<>(this,
174 | "pivotModel.autoCalculate")) {
175 |
176 | private static final long serialVersionUID = 1L;
177 |
178 | @Override
179 | protected void onUpdate(AjaxRequestTarget target) {
180 | computeLink.setVisible(!pivotModel.isAutoCalculate());
181 | target.add(computeLink);
182 |
183 | if (pivotModel.isAutoCalculate() && !pivotTable.isVisible()) {
184 | compute(target);
185 | }
186 | }
187 |
188 | };
189 | add(autoCalculateCheckBox);
190 |
191 | computeLink = new IndicatingAjaxLink("compute") {
192 |
193 | private static final long serialVersionUID = 1L;
194 |
195 | @Override
196 | public void onClick(AjaxRequestTarget target) {
197 | compute(target);
198 | }
199 |
200 | /*
201 | * @Override public boolean isEnabled() { return verify(); }
202 | */
203 |
204 | };
205 | computeLink.setOutputMarkupPlaceholderTag(true);
206 | computeLink.add(AttributeModifier.append("class", new ButtonCssClassModel()));
207 | computeLink.setVisible(!pivotModel.isAutoCalculate());
208 | add(computeLink);
209 |
210 | downloadContainer = new WebMarkupContainer("downloadContainer");
211 | downloadContainer.setOutputMarkupPlaceholderTag(true);
212 | downloadContainer.setVisible(pivotTable.isVisible() && (pivotExporters.length > 0));
213 | add(downloadContainer);
214 |
215 | RepeatingView downloadExports = new RepeatingView("downloadExport");
216 | downloadContainer.add(downloadExports);
217 | for (final PivotExporter exporter : pivotExporters) {
218 | Link downloadLink = new Link(downloadExports.newChildId()) {
219 | private static final long serialVersionUID = 1L;
220 |
221 | @Override
222 | public void onClick() {
223 | pivotModel.calculate();
224 | ByteArrayOutputStream out = new ByteArrayOutputStream();
225 | try {
226 | exporter.exportPivot(getPivotModel(), out);
227 | } catch (IOException e) {
228 | throw new RuntimeException(e);
229 | }
230 | ResourceRequestHandler downloadHandler = new ResourceRequestHandler(new ByteArrayResource(
231 | exporter.getFormatMimetype(), out.toByteArray(), pivotExportFilename + "."
232 | + exporter.getFilenameExtension()), null);
233 | RequestCycle.get().scheduleRequestHandlerAfterCurrent(downloadHandler);
234 | }
235 | };
236 | downloadExports.add(downloadLink);
237 | IModel resourceModel = new StringResourceModel("downloadAs", downloadLink, Model.of(exporter
238 | .getFormatName()));
239 | downloadLink.add(new Label("label", resourceModel));
240 | downloadLink.setOutputMarkupPlaceholderTag(true);
241 | downloadLink.add(AttributeModifier.append("class", new ButtonCssClassModel()));
242 | }
243 |
244 | add(new PivotResourcesBehavior());
245 | if (pivotModel.isAutoCalculate()) {
246 | compute(null);
247 | }
248 |
249 | setOutputMarkupId(true);
250 | }
251 |
252 | @Override
253 | public void onEvent(IEvent> event) {
254 | super.onEvent(event);
255 |
256 | if (event.getPayload() instanceof AreaChangedEvent) {
257 | AjaxRequestTarget target = ((AreaChangedEvent) event.getPayload()).getAjaxRequestTarget();
258 | target.add(areasContainer);
259 | target.add(computeLink);
260 |
261 | if (pivotModel.isAutoCalculate()) {
262 | compute(target);
263 | }
264 | }
265 | }
266 |
267 | public PivotModel getPivotModel() {
268 | return pivotModel;
269 | }
270 |
271 | public PivotFieldActionsFactory getPivotFieldActionsFactory() {
272 | return pivotFieldActionsFactory;
273 | }
274 |
275 | public void compute(AjaxRequestTarget target) {
276 | if (!verify()) {
277 | return;
278 | }
279 |
280 | pivotModel.calculate();
281 | PivotTable newPivotTable = new PivotTable("pivotTable", pivotModel);
282 | pivotTable.replaceWith(newPivotTable);
283 | pivotTable = newPivotTable;
284 | if (target != null) {
285 | // update pivot table
286 | target.add(pivotTable);
287 |
288 | // update download container visibility
289 | downloadContainer.setVisible(pivotTable.isVisible() && (pivotExporters.length > 0));
290 | target.add(downloadContainer);
291 | }
292 | }
293 |
294 | protected PivotModel createPivotModel(PivotDataSource pivotDataSource) {
295 | PivotModel pivotModel = new DefaultPivotModel(pivotDataSource);
296 |
297 | // debug
298 | /*
299 | * Tree columnsHeaderTree = pivotModel.getColumnsHeaderTree();
300 | * System.out.println("### Columns Header Tree ###");
301 | * TreeHelper.printTree(columnsHeaderTree.getRoot());
302 | * TreeHelper.printLeafValues(columnsHeaderTree.getRoot());
303 | *
304 | * Tree rowsHeaderTree = pivotModel.getRowsHeaderTree();
305 | * System.out.println("### Rows Header Tree ### ");
306 | * TreeHelper.printTree(rowsHeaderTree.getRoot());
307 | * TreeHelper.printLeafValues(rowsHeaderTree.getRoot());
308 | */
309 |
310 | return pivotModel;
311 | }
312 |
313 | protected PivotTable createPivotTabel(String id, PivotModel pivotModel) {
314 | PivotTable pivotTable = new PivotTable(id, pivotModel);
315 | pivotTable.setOutputMarkupPlaceholderTag(true);
316 | pivotTable.setVisible(false);
317 |
318 | return pivotTable;
319 | }
320 |
321 | protected PivotFieldActionsFactory createPivotFieldActionsFactory() {
322 | return new DefaultPivotFieldActionsFactory();
323 | }
324 |
325 | private boolean verify() {
326 | return !pivotModel.getFields(PivotField.Area.DATA).isEmpty()
327 | && (!pivotModel.getFields(PivotField.Area.COLUMN).isEmpty() || !pivotModel.getFields(
328 | PivotField.Area.ROW).isEmpty());
329 | }
330 |
331 | /**
332 | * Set the pivot exporter to use
333 | */
334 | public void setPivotExporters(PivotExporter[] pivotExporter) {
335 | this.pivotExporters = pivotExporter;
336 | }
337 |
338 | /**
339 | * Set the basename of the download files
340 | *
341 | * @param pivotExportFilename
342 | */
343 | public void setPivotExportFilename(String pivotExportFilename) {
344 | this.pivotExportFilename = pivotExportFilename;
345 | }
346 |
347 | public IPivotConfigStorage getPivotConfigStorage() {
348 | return pivotConfigStorage;
349 | }
350 |
351 | /**
352 | * Set the Pivot Configuration Storage to use. By default no storage is set.
353 | *
354 | * @param pivotConfigStorage
355 | */
356 | public void setPivotConfigStorage(IPivotConfigStorage pivotConfigStorage) {
357 | this.pivotConfigStorage = pivotConfigStorage;
358 | }
359 | }
360 |
--------------------------------------------------------------------------------