Révision 19

tmp/org.txm.textsbalance.core/build.properties (revision 19)
1
source.. = src/
2
output.. = bin/
3
bin.includes = META-INF/,\
4
               .,\
5
               plugin.xml
0 6

  
tmp/org.txm.textsbalance.core/plugin.xml (revision 19)
1
<?xml version="1.0" encoding="UTF-8"?>
2
<?eclipse version="3.4"?>
3
<plugin>
4
   <extension
5
         point="org.eclipse.core.runtime.preferences">
6
      <initializer
7
            class="org.txm.textsbalance.core.preferences.TextsBalancePreferences">
8
      </initializer>
9
   </extension>
10
   <extension
11
         point="org.txm.chartsengine.chartcreator">
12
      <ChartCreator
13
            chartsEngineName="jfreechart_charts_engine"
14
            class="org.txm.textsbalance.core.chartsengine.jfreechart.JFCBalanceSpiderChartCreator"
15
            fileNamePrefix="texts_balance">
16
      </ChartCreator>
17
      <ChartCreator
18
            chartsEngineName="TMP_r_charts_engine"
19
            class="org.txm.textsbalance.core.chartsengine.r.RBalanceSpiderChartCreator"
20
            fileNamePrefix="texts_balance">
21
      </ChartCreator>
22
   </extension>
23

  
24
</plugin>
0 25

  
tmp/org.txm.textsbalance.core/.settings/org.eclipse.jdt.core.prefs (revision 19)
1
eclipse.preferences.version=1
2
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4
org.eclipse.jdt.core.compiler.compliance=1.6
5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7
org.eclipse.jdt.core.compiler.source=1.6
0 8

  
tmp/org.txm.textsbalance.core/.classpath (revision 19)
1
<?xml version="1.0" encoding="UTF-8"?>
2
<classpath>
3
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
4
	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
5
	<classpathentry kind="src" path="src"/>
6
	<classpathentry kind="output" path="bin"/>
7
</classpath>
0 8

  
tmp/org.txm.textsbalance.core/META-INF/MANIFEST.MF (revision 19)
1
Manifest-Version: 1.0
2
Bundle-ManifestVersion: 2
3
Bundle-Name: Texts Balance TBX
4
Bundle-SymbolicName: org.txm.textsbalance.core;singleton:=true
5
Bundle-Version: 1.0.0.qualifier
6
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
7
Export-Package: org.txm.textsbalance.core.chartsengine.jfreechart,
8
 org.txm.textsbalance.core.chartsengine.r,
9
 org.txm.textsbalance.core.functions,
10
 org.txm.textsbalance.core.preferences
11
Require-Bundle: org.eclipse.core.runtime;bundle-version="3.10.0",
12
 org.txm.chartsengine.jfreechart.rcp;bundle-version="1.0.0",
13
 org.txm.chartsengine.r.rcp;bundle-version="1.0.0",
14
 org.txm.toolbox;bundle-version="0.7.0"
15
Bundle-Vendor: TXM
0 16

  
tmp/org.txm.textsbalance.core/.project (revision 19)
1
<?xml version="1.0" encoding="UTF-8"?>
2
<projectDescription>
3
	<name>org.txm.textsbalance.core</name>
4
	<comment></comment>
5
	<projects>
6
	</projects>
7
	<buildSpec>
8
		<buildCommand>
9
			<name>org.eclipse.jdt.core.javabuilder</name>
10
			<arguments>
11
			</arguments>
12
		</buildCommand>
13
		<buildCommand>
14
			<name>org.eclipse.pde.ManifestBuilder</name>
15
			<arguments>
16
			</arguments>
17
		</buildCommand>
18
		<buildCommand>
19
			<name>org.eclipse.pde.SchemaBuilder</name>
20
			<arguments>
21
			</arguments>
22
		</buildCommand>
23
	</buildSpec>
24
	<natures>
25
		<nature>org.eclipse.pde.PluginNature</nature>
26
		<nature>org.eclipse.jdt.core.javanature</nature>
27
	</natures>
28
</projectDescription>
0 29

  
tmp/org.txm.textsbalance.core/src/org/txm/textsbalance/core/chartsengine/jfreechart/MultipleSpiderWebPlot.java (revision 19)
1
/* ===========================================================
2
 * JFreeChart : a free chart library for the Java(tm) platform
3
 * ===========================================================
4
 *
5
 * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors.
6
 *
7
 * Project Info:  http://www.jfree.org/jfreechart/index.html
8
 *
9
 * This library is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17
 * License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
22
 * USA.
23
 *
24
 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
25
 * Other names may be trademarks of their respective owners.]
26
 *
27
 * --------------------
28
 * MultipleSpiderWebPlot.java
29
 * --------------------
30
 * (C) Copyright 2004-2013, by Object Refinery Limited.
31
 *
32
 * Original Author:  David Gilbert (for Object Refinery Limited);
33
 * Contributor(s):   Brian Cabana (patch 1943021);
34
 *
35
 * Changes
36
 * -------
37
 * 29-Jan-2004 : Version 1 (DG);
38
 * 31-Mar-2004 : Added setPieIndex() call during drawing (DG);
39
 * 20-Apr-2005 : Small change for update to LegendItem constructors (DG);
40
 * 05-May-2005 : Updated draw() method parameters (DG);
41
 * 16-Jun-2005 : Added get/setDataset() and equals() methods (DG);
42
 * ------------- JFREECHART 1.0.x ---------------------------------------------
43
 * 06-Apr-2006 : Fixed bug 1190647 - legend and section colors not consistent
44
 *               when aggregation limit is specified (DG);
45
 * 27-Sep-2006 : Updated draw() method for deprecated code (DG);
46
 * 17-Jan-2007 : Updated prefetchSectionPaints() to check settings in
47
 *               underlying SpiderWebPlot (DG);
48
 * 17-May-2007 : Added argument check to setPieChart() (DG);
49
 * 18-May-2007 : Set dataset for LegendItem (DG);
50
 * 18-Apr-2008 : In the constructor, register the plot as a dataset listener -
51
 *               see patch 1943021 from Brian Cabana (DG);
52
 * 30-Dec-2008 : Added legendItemShape field, and fixed cloning bug (DG);
53
 * 09-Jan-2009 : See ignoreNullValues to true for sub-chart (DG);
54
 * 01-Jun-2009 : Set series key in getLegendItems() (DG);
55
 * 03-Jul-2013 : Use ParamChecks (DG);
56
 *
57
 */
58

  
59
package org.txm.textsbalance.core.chartsengine.jfreechart;
60

  
61
import java.awt.Color;
62
import java.awt.Font;
63
import java.awt.Graphics2D;
64
import java.awt.Paint;
65
import java.awt.Rectangle;
66
import java.awt.Shape;
67
import java.awt.geom.Ellipse2D;
68
import java.awt.geom.Point2D;
69
import java.awt.geom.Rectangle2D;
70
import java.io.IOException;
71
import java.io.ObjectInputStream;
72
import java.io.ObjectOutputStream;
73
import java.io.Serializable;
74
import java.util.HashMap;
75
import java.util.Iterator;
76
import java.util.List;
77
import java.util.Map;
78

  
79
import org.jfree.chart.ChartRenderingInfo;
80
import org.jfree.chart.JFreeChart;
81
import org.jfree.chart.LegendItem;
82
import org.jfree.chart.LegendItemCollection;
83
import org.jfree.chart.event.PlotChangeEvent;
84
import org.jfree.chart.plot.Plot;
85
import org.jfree.chart.plot.PlotRenderingInfo;
86
import org.jfree.chart.plot.PlotState;
87
import org.jfree.chart.plot.SpiderWebPlot;
88
import org.jfree.chart.title.TextTitle;
89
import org.jfree.chart.util.ParamChecks;
90
import org.jfree.data.category.CategoryDataset;
91
import org.jfree.data.category.CategoryToPieDataset;
92
import org.jfree.data.category.DefaultCategoryDataset;
93
import org.jfree.data.general.DatasetChangeEvent;
94
import org.jfree.data.general.DatasetUtilities;
95
import org.jfree.data.general.PieDataset;
96
import org.jfree.io.SerialUtilities;
97
import org.jfree.ui.RectangleEdge;
98
import org.jfree.ui.RectangleInsets;
99
import org.jfree.util.ObjectUtilities;
100
import org.jfree.util.PaintUtilities;
101
import org.jfree.util.ShapeUtilities;
102
import org.jfree.util.TableOrder;
103

  
104
/**
105
 * A plot that displays multiple pie plots using data from a
106
 * {@link CategoryDataset}.
107
 */
108
public class MultipleSpiderWebPlot extends Plot implements Cloneable, Serializable {
109

  
110
    /** The chart object that draws the individual pie charts. */
111
    private JFreeChart spiderChart;
112

  
113
    /** The dataset. */
114
    private DefaultCategoryDataset dataset;
115

  
116
    /** The data extract order (by row or by column). */
117
    private TableOrder dataExtractOrder;
118

  
119
    /** The pie section limit percentage. */
120
    private double limit = 0.0;
121

  
122
    /**
123
     * The key for the aggregated items.
124
     *
125
     * @since 1.0.2
126
     */
127
    private Comparable aggregatedItemsKey;
128

  
129
    /**
130
     * The paint for the aggregated items.
131
     *
132
     * @since 1.0.2
133
     */
134
    private transient Paint aggregatedItemsPaint;
135

  
136
    /**
137
     * The colors to use for each section.
138
     *
139
     * @since 1.0.2
140
     */
141
    private transient Map sectionPaints;
142

  
143
    /**
144
     * The legend item shape (never null).
145
     *
146
     * @since 1.0.12
147
     */
148
    private transient Shape legendItemShape;
149

  
150
    /**
151
     * Creates a new plot with no data.
152
     */
153
    public MultipleSpiderWebPlot() {
154
        this(null);
155
    }
156

  
157
    /**
158
     * Creates a new plot.
159
     *
160
     * @param dataset  the dataset (<code>null</code> permitted).
161
     */
162
    public MultipleSpiderWebPlot(DefaultCategoryDataset dataset) {
163
        super();
164
        setDataset(dataset);
165
        SpiderWebPlot piePlot = new SpiderWebPlot(null);
166
        this.spiderChart = new JFreeChart(piePlot);
167
        this.spiderChart.removeLegend();
168
        this.dataExtractOrder = TableOrder.BY_COLUMN;
169
        this.spiderChart.setBackgroundPaint(null);
170
        TextTitle seriesTitle = new TextTitle("Series Title",
171
                new Font("SansSerif", Font.BOLD, 12));
172
        seriesTitle.setPosition(RectangleEdge.BOTTOM);
173
        this.spiderChart.setTitle(seriesTitle);
174
        this.aggregatedItemsKey = "Other";
175
        this.aggregatedItemsPaint = Color.lightGray;
176
        this.sectionPaints = new HashMap();
177
        this.legendItemShape = new Ellipse2D.Double(-4.0, -4.0, 8.0, 8.0);
178
    }
179

  
180
    /**
181
     * Returns the dataset used by the plot.
182
     *
183
     * @return The dataset (possibly <code>null</code>).
184
     */
185
    public CategoryDataset getDataset() {
186
        return this.dataset;
187
    }
188

  
189
    /**
190
     * Sets the dataset used by the plot and sends a {@link PlotChangeEvent}
191
     * to all registered listeners.
192
     *
193
     * @param dataset  the dataset (<code>null</code> permitted).
194
     */
195
    public void setDataset(DefaultCategoryDataset dataset) {
196
        // if there is an existing dataset, remove the plot from the list of
197
        // change listeners...
198
        if (this.dataset != null) {
199
            this.dataset.removeChangeListener(this);
200
        }
201

  
202
        // set the new dataset, and register the chart as a change listener...
203
        this.dataset = dataset;
204
        if (dataset != null) {
205
            setDatasetGroup(dataset.getGroup());
206
            dataset.addChangeListener(this);
207
        }
208

  
209
        // send a dataset change event to self to trigger plot change event
210
        datasetChanged(new DatasetChangeEvent(this, dataset));
211
    }
212

  
213
    /**
214
     * Returns the pie chart that is used to draw the individual pie plots.
215
     * Note that there are some attributes on this chart instance that will
216
     * be ignored at rendering time (for example, legend item settings).
217
     *
218
     * @return The pie chart (never <code>null</code>).
219
     *
220
     * @see #setPieChart(JFreeChart)
221
     */
222
    public JFreeChart getPieChart() {
223
        return this.spiderChart;
224
    }
225

  
226
    /**
227
     * Sets the chart that is used to draw the individual pie plots.  The
228
     * chart's plot must be an instance of {@link SpiderWebPlot}.
229
     *
230
     * @param pieChart  the pie chart (<code>null</code> not permitted).
231
     *
232
     * @see #getPieChart()
233
     */
234
    public void setPieChart(JFreeChart pieChart) {
235
        ParamChecks.nullNotPermitted(pieChart, "pieChart");
236
        if (!(pieChart.getPlot() instanceof SpiderWebPlot)) {
237
            throw new IllegalArgumentException("The 'pieChart' argument must "
238
                    + "be a chart based on a SpiderWebPlot.");
239
        }
240
        this.spiderChart = pieChart;
241
        fireChangeEvent();
242
    }
243

  
244
    /**
245
     * Returns the data extract order (by row or by column).
246
     *
247
     * @return The data extract order (never <code>null</code>).
248
     */
249
    public TableOrder getDataExtractOrder() {
250
        return this.dataExtractOrder;
251
    }
252

  
253
    /**
254
     * Sets the data extract order (by row or by column) and sends a
255
     * {@link PlotChangeEvent} to all registered listeners.
256
     *
257
     * @param order  the order (<code>null</code> not permitted).
258
     */
259
    public void setDataExtractOrder(TableOrder order) {
260
        ParamChecks.nullNotPermitted(order, "order");
261
        this.dataExtractOrder = order;
262
        fireChangeEvent();
263
    }
264

  
265
    /**
266
     * Returns the limit (as a percentage) below which small pie sections are
267
     * aggregated.
268
     *
269
     * @return The limit percentage.
270
     */
271
    public double getLimit() {
272
        return this.limit;
273
    }
274

  
275
    /**
276
     * Sets the limit below which pie sections are aggregated.
277
     * Set this to 0.0 if you don't want any aggregation to occur.
278
     *
279
     * @param limit  the limit percent.
280
     */
281
    public void setLimit(double limit) {
282
        this.limit = limit;
283
        fireChangeEvent();
284
    }
285

  
286
    /**
287
     * Returns the key for aggregated items in the pie plots, if there are any.
288
     * The default value is "Other".
289
     *
290
     * @return The aggregated items key.
291
     *
292
     * @since 1.0.2
293
     */
294
    public Comparable getAggregatedItemsKey() {
295
        return this.aggregatedItemsKey;
296
    }
297

  
298
    /**
299
     * Sets the key for aggregated items in the pie plots.  You must ensure
300
     * that this doesn't clash with any keys in the dataset.
301
     *
302
     * @param key  the key (<code>null</code> not permitted).
303
     *
304
     * @since 1.0.2
305
     */
306
    public void setAggregatedItemsKey(Comparable key) {
307
        ParamChecks.nullNotPermitted(key, "key");
308
        this.aggregatedItemsKey = key;
309
        fireChangeEvent();
310
    }
311

  
312
    /**
313
     * Returns the paint used to draw the pie section representing the
314
     * aggregated items.  The default value is <code>Color.lightGray</code>.
315
     *
316
     * @return The paint.
317
     *
318
     * @since 1.0.2
319
     */
320
    public Paint getAggregatedItemsPaint() {
321
        return this.aggregatedItemsPaint;
322
    }
323

  
324
    /**
325
     * Sets the paint used to draw the pie section representing the aggregated
326
     * items and sends a {@link PlotChangeEvent} to all registered listeners.
327
     *
328
     * @param paint  the paint (<code>null</code> not permitted).
329
     *
330
     * @since 1.0.2
331
     */
332
    public void setAggregatedItemsPaint(Paint paint) {
333
        ParamChecks.nullNotPermitted(paint, "paint");
334
        this.aggregatedItemsPaint = paint;
335
        fireChangeEvent();
336
    }
337

  
338
    /**
339
     * Returns a short string describing the type of plot.
340
     *
341
     * @return The plot type.
342
     */
343
    @Override
344
    public String getPlotType() {
345
        return "Multiple Pie Plot";
346
         // TODO: need to fetch this from localised resources
347
    }
348

  
349
    /**
350
     * Returns the shape used for legend items.
351
     *
352
     * @return The shape (never <code>null</code>).
353
     *
354
     * @see #setLegendItemShape(Shape)
355
     *
356
     * @since 1.0.12
357
     */
358
    public Shape getLegendItemShape() {
359
        return this.legendItemShape;
360
    }
361

  
362
    /**
363
     * Sets the shape used for legend items and sends a {@link PlotChangeEvent}
364
     * to all registered listeners.
365
     *
366
     * @param shape  the shape (<code>null</code> not permitted).
367
     *
368
     * @see #getLegendItemShape()
369
     *
370
     * @since 1.0.12
371
     */
372
    public void setLegendItemShape(Shape shape) {
373
        ParamChecks.nullNotPermitted(shape, "shape");
374
        this.legendItemShape = shape;
375
        fireChangeEvent();
376
    }
377

  
378
    /**
379
     * Draws the plot on a Java 2D graphics device (such as the screen or a
380
     * printer).
381
     *
382
     * @param g2  the graphics device.
383
     * @param area  the area within which the plot should be drawn.
384
     * @param anchor  the anchor point (<code>null</code> permitted).
385
     * @param parentState  the state from the parent plot, if there is one.
386
     * @param info  collects info about the drawing.
387
     */
388
    @Override
389
    public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
390
            PlotState parentState, PlotRenderingInfo info) {
391

  
392
        // adjust the drawing area for the plot insets (if any)...
393
        RectangleInsets insets = getInsets();
394
        insets.trim(area);
395
        drawBackground(g2, area);
396
        drawOutline(g2, area);
397

  
398
        // check that there is some data to display...
399
        if (DatasetUtilities.isEmptyOrNull(this.dataset)) {
400
            drawNoDataMessage(g2, area);
401
            return;
402
        }
403

  
404
        int pieCount;
405
        if (this.dataExtractOrder == TableOrder.BY_ROW) {
406
            pieCount = this.dataset.getRowCount();
407
        }
408
        else {
409
            pieCount = this.dataset.getColumnCount();
410
        }
411

  
412
        // the columns variable is always >= rows
413
        int displayCols = (int) Math.ceil(Math.sqrt(pieCount));
414
        int displayRows
415
            = (int) Math.ceil((double) pieCount / (double) displayCols);
416

  
417
        // swap rows and columns to match plotArea shape
418
        if (displayCols > displayRows && area.getWidth() < area.getHeight()) {
419
            int temp = displayCols;
420
            displayCols = displayRows;
421
            displayRows = temp;
422
        }
423

  
424
        prefetchSectionPaints();
425

  
426
        int x = (int) area.getX();
427
        int y = (int) area.getY();
428
        int width = ((int) area.getWidth()) / displayCols;
429
        int height = ((int) area.getHeight()) / displayRows;
430
        int row = 0;
431
        int column = 0;
432
        int diff = (displayRows * displayCols) - pieCount;
433
        int xoffset = 0;
434
        Rectangle rect = new Rectangle();
435

  
436
        for (int pieIndex = 0; pieIndex < pieCount; pieIndex++) {
437
            rect.setBounds(x + xoffset + (width * column), y + (height * row),
438
                    width, height);
439

  
440
            String title;
441
            if (this.dataExtractOrder == TableOrder.BY_ROW) {
442
                title = this.dataset.getRowKey(pieIndex).toString();
443
            }
444
            else {
445
                title = this.dataset.getColumnKey(pieIndex).toString();
446
            }
447
            this.spiderChart.setTitle(title);
448

  
449
            DefaultCategoryDataset piedataset = new DefaultCategoryDataset();
450
            for (int irow = 0 ; irow < this.dataset.getRowCount() ; irow++) {
451
            	this.dataset.getValue(irow, pieIndex);
452
            }
453
            
454
            SpiderWebPlot piePlot = (SpiderWebPlot) this.spiderChart.getPlot();
455
            piePlot.setDataset(piedataset);
456
            
457

  
458
            ChartRenderingInfo subinfo = null;
459
            if (info != null) {
460
                subinfo = new ChartRenderingInfo();
461
            }
462
            this.spiderChart.draw(g2, rect, subinfo);
463
            if (info != null) {
464
                assert subinfo != null;
465
                info.getOwner().getEntityCollection().addAll(
466
                        subinfo.getEntityCollection());
467
                info.addSubplotInfo(subinfo.getPlotInfo());
468
            }
469

  
470
            ++column;
471
            if (column == displayCols) {
472
                column = 0;
473
                ++row;
474

  
475
                if (row == displayRows - 1 && diff != 0) {
476
                    xoffset = (diff * width) / 2;
477
                }
478
            }
479
        }
480

  
481
    }
482

  
483
    /**
484
     * For each key in the dataset, check the <code>sectionPaints</code>
485
     * cache to see if a paint is associated with that key and, if not,
486
     * fetch one from the drawing supplier.  These colors are cached so that
487
     * the legend and all the subplots use consistent colors.
488
     */
489
    private void prefetchSectionPaints() {
490

  
491
//        // pre-fetch the colors for each key...this is because the subplots
492
//        // may not display every key, but we need the coloring to be
493
//        // consistent...
494
//
495
//        SpiderWebPlot piePlot = (SpiderWebPlot) getPieChart().getPlot();
496
//
497
//        if (this.dataExtractOrder == TableOrder.BY_ROW) {
498
//            // column keys provide potential keys for individual pies
499
//            for (int c = 0; c < this.dataset.getColumnCount(); c++) {
500
//                Comparable key = this.dataset.getColumnKey(c);
501
//                Paint p = piePlot.getSeriesPaint(key);
502
//                if (p == null) {
503
//                    p = (Paint) this.sectionPaints.get(key);
504
//                    if (p == null) {
505
//                        p = getDrawingSupplier().getNextPaint();
506
//                    }
507
//                }
508
//                this.sectionPaints.put(key, p);
509
//            }
510
//        }
511
//        else {
512
//            // row keys provide potential keys for individual pies
513
//            for (int r = 0; r < this.dataset.getRowCount(); r++) {
514
//                Comparable key = this.dataset.getRowKey(r);
515
//                Paint p = piePlot.getSeriesPaint(key);
516
//                if (p == null) {
517
//                    p = (Paint) this.sectionPaints.get(key);
518
//                    if (p == null) {
519
//                        p = getDrawingSupplier().getNextPaint();
520
//                    }
521
//                }
522
//                this.sectionPaints.put(key, p);
523
//            }
524
//        }
525

  
526
    }
527

  
528
    /**
529
     * Returns a collection of legend items for the pie chart.
530
     *
531
     * @return The legend items.
532
     */
533
    @Override
534
    public LegendItemCollection getLegendItems() {
535

  
536
        LegendItemCollection result = new LegendItemCollection();
537
        if (this.dataset == null) {
538
            return result;
539
        }
540

  
541
        List keys = null;
542
        prefetchSectionPaints();
543
        if (this.dataExtractOrder == TableOrder.BY_ROW) {
544
            keys = this.dataset.getColumnKeys();
545
        }
546
        else if (this.dataExtractOrder == TableOrder.BY_COLUMN) {
547
            keys = this.dataset.getRowKeys();
548
        }
549
        if (keys == null) {
550
            return result;
551
        }
552
        int section = 0;
553
        Iterator iterator = keys.iterator();
554
        while (iterator.hasNext()) {
555
            Comparable key = (Comparable) iterator.next();
556
            String label = key.toString();  // TODO: use a generator here
557
            String description = label;
558
            Paint paint = (Paint) this.sectionPaints.get(key);
559
            LegendItem item = new LegendItem(label, description, null,
560
                    null, getLegendItemShape(), paint,
561
                    Plot.DEFAULT_OUTLINE_STROKE, paint);
562
            item.setSeriesKey(key);
563
            item.setSeriesIndex(section);
564
            item.setDataset(getDataset());
565
            result.add(item);
566
            section++;
567
        }
568
        if (this.limit > 0.0) {
569
            LegendItem a = new LegendItem(this.aggregatedItemsKey.toString(),
570
                    this.aggregatedItemsKey.toString(), null, null,
571
                    getLegendItemShape(), this.aggregatedItemsPaint,
572
                    Plot.DEFAULT_OUTLINE_STROKE, this.aggregatedItemsPaint);
573
            result.add(a);
574
        }
575
        return result;
576
    }
577

  
578
    /**
579
     * Tests this plot for equality with an arbitrary object.  Note that the
580
     * plot's dataset is not considered in the equality test.
581
     *
582
     * @param obj  the object (<code>null</code> permitted).
583
     *
584
     * @return <code>true</code> if this plot is equal to <code>obj</code>, and
585
     *     <code>false</code> otherwise.
586
     */
587
    @Override
588
    public boolean equals(Object obj) {
589
        if (obj == this) {
590
            return true;
591
        }
592
        if (!(obj instanceof MultipleSpiderWebPlot)) {
593
            return false;
594
        }
595
        MultipleSpiderWebPlot that = (MultipleSpiderWebPlot) obj;
596
        if (this.dataExtractOrder != that.dataExtractOrder) {
597
            return false;
598
        }
599
        if (this.limit != that.limit) {
600
            return false;
601
        }
602
        if (!this.aggregatedItemsKey.equals(that.aggregatedItemsKey)) {
603
            return false;
604
        }
605
        if (!PaintUtilities.equal(this.aggregatedItemsPaint,
606
                that.aggregatedItemsPaint)) {
607
            return false;
608
        }
609
        if (!ObjectUtilities.equal(this.spiderChart, that.spiderChart)) {
610
            return false;
611
        }
612
        if (!ShapeUtilities.equal(this.legendItemShape, that.legendItemShape)) {
613
            return false;
614
        }
615
        if (!super.equals(obj)) {
616
            return false;
617
        }
618
        return true;
619
    }
620

  
621
    /**
622
     * Returns a clone of the plot.
623
     *
624
     * @return A clone.
625
     *
626
     * @throws CloneNotSupportedException if some component of the plot does
627
     *         not support cloning.
628
     */
629
    @Override
630
    public Object clone() throws CloneNotSupportedException {
631
        MultipleSpiderWebPlot clone = (MultipleSpiderWebPlot) super.clone();
632
        clone.spiderChart = (JFreeChart) this.spiderChart.clone();
633
        clone.sectionPaints = new HashMap(this.sectionPaints);
634
        clone.legendItemShape = ShapeUtilities.clone(this.legendItemShape);
635
        return clone;
636
    }
637

  
638
    /**
639
     * Provides serialization support.
640
     *
641
     * @param stream  the output stream.
642
     *
643
     * @throws IOException  if there is an I/O error.
644
     */
645
    private void writeObject(ObjectOutputStream stream) throws IOException {
646
        stream.defaultWriteObject();
647
        SerialUtilities.writePaint(this.aggregatedItemsPaint, stream);
648
        SerialUtilities.writeShape(this.legendItemShape, stream);
649
    }
650

  
651
    /**
652
     * Provides serialization support.
653
     *
654
     * @param stream  the input stream.
655
     *
656
     * @throws IOException  if there is an I/O error.
657
     * @throws ClassNotFoundException  if there is a classpath problem.
658
     */
659
    private void readObject(ObjectInputStream stream)
660
        throws IOException, ClassNotFoundException {
661
        stream.defaultReadObject();
662
        this.aggregatedItemsPaint = SerialUtilities.readPaint(stream);
663
        this.legendItemShape = SerialUtilities.readShape(stream);
664
        this.sectionPaints = new HashMap();
665
    }
666

  
667
}
0 668

  
tmp/org.txm.textsbalance.core/src/org/txm/textsbalance/core/chartsengine/jfreechart/JFCBalanceSpiderChartCreator.java (revision 19)
1
package org.txm.textsbalance.core.chartsengine.jfreechart;
2

  
3
import java.util.HashMap;
4
import java.util.Iterator;
5
import java.util.Set;
6

  
7
import org.jfree.chart.JFreeChart;
8
import org.jfree.chart.labels.CategoryToolTipGenerator;
9
import org.jfree.chart.plot.SpiderWebPlot;
10
import org.jfree.data.category.CategoryDataset;
11
import org.jfree.data.category.DefaultCategoryDataset;
12
import org.txm.chartsengine.jfreechart.core.JFCChartCreator;
13
import org.txm.chartsengine.jfreechart.core.themes.base.Theme;
14
import org.txm.textsbalance.core.functions.TextsBalance;
15

  
16
public class JFCBalanceSpiderChartCreator extends JFCChartCreator {
17

  
18
	public JFCBalanceSpiderChartCreator() {
19
		// TODO Auto-generated constructor stub
20
	}
21

  
22
	@Override
23
	public JFreeChart createChart(Object resultData, String preferencesNode) {
24

  
25
		final TextsBalance balance = (TextsBalance) resultData;
26
		
27
		HashMap<Integer, Comparable[]> data = balance.getDataset();
28
		
29
		
30
		JFreeChart chart = null;
31

  
32
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
33
		
34
		Set<Integer> keys = data.keySet();
35
		Iterator<Integer> it = keys.iterator();
36
		while (it.hasNext()){
37
		   int key = it.next();
38
		   Comparable[] value = data.get(key);
39
		   dataset.addValue(key, value[0], value[1]);
40
		}
41
		
42
		
43
		SpiderWebPlot plot = new SpiderWebPlot(dataset);
44
		plot.setToolTipGenerator(new CategoryToolTipGenerator() {
45
			@Override
46
			public String generateToolTip(CategoryDataset dataset, int row, int col) {
47
				// FIXME: tests
48
//				System.out.println("JFCBalanceSpiderChartCreator.createChart(...).new CategoryToolTipGenerator() {...}.generateToolTip() row = " + row + " col = " + col);
49
//				System.out.println("JFCBalanceSpiderChartCreator.createChart(...).new CategoryToolTipGenerator() {...}.generateToolTip() " + dataset.getValue(row, col));
50
				
51
//				if(balance.getValues().size() > col)	{
52
//					 balance.getValues().get(col);
53
//				}
54
//				return "error";
55
				return String.valueOf(dataset.getValue(row, col).intValue());
56
			}
57
		});
58

  
59

  
60
		chart = new JFreeChart(plot);
61
		chart.setTitle("metadata = " + balance.getPropertyName() + ", N = " +  balance.getValues().size() + ", fmin = " + balance.getFMin() + ", fmax = " + balance.getFMax());
62

  
63
		// FIXME: tests
64
		//this.getChartsEngine().getTheme().apply(chart);
65
		this.getChartsEngine().getTheme().applyThemeToChart(chart, Theme.ITEMS_RENDERING_GRAYSCALE_MODE);
66
		
67
		return chart;
68
		
69
	}
70

  
71

  
72
	@Override
73
	public Class getResultDataType() {
74
		return TextsBalance.class;
75
	}
76

  
77

  
78

  
79

  
80

  
81
	
82

  
83
}
0 84

  
tmp/org.txm.textsbalance.core/src/org/txm/textsbalance/core/chartsengine/r/RBalanceSpiderChartCreator.java (revision 19)
1
package org.txm.textsbalance.core.chartsengine.r;
2

  
3
import java.io.File;
4

  
5
import org.rosuda.REngine.REXPMismatchException;
6
import org.txm.chartsengine.core.ChartCreator;
7
import org.txm.chartsengine.r.core.RChartsEngine;
8
import org.txm.stat.StatException;
9
import org.txm.stat.engine.r.RWorkspace;
10
import org.txm.stat.engine.r.RWorkspaceException;
11
import org.txm.textsbalance.core.functions.TextsBalance;
12

  
13
public class RBalanceSpiderChartCreator extends ChartCreator {
14

  
15
	public RBalanceSpiderChartCreator() {
16
		// TODO Auto-generated constructor stub
17
	}
18

  
19
	@Override
20
	public Object createChart(Object resultData, String preferencesNode) {
21
		// TODO Auto-generated method stub
22
		return null;
23
	}
24

  
25
	@Override
26
	public File createChartFile(Object resultData, File file, String preferencesNode) {
27
		
28
//		try {
29
	
30
			
31
//			RWorkspace rw = RWorkspace.getRWorkspaceInstance();
32
//	System.out.println("load wordcloud...");
33
//			rw.eval("library(wordcloud)"); //$NON-NLS-1$
34
			//System.out.println("tmpfreqs...");
35
//			rw.addVectorToWorkspace("tmpfreqs", wordCloud.getFreqs()); //$NON-NLS-1$
36
			//System.out.println("tmplabels...");
37
//			rw.addVectorToWorkspace("tmplabels", wordCloud.getLabels()); //$NON-NLS-1$
38
			
39
			//wordcloud(words,freq,
40
			// scale : A vector of length 2 indicating the range of the size of the words.
41
			// min.freq:  words with frequency below min.freq will not be plotted
42
			// max.words : Maximum number of words to be plotted. least frequent terms dropped
43
			// random.order : plot words in random order. If false, they will be plotted in decreasing frequency
44
			// random.color : choose colors randomly from the colors. If false, the color is chosen based on the frequency
45
			// rot.per : proportion words with 90 degree rotation
46
			// colors : color words from least to most frequent
47
			// ordered.colors : if true, then colors are assigned to words in order
48
			//System.out.println("wordcloud...");
49
			
50
			// FIXME : stars plot tests
51
			//String cmd = "stars(mtcars[, 1:7], key.loc = c(14, 2), main = \"Motor Trend Cars : stars(*, full = F)\", full = FALSE)"; //$NON-NLS-1$
52
			String cmd = "stars(USJudgeRatings, locations = c(0, 0), scale = FALSE, radius  =  FALSE, col.stars = 1:10, key.loc = c(0, 0), main = \"US Judges rated\")";
53
			//String cmd = "stars(cbind(1:16, 10*(16:1)), draw.segments = TRUE, main = \"A Joke -- do *not* use symbols on 2D data!\")";
54
			
55
			
56

  
57
			//rw.plot(file, cmd, ((RChartsEngine) this.chartsEngine).getRDevice());
58
			
59
			((RChartsEngine) this.chartsEngine).plot(file, cmd);
60
			
61
				//System.out.println("cleaning");
62
//				rw.eval("rm(tmplabels)"); //$NON-NLS-1$
63
//				rw.eval("rm(tmpfreqs)"); //$NON-NLS-1$
64
//		}
65
//		catch(RWorkspaceException e) {
66
//			// TODO Auto-generated catch block
67
//			e.printStackTrace();
68
//		}
69
//		catch(REXPMismatchException e) {
70
//			// TODO Auto-generated catch block
71
//			e.printStackTrace();
72
//		}
73
//		catch(StatException e) {
74
//			// TODO Auto-generated catch block
75
//			e.printStackTrace();
76
//		}
77
		
78
		return file;
79
	}
80

  
81
	@Override
82
	public Class getResultDataType() {
83
		return TextsBalance.class;
84
	}
85

  
86

  
87

  
88
}
0 89

  
tmp/org.txm.textsbalance.core/src/org/txm/textsbalance/core/preferences/TextsBalancePreferences.java (revision 19)
1
package org.txm.textsbalance.core.preferences;
2

  
3

  
4
import org.eclipse.core.runtime.preferences.DefaultScope;
5
import org.osgi.framework.FrameworkUtil;
6
import org.osgi.service.prefs.Preferences;
7
import org.txm.tbx.preferences.TXMPreferences;
8

  
9
/**
10
 * Preferences initializer and manager.
11
 * @author sjacquot
12
 *
13
 */
14
public class TextsBalancePreferences extends TXMPreferences {
15

  
16

  
17
	// auto populate the preference node qualifier from the current bundle id
18
	public static final String PREFERENCES_NODE = FrameworkUtil.getBundle(TextsBalancePreferences.class).getSymbolicName();
19

  
20
	
21
	public static final String PREFERENCES_PREFIX = "texts_balance_"; //$NON-NLS-1$
22
	
23
	public static final String GROUP_BY_WORDS = PREFERENCES_PREFIX + "count_by_words"; //$NON-NLS-1$
24
	public static final String METHOD = PREFERENCES_PREFIX + "method"; //$NON-NLS-1$
25
	
26
	// local result preferences
27
	public static final String STRUCTURAL_UNIT = PREFERENCES_PREFIX + "structural_unit"; //$NON-NLS-1$
28
	public static final String STRUCTURAL_UNIT_PROPERTY_INDEX = PREFERENCES_PREFIX + "structural_unit_property_index"; //$NON-NLS-1$
29
	
30
	
31
	public TextsBalancePreferences() {
32
		// TODO Auto-generated constructor stub
33
	}
34

  
35
	@Override
36
	public void initializeDefaultPreferences() {
37

  
38
		// FIXME: trying to store the preference in the host plugin preference node
39
//		IPreferencesService service = Platform.getPreferencesService();
40
//		service.getRootNode().node(DefaultScope.SCOPE).node(Application.PLUGIN_ID).putBoolean(GROUP_BY_WORDS, true);
41
//		service.getRootNode().node(DefaultScope.SCOPE).node(Application.PLUGIN_ID).putInt(METHOD, 2);
42
//		try {
43
//			service.getRootNode().flush();
44
//		} catch (BackingStoreException e) {
45
//			System.err.println(e);
46
//		}
47
		
48
		Preferences defaultPreferences = DefaultScope.INSTANCE.getNode(PREFERENCES_NODE);
49
//		//Preferences defaultPreferences = DefaultScope.INSTANCE.getNode(Application.PLUGIN_ID);
50
		defaultPreferences.putBoolean(GROUP_BY_WORDS, true);
51
		defaultPreferences.putInt(METHOD, 2);
52
		
53
		
54
		defaultPreferences.put(STRUCTURAL_UNIT, "text");
55
		defaultPreferences.putInt(STRUCTURAL_UNIT_PROPERTY_INDEX, 0);
56

  
57
		// FIXME: Debug
58
//		System.err.println("*******************************TextsBalancePreferencesInitializer.initializeDefaultPreferences()");
59
		
60
	}
61
	
62
	
63

  
64
}
65

  
66

  
0 67

  
tmp/org.txm.textsbalance.core/src/org/txm/textsbalance/core/functions/TextsBalance.java (revision 19)
1
/**
2
 * 
3
 */
4
package org.txm.textsbalance.core.functions;
5

  
6
import java.io.File;
7
import java.util.ArrayList;
8
import java.util.Arrays;
9
import java.util.Collections;
10
import java.util.HashMap;
11
import java.util.List;
12

  
13
import org.txm.HasResults;
14
import org.txm.Toolbox;
15
import org.txm.functions.Function;
16
import org.txm.functions.TXMResult;
17
import org.txm.searchengine.cqp.AbstractCqiClient;
18
import org.txm.searchengine.cqp.NetCqiClient;
19
import org.txm.searchengine.cqp.clientExceptions.CqiClientException;
20
import org.txm.searchengine.cqp.corpus.Corpus;
21
import org.txm.searchengine.cqp.corpus.QueryResult;
22
import org.txm.searchengine.cqp.corpus.StructuralUnit;
23
import org.txm.searchengine.cqp.corpus.StructuralUnitProperty;
24
import org.txm.searchengine.cqp.corpus.query.Match;
25
import org.txm.searchengine.cqp.corpus.query.Query;
26
import org.txm.utils.logger.Log;
27

  
28
/**
29
 * @author mdecorde
30
 * @author sjacquot
31
 *
32
 */
33
public class TextsBalance extends Function implements TXMResult {
34

  
35
	
36
	
37
	protected Corpus corpus;
38
	
39
	
40
	HashMap<Integer, Comparable[]> dataset;
41
	
42
	
43
	protected String propertyName;
44
	protected List<String> values;
45
	protected int fMin;
46
	protected int fMax;
47
	
48
	protected String name;
49
	
50
	/**
51
	 * 
52
	 */
53
	public TextsBalance(Corpus corpus) {
54
		this.corpus = corpus;
55
		
56
		this.fMin = 999999999;
57
		this.fMax = 0;
58
	}
59

  
60
	
61
	/**
62
	 * @param method 1: use CQL to solve matches, 2 uses corpus struct indexes, 2 is faster !
63
	 * @param method
64
	 * @param su
65
	 * @param suPropertyName
66
	 * @param groupByTexts
67
	 * @throws CqiClientException
68
	 */
69
	public void compute(int method, StructuralUnit su, String suPropertyName, boolean groupByTexts) throws CqiClientException {
70
		
71
		this.name = su.getName() + "@" + suPropertyName + " (group by texts = " + groupByTexts + ")";
72
		
73
		Log.warning("Compute balance with metadata propertyName = " + suPropertyName + ", structural unit = " + su.getName() + " and count_texts = " + groupByTexts);
74
		try {
75
			if (suPropertyName == null || suPropertyName.length() == 0) return;
76
			
77
			
78
			this.dataset = new HashMap<Integer, Comparable[]>();
79

  
80
			this.propertyName = suPropertyName;
81
			StructuralUnitProperty p = su.getProperty(suPropertyName);
82
			this.values = p.getValues();
83
			Collections.sort(values);
84

  
85

  
86
			//int method = 2;
87
			//System.out.println("Method: "+method);
88
			//long time = System.currentTimeMillis();
89
			if (method == 1) { // using CQL to solve matches
90
				for (String value : values) {
91
					int v = 0;
92
					if (groupByTexts) {
93
						QueryResult r = corpus.query(new Query("<"+p.getFullName()+"=\""+value+"\">[]"), "tmp", false);
94
						v = r.getNMatch();
95
						r.drop();
96
					} else {
97
						QueryResult r = corpus.query(new Query("[_."+p.getFullName()+"=\""+value+"\"] expand to text"), "tmp", false);
98
						int t = 0;
99
						for (Match m : r.getMatches()) t += m.getLength();
100
						v = t;
101
						r.drop();
102
					}
103
					if (v < fMin) fMin=v;
104
					if (v > fMax) fMax=v;
105
					dataset.put(v, new Comparable[]{p.getName(), value});
106
				}
107
			} else {
108
				AbstractCqiClient CQI = Toolbox.getCqiClient();
109
				if (CQI instanceof NetCqiClient) {
110
					System.out.println("Error: CQP eval method only available with CQP memory mode");
111
					return;
112
				}
113

  
114
				String supqn = p.getQualifiedName();
115
				int nsup = CQI.attributeSize(supqn);
116

  
117
				ArrayList<Match> sup_limits = new ArrayList<Match>(nsup);
118
				for (int i = 0 ; i < nsup ; i++) {
119
					int[] l = CQI.struc2Cpos(supqn, i);
120
					sup_limits.add(new Match(l[0], l[1]));
121
				}
122
				//System.out.println("All sup limits are "+sup_limits);
123
				List<Match> corpus_matches = corpus.getMatches();
124
				//System.out.println("corpus matches: "+corpus_matches);
125
				ArrayList<Integer> inter = intersect(corpus_matches, sup_limits);
126
				//System.out.println( "No of $sup that covers $corpus: "+inter);
127
				int[] structid = new int[inter.size()];
128
				for (int i = 0 ; i < structid.length ; i++) structid[i] = inter.get(i);
129

  
130
				String[] inter_values = CQI.struc2Str(supqn, structid);
131
				//System.out.println( " with values: "+Arrays.toString(inter_values));
132
				HashMap<String, Integer> inter_uniq = new HashMap<String, Integer>();
133

  
134
				if (groupByTexts) {
135
					for (String o : inter_values) {
136
						if (!inter_uniq.containsKey(o)) {
137
							inter_uniq.put(o, 0);
138
						}
139
						inter_uniq.put(o, inter_uniq.get(o) +1);
140
					}
141
				} else {
142
					for (int imatch = 0 ; imatch < inter.size() ; imatch++) {
143
						String o = inter_values[imatch];
144
						if (!inter_uniq.containsKey(o)) {
145
							inter_uniq.put(o, 0);
146
						}
147
						int s = sup_limits.get(inter.get(imatch)).getLength();
148
						inter_uniq.put(o, inter_uniq.get(o) + s);
149

  
150
					}
151
				}
152
				Object[] sortedkeys = inter_uniq.keySet().toArray();
153
				Arrays.sort(sortedkeys);
154
				for (Object k : sortedkeys) {
155
					int v = inter_uniq.get(k);
156
					if (v < fMin) fMin=v;
157
					if (v > fMax) fMax=v;
158
					dataset.put(v, new Comparable[]{p.getName(), k.toString()});
159
					
160
				}
161
			}
162
		}
163
		catch(Exception e) {
164
			System.out.println("Error while computing text informations: "+e);
165
			e.printStackTrace();
166
		}
167
	}
168
	
169
	
170
	/**
171
	 * 
172
	 * @param corpus
173
	 * @param structs
174
	 * @return
175
	 */
176
	public static ArrayList<Integer> intersect(List<Match> corpus, List<Match> structs) {
177
		int ai=0, bi=0;
178
		ArrayList<Integer> result = new ArrayList<Integer>();
179

  
180
		while (ai < corpus.size() && bi < structs.size() ) {
181
			if (structs.get(bi).contains(corpus.get(ai))) { 
182
				result.add(bi);
183
				ai++; 
184
			} else if (corpus.get(ai).contains(structs.get(bi))) { 
185
				result.add(bi);
186
				bi++; 
187
			} else { 
188
				if (structs.get(bi).getStart() < corpus.get(ai).getStart()) {
189
					bi++;
190
				} else {
191
					ai++;	
192
				}
193
			} 
194
		}
195

  
196
		return result;
197
	}
198

  
199

  
200
	/**
201
	 * @return the dataset
202
	 */
203
	public HashMap<Integer, Comparable[]> getDataset() {
204
		return dataset;
205
	}
206

  
207

  
208
	/**
209
	 * @return the corpus
210
	 */
211
	public Corpus getCorpus() {
212
		return corpus;
213
	}
214

  
215

  
216
	/**
217
	 * @return the propertyName
218
	 */
219
	public String getPropertyName() {
220
		return propertyName;
221
	}
222

  
223

  
224
	/**
225
	 * @return the values
226
	 */
227
	public List<String> getValues() {
228
		return values;
229
	}
230

  
231

  
232
	/**
233
	 * @return the fMin
234
	 */
235
	public int getFMin() {
236
		return fMin;
237
	}
238

  
239

  
240
	/**
241
	 * @return the fMax
242
	 */
243
	public int getFMax() {
244
		return fMax;
245
	}
246

  
247

  
248
	@Override
249
	public boolean toTxt(File outfile, String encoding, String colseparator, String txtseparator) throws Exception {
250
		// TODO Auto-generated method stub
251
		return false;
252
	}
253

  
254

  
255
	@Override
256
	public void clean() {
257
		// TODO Auto-generated method stub
258
		
259
	}
260

  
261

  
262
	@Override
263
	public boolean delete() {
264
		return this.corpus.removeResult(this);
265
	}
266

  
267

  
268
	@Override
269
	public HasResults getParent() {
270
		return this.corpus;
271
	}
272

  
273

  
274
	/**
275
	 * @return the name
276
	 */
277
	public String getName() {
278
		return name;
279
	}
280
	
281
	
282
}
0 283

  

Formats disponibles : Unified diff