001    package nl.cwi.sen1.visplugin.barchart;
002    
003    import java.awt.Color;
004    
005    import javax.swing.JLabel;
006    import javax.swing.JPanel;
007    
008    import nl.cwi.sen1.relationstores.Factory;
009    import nl.cwi.sen1.relationstores.types.Integer;
010    import nl.cwi.sen1.relationstores.types.RElem;
011    import nl.cwi.sen1.relationstores.types.RElemElements;
012    import nl.cwi.sen1.relationstores.types.RTuple;
013    import nl.cwi.sen1.relationstores.types.RType;
014    import nl.cwi.sen1.relationstores.types.idcon.IdCon;
015    import nl.cwi.sen1.visplugin.VisualizationPluginWindow;
016    
017    import org.jfree.chart.ChartFactory;
018    import org.jfree.chart.ChartPanel;
019    import org.jfree.chart.JFreeChart;
020    import org.jfree.chart.axis.CategoryAxis;
021    import org.jfree.chart.axis.CategoryLabelPositions;
022    import org.jfree.chart.axis.NumberAxis;
023    import org.jfree.chart.plot.CategoryPlot;
024    import org.jfree.chart.plot.PlotOrientation;
025    import org.jfree.chart.renderer.category.CategoryItemRenderer;
026    import org.jfree.data.category.CategoryDataset;
027    import org.jfree.data.category.DefaultCategoryDataset;
028    
029    /**
030     * BarChart Plugin VisualisationWindow. Shows a bar chart.
031     * Original code : PieChart plugin ( A. Belgraver, R. van Remortel )
032     * @author Srinivasan Tharmarajah
033     */
034    public class BCVisualizationWindow extends VisualizationPluginWindow {
035    
036        /**
037         * Render the RTuple in a Bar Chart.
038         * 
039         * @param fact
040         *            RTuple with the information
041         * @return JPanel holding the bar chart
042         * @author A. Belgraver
043         * @author R. van Remortel
044         * @author Srinivasan Tharmarjah
045         * @date 07-3-2007
046         */
047        public JPanel render(RTuple fact) {
048            // Check if the fact is a supported Rtype.
049            if (!isTypeSupported(fact)) {
050                // for not supported type show an error message.
051                JPanel jp = new JPanel();
052                jp.add(new JLabel("Not a supported type"+fact.getRtype().toString()));
053                return jp;
054            }
055    
056            // Create and return the piechart.
057            String name = getRTupleName(fact);
058            CategoryDataset dataset = convertRTupleToDataset(fact);
059            JFreeChart chart = createPieChart(name, dataset);
060    
061            return new ChartPanel(chart,true,false,true,true,true);
062        }
063    
064        /**
065         * Set a new Factory object, for testing purposes.
066         * 
067         * @param factory
068         * Factory to use
069         * @author A. Belgraver
070         * @date 07-3-2007
071         */
072        public void setFactory(Factory factory) {
073            m_factory = factory;
074        }
075    
076        /**
077         * Check if a given RType is supported by this visualisation.
078         * 
079         * @param fact
080         *            The facts for which to verify if the type is supported
081         * @return True if it itype is supported
082         * @author Aldert Boerhoop
083         * @author Anton Gerdessen
084         * @author Srinivasan Tharmarajah
085         * @date 12-03-2007
086         */
087        public boolean isTypeSupported(RTuple fact) {
088            boolean match = (isRelIntStr(fact) || isRelStrInt(fact) || isRelIntInt(fact) );
089    
090            return match;
091        }
092    
093        /**
094         * Check to see if the RTuple is indeed a str,int relation.
095         * 
096         * @param fact
097         *            RTuple to test
098         * @return True if it is the correct str,int type
099         * @author A. Belgraver
100         * @author R. van Remortel
101         * @author Srinivasan Tharmarajah
102         * @author Aldert Boerhoop (reviewer)
103         * @author Anton Gerdessen (reviewer)
104         * @date 20-2-2007
105         * @todo Needs better implementation needs to be resolved reflection, dynamic 
106         * dispatch... in a the base or utility class for all plugins, remark by Anton G.     * 
107         */
108        private boolean isRelIntStr(RTuple fact) {
109            RType rType = m_factory.RTypeFromString("relation([int,str])");
110            boolean match = rType.equals(fact.getRtype());
111            
112            return match;
113        }
114    
115        /**
116         * Check to see if the RTuple is indeed a str,int relation.
117         * 
118         * @param fact
119         *            RTuple to test
120         * @return True if it is the correct str,int type
121         * @author A. Belgraver
122         * @author R. van Remortel
123         * @author Srinivasan Tharmarajah
124         * @author Aldert Boerhoop (reviewer)
125         * @author Anton Gerdessen (reviewer)
126         * @date 20-2-2007
127         * @todo Needs better implementation needs to be resolved reflection, dynamic 
128         * dispatch... in a the base or utility class for all plugins, remark by Anton G.     * 
129         */
130        private boolean isRelStrInt(RTuple fact) {
131            RType rType = m_factory.RTypeFromString("relation([str,int])");
132            boolean match = rType.equals(fact.getRtype());
133            
134            return match;
135        }
136    
137        /**
138         * Get the name of the RTuple.
139         * 
140         * @param fact
141         *            RTuple holding information
142         * @return String holding the name of the tuple
143         * @author A. Belgraver
144         * @author R. van Remortel
145         * @author Aldert Boerhoop (reviewer)
146         * @author Anton Gerdessen (reviewer)
147         * @date 07-3-2007
148         * @todo Needs better implementation needs to be resolved reflection, dynamic 
149         * dispatch... in a the base or utility class for all plugins, remark by Anton G.
150         */
151        public String getRTupleName(RTuple fact) {
152            IdCon idCon = (IdCon) fact.getVariable();
153            return idCon.getString();
154        }
155    
156        /**
157         * Create the bar chart.
158         * 
159         * @param title
160         *            Name to display on screen
161         * @param dataset
162         *            Dataset to show
163         * @return a JFreeChart chart
164         * @author Srinivasan Tharmarajah
165         * @date 12-03-2007
166         */
167    private JFreeChart createPieChart(String title, CategoryDataset dataset) {
168            
169        // create the chart...
170        final JFreeChart chart = ChartFactory.createBarChart(
171            title,                    // chart title
172            "Fact",                   // domain axis label
173            "Value",                  // range axis label
174            dataset,                  // data
175            PlotOrientation.VERTICAL, // orientation
176            false,                    // include legend
177            true,                     // tooltips?
178            false                     // URLs?
179        );
180    
181        // set the background color for the chart...
182        chart.setBackgroundPaint(Color.white);
183    
184        // get a reference to the plot for further customisation...
185        final CategoryPlot plot = chart.getCategoryPlot();
186        plot.setBackgroundPaint(Color.lightGray);
187        plot.setDomainGridlinePaint(Color.white);
188        plot.setRangeGridlinePaint(Color.white);
189        
190        // set the range axis to display integers only...
191        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
192        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
193        rangeAxis.setUpperMargin(0.15);
194        
195        // disable bar outlines...
196        final CategoryItemRenderer renderer = plot.getRenderer();
197        renderer.setSeriesItemLabelsVisible(0, Boolean.TRUE);
198        
199        final CategoryAxis domainAxis = plot.getDomainAxis();
200        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
201        
202        return chart;
203            
204        }
205    
206        /**
207         * Convert RTuple into a BarChart Dataset.
208         * 
209         * @param fact
210         *            RTuple with the data
211         * @return BarChart dataset
212         * @author A. Belgraver
213         * @author R. van Remortel
214         * @author Srinivasan Tharmarajah
215         * @date 12-03-2007
216         */
217        public CategoryDataset convertRTupleToDataset(RTuple fact) {
218            RElem set = fact.getValue();
219            RElemElements elements = set.getElements();
220            
221            final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
222            
223            while (elements.hasTail()) {
224                RElem headElement = elements.getHead();
225                // Replace the current looping set with: ( set - head ).
226                elements = elements.getTail();
227    
228                // HeadElement itselfs is a tuple <str,int> or <int,str>.
229                RElemElements tuple = headElement.getElements();
230    
231                // Disassemble the tuple into its parts.
232                String name = "";
233                nl.cwi.sen1.relationstores.types.Integer value;
234                
235                if (isRelStrInt(fact)) {
236                    name = tuple.getRElemAt(0).getStrCon();
237                    value = tuple.getRElemAt(1).getInteger();
238                }
239                else if (isRelIntStr(fact))  {
240                    name = tuple.getRElemAt(1).getStrCon();
241                    value = tuple.getRElemAt(0).getInteger();
242                }
243                else if (isRelIntInt(fact)) {
244                    Integer i = tuple.getRElemAt(1).getInteger();
245                    if (i.isNatCon()) {
246                            name = "" + i.getNatCon();
247                    }
248                    else if (i.isNegative()) {
249                            name = "-" + i.getNatCon();
250                    }
251                    else if (i.isPositive()) {
252                            name = "+" + i.getNatCon();
253                    }
254                    value = tuple.getRElemAt(0).getInteger();
255                }
256                else{
257                    throw new RuntimeException("Unknown relation type.");
258                }
259                
260                // Store the current tuple in the dataset.
261                dataset.addValue(Double.valueOf(value.getNatCon()), name, name);
262            }
263            return dataset;
264        }
265    
266            private boolean isRelIntInt(RTuple fact) {
267                     RType rType = m_factory.RTypeFromString("relation([int,int])");
268                    boolean match = rType.equals(fact.getRtype());
269                    
270                    return match;
271            }
272    
273       }