You are viewing a plain text version of this content. The canonical link for it is here.
Posted to alois-commits@incubator.apache.org by fl...@apache.org on 2010/11/04 18:27:42 UTC
svn commit: r1031127 [15/22] - in /incubator/alois/trunk: ./ bin/ debian/
doc/ etc/ etc/alois/ etc/alois/apache2/ etc/alois/environments/
etc/alois/prisma/ etc/cron.d/ etc/default/ etc/logrotate.d/ prisma/
prisma/bin/ prisma/conf/ prisma/conf/prisma/ p...
Added: incubator/alois/trunk/rails/java/CreateChart.java
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/java/CreateChart.java?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/java/CreateChart.java (added)
+++ incubator/alois/trunk/rails/java/CreateChart.java Thu Nov 4 18:27:22 2010
@@ -0,0 +1,663 @@
+import java.awt.*;
+import java.io.*;
+// import java.util.*;
+// import org.jfree.chart.imagemap.*;
+import org.jfree.chart.*;
+import org.jfree.chart.entity.*;
+import org.jfree.chart.plot.*;
+import org.jfree.data.category.*;
+import org.jfree.data.general.*;
+import org.jfree.util.*;
+import org.jfree.ui.TextAnchor;
+import org.jfree.chart.labels.*;
+import org.jfree.chart.renderer.xy.*;
+import org.jfree.chart.renderer.category.*;
+import org.jfree.data.xy.*;
+import org.jfree.chart.axis.*;
+// import org.jfree.chart.labels.*;
+import org.jfree.chart.urls.*;
+import java.net.URLEncoder;
+import java.awt.image.BufferedImage;
+/**
+ * Creates an HTML image map for a multiple pie chart.
+ */
+public class CreateChart {
+
+ public class MyGenerator implements CategoryURLGenerator,
+ CategoryToolTipGenerator,
+ PieURLGenerator,
+ PieToolTipGenerator,
+ XYURLGenerator,
+ XYToolTipGenerator {
+ private String prefix = "index.html";
+ private String seriesParameterName = "series";
+ private String categoryParameterName = "category";
+ private String rangeParameterName = "range";
+ private String rangeKey = null;
+ private CreateChart createChart = null;
+
+ private CategoryDataset theDataset = null;
+
+ public MyGenerator(String prefix, CategoryDataset ds) {
+ super();
+ this.prefix = prefix;
+ this.theDataset = ds;
+ }
+
+ public MyGenerator(String prefix) {
+ this.prefix = prefix;
+ }
+ public MyGenerator(String prefix, String rangeKey, CreateChart createChart) {
+ this.prefix = prefix;
+ this.rangeKey = rangeKey;
+ this.createChart = createChart;
+ }
+
+ public MyGenerator(String prefix,
+ String seriesParameterName,
+ String categoryParameterName) {
+ this.prefix = prefix;
+ this.seriesParameterName = seriesParameterName;
+ this.categoryParameterName = categoryParameterName;
+ }
+
+ public MyGenerator(String prefix,
+ String seriesParameterName,
+ String categoryParameterName,
+ String rangeParameterName,
+ String rangeKey) {
+ this.prefix = prefix;
+ this.seriesParameterName = seriesParameterName;
+ this.categoryParameterName = categoryParameterName;
+ this.rangeParameterName = rangeParameterName;
+ this.rangeKey = rangeKey;
+ }
+
+ public String myGenerateURL(Comparable seriesKey, Comparable categoryKey, Comparable rangeKey) {
+ if (categoryKey.toString().equals("<<REST>>") ||
+ seriesKey.toString().equals("<<REST>>") ||
+ (rangeKey != null && rangeKey.toString().equals("<<REST>>"))) { return "";}
+
+ String url = this.prefix;
+ boolean firstParameter = url.indexOf("?") == -1;
+
+ if (categoryKey.toString().equals("rest_value")) { return "";}
+ if (seriesKey.toString().equals("rest_serie")) { return "";}
+
+ url += firstParameter ? "?" : "&";
+ try {
+ url += this.seriesParameterName + "="
+ + URLEncoder.encode(seriesKey.toString(),"UTF-8");
+ url += "&" + this.categoryParameterName + "="
+ + URLEncoder.encode(categoryKey.toString(),"UTF-8");
+ if (rangeKey != null) {
+ url += "&" + this.rangeParameterName + "="
+ + URLEncoder.encode(rangeKey.toString(),"UTF-8");
+ }
+ }
+ catch ( java.io.UnsupportedEncodingException uee ) {
+ uee.printStackTrace();
+ }
+
+ return url;
+ }
+
+ public String myGenerateToolTip(Comparable seriesKey, Comparable categoryKey, Comparable rangeKey, Number value) {
+ String text = "";
+ if (this.rangeKey != null && !this.rangeKey.equals("<<NULL>>")) {
+ text += this.rangeKey + ", ";
+ }
+
+ if (seriesKey != null && !seriesKey.toString().equals("<<NULL>>")) {
+ text += seriesKey.toString() + ", ";
+ }
+
+ text += this.createChart.xAxis + "=" + categoryKey.toString() + ", ";
+
+ text += "value: " + value;
+ return text;
+ }
+
+ /** Pie **/
+
+ public String generateURL(PieDataset data, Comparable categoryKey, int pieIndex) {
+ Comparable seriesKey = theDataset.getRowKey(pieIndex);
+ return myGenerateURL(seriesKey, categoryKey, null);
+ }
+ public String generateToolTip(PieDataset data, Comparable categoryKey) {
+ /** not working **/
+ Comparable seriesKey = theDataset.getRowKey(0);
+ return myGenerateToolTip(seriesKey, categoryKey, null,999);
+ }
+
+
+ /** Category **/
+
+ public String generateURL(CategoryDataset dataset,
+ int series,
+ int category) {
+ Comparable seriesKey = dataset.getRowKey(series);
+ Comparable categoryKey = dataset.getColumnKey(category);
+
+ return myGenerateURL(seriesKey, categoryKey, this.rangeKey);
+ }
+
+ public String generateToolTip(CategoryDataset dataset,
+ int series, int category) {
+ Comparable seriesKey = dataset.getRowKey(series);
+ Comparable categoryKey = dataset.getColumnKey(category);
+
+ return myGenerateToolTip(seriesKey, categoryKey, this.rangeKey,dataset.getValue(seriesKey,categoryKey));
+ }
+
+ /** XY **/
+ public String generateURL(XYDataset dataset, int series, int item) {
+ Comparable seriesKey = dataset.getSeriesKey(series);
+ Comparable categoryKey = (Comparable)dataset.getX(series,item);
+
+ return myGenerateURL(seriesKey, categoryKey, this.rangeKey);
+ }
+
+ public String generateToolTip(XYDataset dataset, int series, int item) {
+ Comparable seriesKey = dataset.getSeriesKey(series);
+ Comparable categoryKey = (Comparable)dataset.getX(series,item);
+
+ return myGenerateToolTip(seriesKey, categoryKey, this.rangeKey,dataset.getY(series,item));
+ }
+
+
+ }
+
+
+ public static final boolean LEGEND = true;
+ public static final boolean TOOL_TIPS = true;
+ public static final boolean URLS = true;
+
+ public String filebase;
+ public JFreeChart chart;
+ public CategoryDataset[] category_datasets;
+ public XYDataset[] xy_datasets;
+ public String[] rangeNames;
+ public PieDataset pie_dataset;
+ public String htmlFile;
+ public String imageMapFile;
+ public String imageFile;
+ public String URLPrefix;
+
+ public String chartTitle;
+ public String xAxis;
+ public String yAxis;
+ public String type;
+ public boolean stacked = false;
+ public PlotOrientation orientation;
+
+ public int rangeCount = 0;
+ public int serieCount = 0;
+
+ public int width = 600;
+ public int height = 400;
+
+ /**
+ * Default constructor.
+ */
+ public CreateChart(String filebase, String URLPrefix) {
+ super();
+ this.filebase = filebase;
+ this.htmlFile = filebase + ".html";
+ this.imageMapFile = filebase + ".map";
+ this.imageFile = filebase + ".png";
+ this.URLPrefix = URLPrefix;
+ }
+
+ public void saveFiles() {
+
+ // save it to an image
+ try {
+ ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
+ File file1 = new File(this.imageFile);
+ ChartUtilities.saveChartAsPNG(file1, chart, this.width, this.height, info);
+
+ // write an HTML page incorporating the image with an image map
+ File file2 = new File(this.htmlFile);
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(file2));
+ PrintWriter writer = new PrintWriter(out);
+ writer.println("<HEAD><TITLE>JFreeChart Image Map</TITLE></HEAD>");
+ writer.println("<BODY>");
+ writer.println(ChartUtilities.getImageMap("chart", info));
+ writer.println("<IMG SRC=\"" + this.imageFile + "\" "
+ + "WIDTH=\"" + this.width +"\" HEIGHT=\"" + this.height + "\" BORDER=\"0\" USEMAP=\"#chart\">");
+ writer.println("</BODY>");
+ writer.println("</HTML>");
+ writer.close();
+
+ File file3 = new File(this.imageMapFile);
+ out = new BufferedOutputStream(new FileOutputStream(file3));
+ writer = new PrintWriter(out);
+ writer.println(ChartUtilities.getImageMap("chart", info));
+ writer.close();
+
+ }
+ catch (IOException e) {
+ System.out.println(e.toString());
+ }
+
+ }
+
+ private Object callFunction(Object obj, String name) throws Exception {
+ return callFunction(obj,name,new Object[] {});
+ }
+ private Object callFunction(Object obj, String name, Object arg) throws Exception {
+ return callFunction(obj,name,new Object[] {arg});
+ }
+ private Object callFunction(Object obj, String name, Object[] args) throws Exception {
+ Class[] classes = new Class[args.length];
+ String classes_string = "";
+ for (int i = 0; i<args.length; i++) {
+ classes[i] = args[i].getClass();
+ try {
+ classes[i] = (Class)classes[i].getField("TYPE").get(classes[i]);
+ } catch (NoSuchFieldException ex) {
+ // ok this is not a primitive type
+ }
+ classes_string += args[i].getClass().getName() + " ";
+ }
+
+ try {
+ return callFunction(obj, name, args, classes);
+ } catch ( NoSuchMethodException e) {
+ throw new Exception("Method " + obj.getClass().getName() + "." + name + "(" + classes_string + ") not found.");
+ }
+ }
+
+ private Object callFunction(Object obj, String name, Object[] args, Class[] classes) throws Exception {
+ return obj.getClass().getMethod(name,classes).invoke(obj,args);
+ }
+
+ private void configureColors(Object renderer) throws Exception {
+ Class[] pc = new Class[] {Integer.TYPE, Class.forName("java.awt.Paint")};
+ java.awt.Color secondColor = Color.white;
+ int i = 0;
+ if (false) {
+ for (java.awt.Paint item : ChartColor.createDefaultPaintArray()) {
+ callFunction(renderer, "setSeriesPaint",
+ new java.lang.Object[]
+ {i,(java.awt.Paint)
+ new GradientPaint(
+ 0.0f, 0.0f, (java.awt.Color)item,
+ 1000, 0.0f, secondColor
+ )},pc);
+ i += 1;
+ }
+ } else {
+ for (java.awt.Paint item : ChartColor.createDefaultPaintArray()) {
+ callFunction(renderer, "setSeriesPaint",
+ new java.lang.Object[]
+ {i, (java.awt.Paint)item },pc);
+ i += 1;
+ }
+ }
+
+ for (java.awt.Paint item : ChartColor.createDefaultPaintArray()) {
+ BufferedImage bi = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB);
+ Graphics2D big = bi.createGraphics();
+ big.setColor((java.awt.Color)item);
+ big.fillRect(0, 0, 1, 1);
+ big.fillOval(1, 1, 2, 2);
+ big.setColor(secondColor);
+ big.fillRect(1, 0, 2, 1);
+ big.fillOval(0, 1, 1, 2);
+ Rectangle r = new Rectangle(0, 0, 2, 2);
+ callFunction(renderer, "setSeriesPaint",new java.lang.Object[] {i,(java.awt.Paint) new TexturePaint(bi, r)},pc);
+ i += 1;
+ }
+
+ for (java.awt.Paint item : ChartColor.createDefaultPaintArray()) {
+ BufferedImage bi = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB);
+ Graphics2D big = bi.createGraphics();
+ big.setColor((java.awt.Color)item);
+ big.fillRect(0, 0, 1, 1);
+ big.fillOval(1, 0, 2, 1);
+ big.setColor(secondColor);
+ big.fillRect(0, 1, 1, 2);
+ big.fillOval(1, 1, 2, 2);
+ Rectangle r = new Rectangle(0, 0, 2, 2);
+ callFunction(renderer, "setSeriesPaint",new java.lang.Object[] {i, (java.awt.Paint)new TexturePaint(bi, r)},pc);
+ i += 1;
+ }
+ }
+
+ private void correctLegend(Object plot,Object subplot) throws Exception {
+
+ Object li = callFunction(subplot,"getLegendItems");
+ callFunction(plot,"setFixedLegendItems",new Object[] { li });
+ if (((Integer)callFunction(li,"getItemCount")) == 1 &&
+ ((String)callFunction(callFunction(li,"get",0),"getLabel")).equals("<<NULL>>")) {
+ callFunction(plot,"setFixedLegendItems",new LegendItemCollection());
+ }
+ }
+
+
+
+ private XYItemRenderer createLineRenderer() throws Exception {
+ XYItemRenderer renderer;
+ if (this.stacked)
+ renderer = new StackedXYAreaRenderer2();
+ else
+ renderer = new StandardXYItemRenderer( StandardXYItemRenderer.SHAPES_AND_LINES);
+ configureColors(renderer);
+ return renderer;
+ }
+ private BarRenderer createBarRenderer() throws Exception {
+ // RENDERER
+ BarRenderer renderer;
+ if (this.stacked)
+ renderer = new StackedBarRenderer();
+ else
+ renderer = new BarRenderer();
+
+ ItemLabelPosition position1 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER);
+ ItemLabelPosition position2 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER);
+ renderer.setPositiveItemLabelPosition(position1);
+ renderer.setNegativeItemLabelPosition(position2);
+ renderer.setDrawBarOutline(false);
+ configureColors(renderer);
+ return renderer;
+ }
+
+
+
+ /**
+ * Creates a sample chart with the given dataset.
+ *
+ * @param dataset the dataset.
+ *
+ * @return A sample chart.
+ */
+ private void createPieChart() throws Exception {
+ this.chart = ChartFactory.createMultiplePieChart(
+ this.chartTitle, // chart title
+ this.category_datasets[0], // dataset
+ TableOrder.BY_ROW,
+ CreateChart.LEGEND, // include legend
+ CreateChart.TOOL_TIPS,
+ CreateChart.URLS
+ );
+ MultiplePiePlot plot = (MultiplePiePlot) this.chart.getPlot();
+ JFreeChart subchart = plot.getPieChart();
+
+ PiePlot p = (PiePlot) subchart.getPlot();
+ /* p.setLabelGenerator(new StandardPieItemLabelGenerator("{0}"));*/
+ p.setLabelFont(new Font("SansSerif", Font.PLAIN, 8));
+ p.setInteriorGap(0.30);
+ MyGenerator generator = new MyGenerator(this.URLPrefix,this.category_datasets[0]);
+ p.setURLGenerator(generator);
+ // p.setToolTipGenerator(generator);
+ }
+
+ public void createLineChart() throws Exception {
+ // parent plot...
+ final NumberAxis domainAxis = new NumberAxis(this.xAxis);
+ domainAxis.setAutoRangeIncludesZero(false);
+ domainAxis.setAutoRangeStickyZero(false);
+ domainAxis.setAutoRange(true);
+
+ final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(domainAxis);
+
+ //plot.setGap(10.0);
+ for (int range = 0; range<rangeCount; range++) {
+
+ NumberAxis rangeAxis = new NumberAxis(this.rangeNames[range] + " " + this.yAxis);
+ if (this.rangeNames[range] == null) {
+ rangeAxis = new NumberAxis(this.yAxis);
+ }
+ rangeAxis.setAutoRangeIncludesZero(true);
+ rangeAxis.setAutoRangeStickyZero(true);
+ rangeAxis.setAutoRange(true);
+
+ XYItemRenderer my_renderer = createLineRenderer();
+ MyGenerator generator = new MyGenerator(this.URLPrefix, this.rangeNames[range], this);
+ my_renderer.setURLGenerator(generator);
+ my_renderer.setBaseToolTipGenerator(generator);
+
+
+ final XYPlot subplot = new XYPlot(this.xy_datasets[range],
+ null, rangeAxis, my_renderer);
+
+ subplot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
+ plot.add(subplot, 1);
+
+ correctLegend(plot, subplot);
+
+ plot.setOrientation(this.orientation);
+ }
+
+
+ // return a new chart containing the overlaid plot...
+ this.chart = new JFreeChart(this.chartTitle,
+ JFreeChart.DEFAULT_TITLE_FONT, plot, true);
+ }
+
+ public void createBarChart() throws Exception {
+ // create the chart...
+
+ CategoryAxis categoryAxis = new CategoryAxis(this.xAxis);
+ // categoryAxis = null;
+
+
+ CombinedDomainCategoryPlot plot = new CombinedDomainCategoryPlot(categoryAxis);
+
+ for (int range = 0; range<rangeCount; range++) {
+ BarRenderer my_renderer = createBarRenderer();
+ MyGenerator generator = new MyGenerator(this.URLPrefix, this.rangeNames[range], this);
+ my_renderer.setBaseItemURLGenerator(generator);
+ my_renderer.setBaseToolTipGenerator(generator);
+
+ ValueAxis valueAxis = new NumberAxis(this.rangeNames[range] + " " + this.yAxis);
+
+ if (this.rangeNames[range] == null) {
+ valueAxis = new NumberAxis(this.yAxis);
+ }
+
+ CategoryPlot subplot = new CategoryPlot(this.category_datasets[range], categoryAxis, valueAxis,
+ my_renderer);
+
+ plot.add(subplot, 1);
+
+ // Correct Legend
+ correctLegend(plot,subplot);
+
+ subplot.setOrientation(this.orientation);
+
+ }
+
+
+ // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
+ this.chart = new JFreeChart(this.chartTitle, JFreeChart.DEFAULT_TITLE_FONT,
+ plot, true);
+
+ chart.setBackgroundPaint(Color.white);
+ plot.setBackgroundPaint(Color.lightGray);
+ plot.setDomainGridlinePaint(Color.white);
+ plot.setRangeGridlinePaint(Color.white);
+
+ // plot.clearDomainAxes();
+ final CategoryAxis domainAxis = plot.getDomainAxis();
+ domainAxis.setCategoryLabelPositions(
+ CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)
+ );
+ // OPTIONAL CUSTOMISATION COMPLETED.
+ }
+
+
+ public void createXYChart() throws Exception {
+ // create the chart...
+ this.chart = ChartFactory.createXYLineChart(
+ this.chartTitle, // chart title
+ this.xAxis, // x axis label
+ this.yAxis, // y axis label
+ this.xy_datasets[0], // data
+ this.orientation,
+ CreateChart.LEGEND, // include legend
+ CreateChart.TOOL_TIPS, // tooltips
+ CreateChart.URLS // urls
+ );
+
+ // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
+ chart.setBackgroundPaint(Color.white);
+ // get a reference to the plot for further customisation...
+ XYPlot plot = chart.getXYPlot();
+ plot.setBackgroundPaint(Color.lightGray);
+ // plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
+ plot.setDomainGridlinePaint(Color.white);
+ plot.setRangeGridlinePaint(Color.white);
+
+ XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
+ // renderer.setSeriesLinesVisible(1, false);
+ // renderer.setSeriesShapesVisible(1, false);
+ plot.setRenderer(renderer);
+
+ // change the auto tick unit selection to integer units only...
+ NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
+ rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
+ // OPTIONAL CUSTOMISATION COMPLETED.
+ // save the image to an appropriate location : The images folder in your Instant Rails application
+ }
+
+
+ public void createCategory1TestData() throws Exception {
+ double[][] data = new double[][] {
+ {3.0, 4.0, 3.0, 5.0},
+ {5.0, 7.0, 6.0, 8.0},
+ {5.0, 7.0, 3.0, 8.0},
+ {1.0, 2.0, 3.0, 4.0},
+ {2.0, 3.0, 2.0, 3.0}
+ };
+ CategoryDataset cd = DatasetUtilities.createCategoryDataset(
+ "Region ",
+ "Sales/Q",
+ data
+ );
+ this.category_datasets = new CategoryDataset[1];
+ this.category_datasets[0] = cd;
+ }
+
+
+
+
+ public void loadDataFromStdIn() throws IOException {
+ java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
+
+ // System.out.println("Chart title?");
+ this.chartTitle = stdin.readLine();
+
+ // System.out.println("Width?");
+ this.width = Integer.parseInt(stdin.readLine());
+ // System.out.println("Height?");
+ this.height = Integer.parseInt(stdin.readLine());
+
+ // System.out.println("X-Axis?");
+ this.xAxis = stdin.readLine();
+
+ // System.out.println("Y-Axis?");
+ this.yAxis = stdin.readLine();
+
+ // System.out.println("Series count?");
+ serieCount = Integer.parseInt(stdin.readLine());
+
+ // System.out.println("Range count?");
+ rangeCount = Integer.parseInt(stdin.readLine());
+
+ this.category_datasets = new CategoryDataset[rangeCount];
+ this.xy_datasets = new CategoryTableXYDataset[rangeCount];
+ this.rangeNames = new String[rangeCount];
+
+ for (int range = 0; range<rangeCount; range++) {
+ rangeNames[range] = stdin.readLine();
+ if (rangeNames[range].equals("<<NULL>>")) {
+ rangeNames[range] = null;
+ }
+
+ CategoryDataset category_dataset = new DefaultCategoryDataset();
+ category_datasets[range] = category_dataset;
+
+ //XYSeriesCollection xy_serie = new XYSeriesCollection();
+ CategoryTableXYDataset xy_dataset = new CategoryTableXYDataset();
+ xy_datasets[range] = xy_dataset;
+
+ for (int serie = 0; serie<serieCount; serie++) {
+ // System.out.println("Serie name?");
+ String serieName = stdin.readLine();
+
+ int rowCount = Integer.parseInt(stdin.readLine());
+ int columnCount = Integer.parseInt(stdin.readLine());
+
+ //final XYSeries xy_serie = new XYSeries(serieName);
+
+ for (int row = 0; row<rowCount; row++) {
+ // System.out.println("Category name?");
+ String categoryName = stdin.readLine();
+ for (int col = 0; col<columnCount; col++) {
+ String val = stdin.readLine();
+ // System.out.println(val + ":" + serieName + ":" + categoryName + "\n");
+
+ ((DefaultCategoryDataset)category_dataset).addValue(
+ Integer.parseInt(val),
+ serieName,
+ categoryName);
+ if (type.equals("line") || type.equals("lines")) {
+ //xy_serie.add(Float.parseFloat(categoryName), Float.parseFloat(val));
+ xy_dataset.add(Float.parseFloat(categoryName), Float.parseFloat(val), serieName);
+ }
+
+ }
+ }
+ // xy_serie.addSeries(xy_serie);
+ }
+ }
+ }
+
+ /**
+ * Starting point for the chart.
+ *
+ * @param args ignored.
+ */
+ public static void main(String[] args) {
+ try {
+ CreateChart chart = new CreateChart(args[0],args[1]);
+ chart.type = args[2];
+ chart.stacked = Boolean.parseBoolean(args[3]);
+ if (Boolean.parseBoolean(args[4]))
+ chart.orientation = PlotOrientation.HORIZONTAL;
+ else
+ chart.orientation = PlotOrientation.VERTICAL;
+
+ chart.loadDataFromStdIn(); // chart.createCategoryTestData();
+ //chart.createCategory2TestData();
+
+ if (chart.type.equals("bar"))
+ chart.createBarChart();
+ else if (chart.type.equals("pie"))
+ chart.createPieChart();
+ else if (chart.type.equals("line"))
+ chart.createLineChart();
+ else
+ throw new Exception("Unknown type '" + chart.type + "'");
+
+ chart.saveFiles();
+ System.exit(0);
+ } catch (Exception ex) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ ex.printStackTrace(pw);
+ pw.flush();
+ sw.flush();
+
+ System.out.print(sw.toString());
+
+ System.out.println(ex.toString());
+ System.exit(1);
+ }
+
+ }
+}
+
Added: incubator/alois/trunk/rails/lib/action_mailer-patch.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/action_mailer-patch.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/action_mailer-patch.rb (added)
+++ incubator/alois/trunk/rails/lib/action_mailer-patch.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,78 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module ActionMailer
+ # Represents a subpart of an email message. It shares many similar
+ # attributes of ActionMailer::Base. Although you can create parts manually
+ # and add them to the +parts+ list of the mailer, it is easier
+ # to use the helper methods in ActionMailer::PartContainer.
+ class Part
+ # Convert the part to a mail object which can be included in the parts
+ # list of another mail object.
+ def to_mail(defaults)
+ part = TMail::Mail.new
+
+ real_content_type, ctype_attrs = parse_content_type(defaults)
+
+ if @parts.empty?
+ part.content_transfer_encoding = transfer_encoding || "quoted-printable"
+ case (transfer_encoding || "").downcase
+ when "base64" then
+ part.body = TMail::Base64.folding_encode(body)
+ when "quoted-printable"
+ part.body = [normalize_new_lines(body)].pack("M*")
+ else
+ part.body = body
+ end
+
+ # Always set the content_type after setting the body and or parts!
+ if content_disposition == "attachment"
+ ctype_attrs.delete "charset"
+ end
+
+ # Also don't set filename and name when there is none (like in
+ # non-attachment parts)
+ if filename
+ ctype_attrs.delete "charset"
+ part.set_content_type(real_content_type, nil,
+ squish("name" => filename).merge(ctype_attrs))
+ part.set_content_disposition(content_disposition,
+ squish("filename" => filename).merge(ctype_attrs))
+ else
+ part.set_content_type(real_content_type, nil, ctype_attrs)
+ part.set_content_disposition(content_disposition)
+ end
+ else
+ if String === body
+ @parts.unshift Part.new(:charset => charset, :body => @body, :content_type => 'text/plain')
+ @body = nil
+ end
+
+ @parts.each do |p|
+ prt = (TMail::Mail === p ? p : p.to_mail(defaults))
+ part.parts << prt
+ end
+
+ if real_content_type =~ /multipart/
+ ctype_attrs.delete 'charset'
+ part.set_content_type(real_content_type, nil, ctype_attrs)
+ end
+ end
+
+ headers.each { |k,v| part[k] = v }
+
+ part
+ end
+ end
+end
Added: incubator/alois/trunk/rails/lib/alois/config.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/alois/config.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/alois/config.rb (added)
+++ incubator/alois/trunk/rails/lib/alois/config.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,97 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'yaml'
+
+if defined?(RAILS_ROOT)
+ ALOIS_DEFAULT_CONFIG = "#{RAILS_ROOT}/config/alois.conf" unless defined?(ALOIS_DEFAULT_CONFIG)
+else
+ ALOIS_DEFAULT_CONFIG = "/etc/alois/alois.conf" unless defined?(ALOIS_DEFAULT_CONFIG)
+end
+
+def get_replacements(configfile)
+ # prepare regexps
+ replacements = {}
+ configs = read_config(configfile, false)
+ for (configname,config) in configs
+ for (valuename,value) in config
+ replacements["{{#{configname}.#{valuename}}}"] = value
+ end if not config == nil
+ end
+ return replacements
+end
+
+def replace_configurations(replacements, value)
+ def str_sub(replacements, value)
+ for (reg,val) in replacements
+ value = value.gsub(reg.to_s,val.to_s)
+ end
+ print "WARNING: Not replaced:#{value}" if value =~ /\{\{/ or value =~ /\}\}/
+ return value
+ end
+
+ case value.class.to_s
+ when "String"
+ return str_sub(replacements, value)
+ when "Array"
+ return value.map { |v| replace_configurations(replacements, v)}
+ else
+ return value
+ end
+end
+
+
+def read_config(configfile = nil, with_replace = true)
+ configfile = ALOIS_DEFAULT_CONFIG unless configfile
+ return $current_config if $current_config_file == configfile and $current_replacement == with_replace
+
+ configfile = ALOIS_DEFAULT_CONFIG unless configfile
+ tree = YAML::parse(File.open(configfile))
+
+ configurations = tree["/configs/*"]
+ configurations = tree.select("/configs")[0].transform
+
+ for (name, configname) in configurations
+ c = tree.select("/#{configname}")[0]
+ c = c.transform if not c == nil
+ configurations[name] = c
+ end
+
+ if with_replace
+ replacements = get_replacements(configfile)
+
+ for (service, host) in configurations
+ throw "#{host} configuration not found!" unless host
+ for (name, value) in host
+ host[name] = replace_configurations(replacements, value)
+ end
+ end
+ end
+
+ $current_config_file = configfile
+ $current_config = configurations
+ $current_replacement = with_replace
+ throw "Configuration could not be loaded." unless configurations
+ return configurations
+end
+
+def get_config(name, property, default_value = nil)
+ v = read_config
+ return default_value unless v
+ v = v[name]
+ return default_value unless v
+ v = v[property]
+ return default_value unless v
+ return v
+end
Added: incubator/alois/trunk/rails/lib/alois/date_time_enhance.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/alois/date_time_enhance.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/alois/date_time_enhance.rb (added)
+++ incubator/alois/trunk/rails/lib/alois/date_time_enhance.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,185 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Time
+
+ def beginning_of_minute
+ change(:sec => 0)
+ end
+
+ def beginning_of_hour
+ change(:min => 0).beginning_of_minute
+ end
+
+
+ def end_of_minute
+ change(:sec => 59)
+ end
+
+ def end_of_hour
+ change(:min => 59).end_of_minute
+ end
+
+ # day and month already included
+
+ def end_of_week
+ 6.days.from_now(beginning_of_week).end_of_day
+ end
+
+ def end_of_year
+ change(:month => 12).end_of_month
+ end
+
+ def self.suggest(text, with_range = true)
+ text = text.strip
+
+ case text
+ when nil, ""
+ ret = ["beginning","end","last","this","today","yesterday","NUMBER"]
+ ret.push("from") if with_range
+ ret
+ when /^(beginning *)$/, /^(end *)$/
+ ret = ["last","this","today","yesterday","NUMBER"]
+ ret.push("from") if with_range
+ ret.map{|v| "#{$1} #{v}"}
+ when /^(from .* until)(.*)/
+ self.suggest($2,false).map{|v| "#{$1} #{v}"}
+ when /^(from)(.*)/
+ ret = self.suggest($2,false).map {|v| "#{$1} #{v}"}
+ if (($2 or "").strip.to_time rescue false)
+ ret.push("#{text} until")
+ end
+ ret
+ when /^(from .* )(-|to|until|till|up to) (.*)/
+ self.suggest($3).map {|v| "#{$1}#{$2} #{v}"}
+ when /^(beginning|end)? ?(\d+|this|last) *$/
+ ["day","days","week","weeks","year","years","hour","hours","month","months"].map {|v| "#{text} #{v}"}
+ when /^(\d+|from|this|last) (beginning|end)? ?(day|days|week|weeks|year|years|hour|hours) *$/
+ ["ago","from now"].map {|v| "#{text} #{v}"}
+ else
+ []
+ end
+ end
+
+end
+
+class String
+
+ alias_method :orig_to_time, :to_time
+ def to_time(from = Time.now)
+ if self =~ /(from )?(the )?(.*) (-|to|until|till|up to) (the )?(.*)/
+ first = $3.to_time(from)
+ second_str = $6
+ if second_str =~ /^(.*) later$/
+ return first.."#{$1} from now".to_time(first)
+ else
+ return first..second_str.to_time(from)
+ end
+ end
+
+ correction = :none
+
+ case self
+ when /^(at )?begin(ning)? (of )?(.*)$/
+ correction = :beginning
+ str = $4
+ when /^(at )?end(ing)? (of )?(.*)$/
+ correction = :end
+ str = $4
+ else
+ str = self
+ end
+
+ time = nil
+
+ case str
+ when "today"
+ num = 0
+ span = "day"
+ direction = "ago"
+ when "yesterday"
+ num = 1
+ span = "day"
+ direction = "ago"
+ when /^(\d+|last|this|the)? ?(day|days|week|weeks|year|years|month|months|hour|hours) ?(ago|from now)?$/
+ direction = ($3 or "ago")
+ direction = "from_now" if direction == "from now"
+ span = $2.singularize
+
+ case $1
+ when "last"
+ raise "'#{$3}' does not make sense with 'last'." if $3
+ num = 1
+ when "this","the"
+ raise "'#{$3}' does not make sense with 'this'." if $3
+ num = 0
+ when nil
+ num = 0
+ else
+ raise "Please add a direction 'ago' or 'from now' to the end #{$3}." unless $3
+ num = $1.to_i
+ end
+ else
+ begin
+ time = orig_to_time
+ case time.strftime("%T")
+ when /00:00:00$/
+ span = "day"
+ when /00:00$/
+ span = "hour"
+ else
+ span = "minute"
+ end
+ rescue ArgumentError
+ raise "Date not recognized '#{self}' ."
+ end
+ end
+
+ time = num.send(span).send(direction,from.to_time) unless time
+
+ case correction
+ when :beginning
+ time.send("beginning_of_#{span}")
+ when :end
+ time.send("end_of_#{span}")
+ else
+ time
+ end
+ end
+
+ def to_time_range(from = Time.now)
+ v = self.to_time(from)
+ if v.class == Range
+ v
+ else
+ "beginning of #{self} until end of #{self}".to_time(from)
+ end
+ end
+
+ def to_time_range_str(from = Time.now)
+ res = self.to_time_range(from)
+ res.first.strftime("%F %T")..res.last.strftime("%F %T")
+ end
+
+ def to_time_str(from = Time.now)
+ res = to_time(from)
+ if res.class.name == "Range"
+ res.first.strftime("%F %T")..res.last.strftime("%F %T")
+ else
+ res.strftime("%F %T")
+ end
+ end
+
+end
+
Added: incubator/alois/trunk/rails/lib/alois/utils.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/alois/utils.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/alois/utils.rb (added)
+++ incubator/alois/trunk/rails/lib/alois/utils.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,282 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require "yaml"
+require "zlib"
+begin
+ require "mysql"
+rescue LoadError
+ print "Unable to load mysql library #{$!}\n"
+end
+
+def question_continue
+ unless defined?(LIBISI)
+ print "Do you want to continue? Press ENTER, CTRL-C to abort\n"
+ STDIN.readline
+ else
+ exit 1 unless $ui.question("Do you want to continue?", :default => false)
+ end
+end
+
+def get_password(name)
+ return ENV["db_#{name}_password".upcase] if ENV["db_#{name}_password".upcase]
+ raise "Libisi not available, cannot get password for #{name}" unless $ui
+ $ui.password("Please enter #{name} password")
+end
+
+def check_mysql_password
+
+ # try to make a connetion on the localhost trough root without a pw
+ begin
+ dbh = connect_mysql_local_real(nil)
+
+ # if we reach here, this is bad,
+ # no password is defined for root
+ # ask user...
+
+ raise "Mysql has no root password defined, will not continue" unless
+ defined?(LIBISI)
+ raise "No mysql root password set" unless
+ $ui.question("No password for root user defined!!\nYou must define one to continue.\nDo you want to define one now?")
+ password = set_mysql_password("ALL", "*", "root@localhost")
+ rescue
+ raise if not $!.to_s =~ /Access denied for user/
+ $log.debug("OK there is a root pw!") if $log
+ end
+end
+
+
+def set_mysql_password(privileges, object, person, password = nil)
+ raise "Libisi not available, cannot set new password." unless $ui
+ if password == nil then
+ print
+ password = $ui.password("Set #{privileges} for #{object} to #{person}...\nPlease enter new password")
+ password2 = $ui.password("Please reenter new password")
+ raise "Password did not match!" if not password2 == password
+ raise "No password entered!" if password == "" or password == nil
+ raise "Do not use '\"'!" if (password =~ /\"/)
+ end
+
+ query = "GRANT #{privileges} PRIVILEGES ON #{object} TO #{person} IDENTIFIED BY \"#{password}\""
+ $log.info("Executing #{query.inspect}")
+ connect_mysql_local_real(nil).query(query)
+ password
+end
+
+# redirect to libisis host_name
+def hostname; host_name; end
+
+def db_root_password
+ check_mysql_password
+ # get the rootpassword
+ @password ||= (ENV["DB_ROOT_PASSWORD"] or get_password("root"))
+ @password
+end
+
+def connect_activerecord_local(db = "mysql")
+ ActiveRecord::Base.establish_connection({
+ :adapter => "mysql",
+ :database => db,
+ :host => "localhost",
+ :username => "root",
+ :port => 3306,
+ :password => db_root_password
+ })
+end
+
+def connect_mysql_local_real(pw, db = "mysql")
+ Mysql.real_connect("localhost", "root", pw, db)
+end
+
+def connect_mysql_local(database = "mysql")
+ conn = connect_mysql_local_real(db_root_password, database)
+end
+
+
+class Object
+ # computes a hash of a yaml serialization
+ # sort the lines first to get the same result
+ # even if attribute order changed.
+ def Object.yaml_hash(yaml)
+ yaml.split("\n").sort.join("\n").hash
+ end
+
+ # Load object from yaml
+ def Object.from_yaml(yaml)
+ ret = YAML.parse(yaml).transform
+ # fix, otherwise attributes_methods:160 will complain nil.[] on cached methods
+ ret.instance_eval("@attributes_cache ||= {}")
+ ret
+ end
+
+ # Load object from zipped yaml
+ def Object.from_zip(zip)
+ i = Zlib::Inflate.new()
+ i.inflate("x\234")
+ return from_yaml(i.inflate(Base64.decode64(zip)))
+ end
+
+ # Serialize object to zipped yaml
+ def Object.to_zip(obj)
+ d = Zlib::Deflate.new()
+ d.deflate(obj.to_yaml)
+ return Base64.encode64(d.deflate(nil))
+ end
+ # Calls Objects to_zip function
+ def to_zip
+ Object.to_zip(self)
+ end
+
+ # Helper function for loading ipranges from a file. Executes Class.create for each entry.
+ def Object.load_from_yaml(filename)
+ yaml_string = ""
+ yaml_string << IO.read(filename)
+ yaml = YAML::load(yaml_string)
+ yaml.each {|vals|
+ self.create(vals[1])
+ }
+ end
+
+ # Use from_yaml function of prisma for loading classes
+ def from_yaml(yaml)
+ self.class.from_yaml(yaml.strip)
+ end
+
+ # returns prisma yaml_hash
+ def yaml_hash
+ yaml = self.to_yaml
+ return Object.yaml_hash(yaml)
+ end
+
+ # TODO: describe this, is this still needed?
+ def load_from_yaml(filename)
+ yaml_string = ""
+ yaml_string << IO.read(filename)
+ yaml = YAML::load(yaml_string)
+ yaml.keys.sort.select {|name|
+ !self.respond_to?(:name) or !self.find_by_name(yaml[name]["name"])
+ }.map {|name|
+ self.create(yaml[name]) rescue $!.to_s
+ }
+ end
+
+ # Use from_zip of prisma
+ def from_zip(zip)
+ self.class.from_zip(zip)
+ end
+
+ alias_method :orig_to_yaml, :to_yaml
+ # This instance variables may not be serialized
+ # this constant is only used for yaml serialization
+ BAD_INSTANCE_VARIABLES = ["@datasource","@attributes_cache",
+ "@source_table_class","@table","@view","@report_template",
+ "@sentinel"] unless defined?(BAD_INSTANCE_VARIABLES)
+
+ # Removes BAD_INSTANCE_VARIABLES and yields
+ # a block. Instancevariables are set again
+ # afterwards.
+ def remove_bad_instance_variables(&block)
+ tmp = {}
+ BAD_INSTANCE_VARIABLES.each {|var|
+ tmp[var] = remove_instance_variable(var) if
+ instance_variable_defined?(var)
+ }
+ if block
+ ret = yield
+ tmp.each {|var,val| instance_variable_set(var,val)}
+ ret
+ end
+ end
+
+
+ # New to_yaml function that removes BAD_INSTANCE_VARIABLES
+ # before serializing. Original to_yaml function can be
+ # called with orig_to_yaml, but will probably not work.
+ def to_yaml( opts = {})
+ remove_bad_instance_variables {
+ self.orig_to_yaml(opts)
+ }
+ end
+
+end
+
+class ActiveRecord::Base
+ def self.description(val=nil); return @desc unless val; @desc = val;end
+
+ def self.connection_approx_count(connection, table_name)
+ case connection.class.name
+ when /Mysql/
+ res = connection.execute("SHOW TABLE STATUS LIKE '#{table_name}'")
+ res = res.fetch_hash
+ return nil unless res
+ a_count = res['Rows'].to_i
+ else
+ $log.warn("Approx count not implemented for #{connection.class.name}")
+ return nil
+ end
+ rescue ActiveRecord::Transactions::TransactionError
+ raise $!
+ end
+
+ def self.approx_count
+ if self.respond_to?(:alois_connection) and conn = self.alois_connection
+ val = connection_approx_count(conn, self.table_name)
+ return val if val and val > 20000
+ end
+
+ return count
+ end
+
+ def self.connection_auto_increment(connection, table_name)
+ case connection.class.name
+ when /Mysql/
+ res = connection.execute("SHOW TABLE STATUS LIKE '#{table_name}'")
+ res.fetch_hash['Auto_increment'].to_i
+ when /SQLite/
+ res = connection.execute("select * from SQLITE_SEQUENCE WHERE name = '#{table_name}'")
+ return(0) if res == []
+ res[0]["seq"].to_i
+ else
+ raise "Autoincrement not implemented for #{connection.class.name}"
+ end
+ rescue ActiveRecord::Transactions::TransactionError
+ raise $!
+ end
+
+ def self.auto_increment
+ if self.respond_to?(:alois_connection) and conn = self.alois_connection
+ return connection_auto_increment(conn, table_name)
+ else
+ raise "Autoincrement not implemented"
+ end
+ end
+
+
+ def self.alois_connection
+ self.connection
+ end
+
+ # Clone, remove bad instancevariables
+ def full_clone
+ res = self.clone
+ res.remove_bad_instance_variables
+ if self.id
+ attrs = res.send :instance_variable_get, '@attributes'
+ attrs[self.class.primary_key] = self[self.class.primary_key]
+ end
+ res.instance_eval("@attributes_cache ||= {}")
+ res
+ end
+
+end
Added: incubator/alois/trunk/rails/lib/awesome_email_fix.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/awesome_email_fix.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/awesome_email_fix.rb (added)
+++ incubator/alois/trunk/rails/lib/awesome_email_fix.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,37 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# with this the css files can be found in the public/stylesheet director
+# multiple css can be defined with "css ['sheet1','sheet2']"
+module ActionMailer
+ module InlineStyles
+ module InstanceMethods
+ def parse_css_doc(file_name)
+ sac = CSS::SAC::Parser.new
+ @css = [@css] if !@css.is_a?(Array)
+ sac.parse(@css.map {|css|
+ css = "#{css}.css" unless css =~ /\.css^/
+ file = File.join(RAILS_ROOT, 'public', 'stylesheets', css)
+ File.read(file)
+ }.join("\n"))
+
+ end
+ end
+
+ def self.included(receiver)
+ receiver.send :include, InstanceMethods
+ end
+ end
+end
+
Added: incubator/alois/trunk/rails/lib/dummy_class_extension.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/dummy_class_extension.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/dummy_class_extension.rb (added)
+++ incubator/alois/trunk/rails/lib/dummy_class_extension.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,25 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# otherwise an exception occurs here
+# when building mails in console
+# /var/local/share/home/fpellanda/logintas/alois/alois-1.0/rails/vendor/rails/actionpack/lib/action_view/base.rb:419:in `template_format'
+class DummyClass
+ def parameters
+ {}
+ end
+ def protocol
+ "dummyprotocol"
+ end
+end
Added: incubator/alois/trunk/rails/lib/fix_activerecrod_base_inspect_bug.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/fix_activerecrod_base_inspect_bug.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/fix_activerecrod_base_inspect_bug.rb (added)
+++ incubator/alois/trunk/rails/lib/fix_activerecrod_base_inspect_bug.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,35 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# this seems not to work
+# essential is the "rescue false"
+
+# /usr/share/alois/www/vendor/rails/activerecord/lib/active_record/base.rb:1153
+module ActiveRecord
+ class Base
+ # Returns a string like 'Post id:integer, title:string, body:text'
+ def self.inspect
+ if self == Base
+ super
+ elsif abstract_class?
+ "#{super}(abstract)"
+ elsif (table_exists? rescue false)
+ attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
+ "#{super}(#{attr_list})"
+ else
+ "#{super}(Table doesn't exist or no connection)"
+ end
+ end
+ end
+end
Added: incubator/alois/trunk/rails/lib/ip_address.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/ip_address.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/ip_address.rb (added)
+++ incubator/alois/trunk/rails/lib/ip_address.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,165 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# code from http://www.prfsa.com/post.rhtml?title=ruby-ip-address-class-part-2
+# example code:
+#
+# ip = IpAddress.new("10.0.0.1")
+# puts "Address: #{ip} (version #{ip.version})"
+# => Address: 10.0.0.1 (version 4)
+#
+# ip = IpAddress.new(156763422792541232312137643, 6)
+# puts "Address: #{ip} (version #{ip.version})"
+# => Address: 0000:0000:0081:abf2:2d8a:a5bf:cf88:b7ab (version 6)
+
+class IpAddress
+ IP_MAX = {4 => (1 << 32) - 1, 6 => (1 << 128) - 1}
+ IP_BITS = {4 => 32, 6 => 128}
+
+ # Takes an Integer or a String representation of an IP Address and coerces it
+ # to a representation of the requested type (:integer / :string). If the
+ # version (4/6) is not specified then it will be guessed with guess_version.
+ def self.coerce(value, to_type, version = nil)
+ raise "unknown type #{to_type.inspect} requested" unless
+ [:integer, :string].include?(to_type)
+ version ||= guess_version(value)
+
+ case value
+ when Integer
+ if to_type == :integer then value
+ elsif version == 4
+ [24, 16, 8, 0].map { |shift| (value >> shift) & 255 }.join(".")
+ else sprintf("%.32x", value).scan(/.{4}/).join(":")
+ end
+ when String
+ if to_type == :string then value
+ elsif version == 4
+ value.split(".").inject(0) { |total, octet| (total << 8) + octet.to_i }
+ else value.delete(":").to_i(16)
+ end
+ end
+ end
+
+ # Takes an Integer or a String and guesses whether it represents an IPv4 or
+ # IPv6 address. For an Integer, IPv4 is assumed unless the value is greater
+ # than IP_MAX[4]. For a String, IPv6 is assumed if it contains at least one
+ # colon (:).
+ def self.guess_version(value)
+ case value
+ when Integer then value > IP_MAX[4] ? 6 : 4
+ when String then value =~ /:/ ? 6 : 4
+ end
+ end
+
+ attr_reader :integer, :string, :version
+
+ # Takes an Integer or a String representation of an IP Address and creates a
+ # new IpAddress object with it. If the version (4/6) is not specified then it
+ # will be guessed with guess_version.
+ def initialize(value, version = nil)
+ @version = version || IpAddress.guess_version(value)
+ @integer = IpAddress.coerce(value, :integer, @version)
+ @string = IpAddress.coerce(value, :string, @version)
+ end
+
+ def to_i; @integer; end
+
+ def to_s; @string; end
+
+ # Adds the specified Integer value to that of the IpAddress and returns a new
+ # IpAddress based on the sum.
+ def +(value)
+ IpAddress.new(@integer + value, @version)
+ end
+
+ # Subtracts the specified Integer value from that of the IpAddress and returns
+ # a new IpAddress based on the difference.
+ def -(value)
+ IpAddress.new(@integer - value, @version)
+ end
+
+ # Returns the next IpAddress after this one.
+ def succ
+ self + 1
+ end
+
+ include Comparable
+
+ # Compares one IpAddress with another based on the Integer representation of
+ # their values.
+ def <=>(other)
+ @integer <=> other.integer
+ end
+
+ # Takes an Integer or a String representation of a network mask and returns
+ # the range of IpAddresses in that network.
+ def mask(value)
+ base_int = @integer & IpAddress.coerce(value, :integer, @version)
+ Range.new(IpAddress.new(base_int, @version),
+ IpAddress.new(base_int + IpAddress.mask_size(value, @version) - 1))
+ end
+
+
+ # Takes an Integer or a String representation of a network mask and returns the
+ # number of addresses it encodes. If the version (4/6) is not specified then it
+ # will be guessed with guess_version.
+ def self.mask_size(value, version = nil)
+ version ||= guess_version(value)
+ (coerce(value, :integer, version) ^ IP_MAX[version]) + 1
+ end
+
+ # Takes an Integer bitcount (bits) and returns an appropriate masking Integer.
+ # For example, a /24 network (in IPv4) corresponds to a mask of 255.255.255.0
+ # or the number 4294967040. If the version (4/6) is not specified then it will
+ # be assumed to be 4 unless bits > 32.
+ def self.mask_from_slash_bits(bits, version = nil)
+ raise "bits > 128" if bits > 128
+ version ||= bits > 32 ? 6 : 4
+
+ max = IP_MAX[version]
+ left_shift = IP_BITS[version] - bits
+ (max << left_shift) & max
+ end
+
+ # Returns the range of IpAddresses in the specified /bits network. Basically a
+ # convenience wrapper around mask.
+ def /(bits)
+ mask(IpAddress.mask_from_slash_bits(bits, @version))
+ end
+
+ def dig
+ open("|/usr/bin/dig -x #{self.to_s} +short") {|f| f.readlines.join("\n") }
+ end
+end
+
+class Integer
+ def to_ip(version = nil)
+ IpAddress.new(self, version)
+ end
+end
+
+class String
+ def to_ip(version = nil)
+ if self =~ /^([\da-f]{4}\:){7}[\da-f]{4}$/ or self =~ /^([\d]{1,3}\.){3}[\d]{1,3}$/
+ return IpAddress.new(self, version)
+ end
+ # if self =~ /^([\da-f]{4}\:){7}[\da-f]{4}$/
+ # todo for ipv6
+ # end
+ if self =~ /^(([\d]{1,3}\.){3}[\d]{1,3})\/(\d{1,2})$/
+ return IpAddress.new($1) / $3.to_i
+ end
+ raise "'#{self}' is not an IP address."
+ end
+end
Added: incubator/alois/trunk/rails/lib/mysql_adapter_extensions.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/mysql_adapter_extensions.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/mysql_adapter_extensions.rb (added)
+++ incubator/alois/trunk/rails/lib/mysql_adapter_extensions.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,72 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module ActiveRecord
+ module ConnectionAdapters
+ class MysqlAdapter
+
+ def auto_increment(table_name)
+ begin
+ res = execute("SHOW TABLE STATUS LIKE '#{table_name}'")
+ res.fetch_hash['Auto_increment'].to_i
+ rescue ActiveRecord::Transactions::TransactionError
+ raise $!
+ end
+ end
+
+ def flush_tables
+ execute("flush tables")
+ end
+
+ def approx_count(table_name)
+ begin
+ res = execute("SHOW TABLE STATUS LIKE '#{table_name}'")
+ res = res.fetch_hash
+ return nil unless res
+ a_count = res['Rows'].to_i
+ rescue ActiveRecord::Transactions::TransactionError
+ raise $!
+ end
+ end
+
+ def current_queries
+ ret = []
+ res = execute("SHOW FULL PROCESSLIST")
+ while col = res.fetch_hash
+ ret.push(col)
+ end
+ return ret
+ end
+
+ def kill(query_id)
+ execute("KILL #{query_id.to_i}")
+ end
+
+ def innodb_status
+ execute("SHOW INNODB STATUS").fetch_hash["Status"]
+ end
+
+ def variables_text
+ hash = {}
+ res = execute("SHOW VARIABLES")
+ while col = res.fetch_hash
+ hash[col["Variable_name"]] = col["Value"]
+ end
+ ml = hash.keys.map {|k| k.length}.max
+
+ hash.keys.sort.map {|key| key.ljust(ml," ") + ": " + hash[key].to_s }.join("\n")
+ end
+ end
+ end
+end
Added: incubator/alois/trunk/rails/lib/tasks/alois.rake
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/lib/tasks/alois.rake?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/lib/tasks/alois.rake (added)
+++ incubator/alois/trunk/rails/lib/tasks/alois.rake Thu Nov 4 18:27:22 2010
@@ -0,0 +1,118 @@
+namespace "alois" do
+
+ desc "Freeze all gems"
+ task :freeze => :environment do
+ Rails.configuration.gems.each {|g|
+ ENV["GEM"] = g.name
+ Rake::Task["gems:freeze"].execute
+ Rake::Task["gems:link"].execute
+ }
+ end
+
+ namespace :db do
+
+ desc "Dumps the schema version."
+ task :dump_schema_version => :environment do
+ DefaultSchemaMigration.dump_schema_version
+ end
+
+ desc "Check schema version."
+ task :print_schema_version => :environment do
+ begin
+ config = Rails::Configuration.new.database_configuration[RAILS_ENV]
+ DefaultSchemaMigration.check_schma_version!(config['database'])
+ print "VERSION: #{DefaultSchemaMigration.version}\n"
+ rescue
+ print "#{$!}\n"
+ case $!.to_s
+ when /mismatch/
+ exit 2
+ when /Unknown database/
+ exit 3
+ when /'mysql.schema_migrations' doesn't exist/
+ exit 4
+ else
+ exit 1
+ end
+ end
+ end
+
+ desc "Creates the database only. (no structure)"
+ task :create => :environment do
+ config = Rails::Configuration.new.database_configuration[RAILS_ENV]
+ connection = connect_mysql_local
+ connection.query("CREATE DATABASE #{config['database']}")
+ end
+
+ desc "Drops the database"
+ task :drop => :environment do
+ config = Rails::Configuration.new.database_configuration[RAILS_ENV]
+ print "Will drop database '#{config['database']}' on '#{config['host']}'."
+ [3,2,1,0].each { |n|
+ print(" #{n} ")
+ STDOUT.flush
+ sleep(1)
+ }
+ print "\n"
+ connection = connect_mysql_local
+ connection.query("DROP DATABASE #{config['database']}")
+ end
+
+ desc "Prints out the current selected default database."
+ task :print_database => :environment do
+ config = Rails::Configuration.new.database_configuration[RAILS_ENV]
+ print "The current connection is: '#{config['database']}' on '#{config['host']}'\n"
+ end
+
+ desc "Removes the default databse - no rails database tasks can be performed anymore."
+ task :undefine_db do
+ File.delete('db') if File.symlink?('db')
+ File.delete('test/fixtures') if File.symlink?('test/fixtures')
+ end
+
+ desc "Defines that the default connection points to the pumpy database."
+ task :set_pumpy_db => :undefine_db do
+ File.symlink('db_pumpy','db')
+ File.symlink('fixtures_pumpy','test/fixtures') if File.directory?('test')
+ end
+
+ desc "Defines that the default connection points to the alois database."
+ task :set_alois_db => :undefine_db do
+ File.symlink('db_alois','db')
+ File.symlink('fixtures_alois','test/fixtures') if File.directory?('test')
+ end
+
+ desc "Compares the current database schema to the 'should be' schema."
+ task :compare_schema => :environment do
+ # dump the actual schema to
+ File.copy("db/expected_schema.rb","db/schema.rb") if File.exist?("db/expected_schema.rb")
+ ENV['SCHEMA'] = "db/current_schema.rb"
+ Rake::Task["db:schema:dump"].invoke
+
+ difference = false
+
+ # compare the
+ open("|/usr/bin/diff -w -u db/schema.rb db/current_schema.rb").each { |line|
+ print line
+ difference = true
+ }
+
+ # remove dumped schema file
+ File.delete("db/current_schema.rb")
+
+ throw "Current db has not the proper schema." if difference
+ end
+
+ desc "Creates the schema dump file from the migration scripts."
+ task :create_schema do
+ ENV['RAILS_ENV'] = 'test'
+ RAILS_ENV = 'test'
+ Rake::Task["environment"].invoke
+ Rake::Task["db:test:purge"].invoke
+ ActiveRecord::Base.connection.reconnect!
+ Rake::Task["db:migrate"].invoke
+ Rake::Task["db:schema:dump"].invoke
+ end
+
+ end
+end
\ No newline at end of file
Added: incubator/alois/trunk/rails/public/404.html
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/404.html?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/public/404.html (added)
+++ incubator/alois/trunk/rails/public/404.html Thu Nov 4 18:27:22 2010
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<body>
+ <h1>File not found</h1>
+ <p>Change this error message for pages not found in public/404.html</p>
+</body>
+</html>
\ No newline at end of file
Added: incubator/alois/trunk/rails/public/500.html
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/500.html?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/public/500.html (added)
+++ incubator/alois/trunk/rails/public/500.html Thu Nov 4 18:27:22 2010
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<body>
+ <h1>Application error</h1>
+ <p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p>
+</body>
+</html>
\ No newline at end of file
Added: incubator/alois/trunk/rails/public/dispatch.cgi
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/dispatch.cgi?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/public/dispatch.cgi (added)
+++ incubator/alois/trunk/rails/public/dispatch.cgi Thu Nov 4 18:27:22 2010
@@ -0,0 +1,10 @@
+#!/usr/bin/ruby1.8
+
+require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
+Dispatcher.dispatch
\ No newline at end of file
Added: incubator/alois/trunk/rails/public/dispatch.fcgi
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/dispatch.fcgi?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/public/dispatch.fcgi (added)
+++ incubator/alois/trunk/rails/public/dispatch.fcgi Thu Nov 4 18:27:22 2010
@@ -0,0 +1,24 @@
+#!/usr/bin/ruby1.8
+#
+# You may specify the path to the FastCGI crash log (a log of unhandled
+# exceptions which forced the FastCGI instance to exit, great for debugging)
+# and the number of requests to process before running garbage collection.
+#
+# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
+# and the GC period is nil (turned off). A reasonable number of requests
+# could range from 10-100 depending on the memory footprint of your app.
+#
+# Example:
+# # Default log path, normal GC behavior.
+# RailsFCGIHandler.process!
+#
+# # Default log path, 50 requests between GC.
+# RailsFCGIHandler.process! nil, 50
+#
+# # Custom log path, normal GC behavior.
+# RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
+#
+require File.dirname(__FILE__) + "/../config/environment"
+require 'fcgi_handler'
+
+RailsFCGIHandler.process!
Added: incubator/alois/trunk/rails/public/dispatch.rb
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/dispatch.rb?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/public/dispatch.rb (added)
+++ incubator/alois/trunk/rails/public/dispatch.rb Thu Nov 4 18:27:22 2010
@@ -0,0 +1,24 @@
+# Copyright 2010 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/usr/bin/ruby1.8
+
+require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
+Dispatcher.dispatch
\ No newline at end of file
Added: incubator/alois/trunk/rails/public/favicon.ico
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/favicon.ico?rev=1031127&view=auto
==============================================================================
(empty)
Added: incubator/alois/trunk/rails/public/help.html
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/help.html?rev=1031127&view=auto
==============================================================================
--- incubator/alois/trunk/rails/public/help.html (added)
+++ incubator/alois/trunk/rails/public/help.html Thu Nov 4 18:27:22 2010
@@ -0,0 +1,404 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Alois Help</title>
+ </head>
+
+ <body>
+ <h1>Alois Help</h1>
+ <h2>Logverarbeitung Ãbersicht</h2>
+ <table>
+ <tr>
+ <th>Logs</th>
+ <th><a href="#database">Pumpy</a></th>
+ <th>Prisma</th>
+ <th><a href="#database">Dobby</a></th>
+ <th><a href="#view">View</a></th>
+ <th><a href="#filter">Filter</a></th>
+ </tr>
+ <tr>
+ <td style="text-align:center"><img src="images/flat-theme/text_block.png"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/inserttable.png"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/tab_right.png"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/matrix.png"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/data.png"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/filter.png"/></td>
+ </tr>
+ <tr>
+ <td>Logs werden per Syslog verschickt.</td>
+ <td>"Raw" gespeicherte Logs in Tabellen auf Insink.</td>
+ <td>Log informationen werden von Pumpy geholt und auseinandergenommen.</td>
+ <td>Aufgesplittete Logmeldungen in Dobby-Datenbank.</td>
+ <td style="border-left: solid 2px black;">Mit SQL generierte Ansichten der Log-Tabellen.</td>
+ <td style="border-right: solid 2px black;">Hilfswerkzeug zum Filtern bestehender Ansichten.</td>
+ </tr>
+ <tr>
+ <th colspan="4"></th>
+ <th colspan="2" style="border-top: solid 2px black;">Daten Sets für Reporting</th>
+ </tr>
+ <tr>
+ <td colspan="4"></td>
+ <td colspan="2" style="text-align:center;"><img src="images/flat-theme/smallcal.png"/></td>
+ </tr>
+ </table>
+ <h2>Reporting Ãbersicht</h2>
+ <table>
+ <tr>
+ <th rowspan="2">Daten Set</th>
+ <th rowspan="2"><a href="#sentinel">Sentinel</a></th>
+ <th><img src="images/flat-theme/tab_right.png" height="20"/></th>
+ <th><a href="#alarm">Alarm</a></th>
+ </tr>
+ <tr>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/bell.png"/></td>
+ </tr>
+ <tr>
+ <td rowspan="2" style="text-align:center"><img src="images/flat-theme/smallcal.png"/></td>
+ <td rowspan="2" style="text-align:center"><img src="images/police_man_ganson.png" width="60" /></td>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td>Von Sentinel generierte Alarme.</td>
+ </tr>
+ <tr>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <th><a href="#report_generate">Report</a></th>
+ </tr>
+ <tr>
+ <td rowspan="2">Zusammengesetzt aus Views + Filter.</td>
+ <td rowspan="2">Periodisch ausgeführter Wächter.</td>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td style="text-align:center"><img src="images/flat-theme/gkrellm.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td>Periodisch von Sentinel generierte Reporte.</td>
+ </tr>
+ </table>
+
+ <h2><a name="view"><img src="images/flat-theme/data.png"/> View</a></h2>
+ <h3>Anzeigen</h3>
+ <p>Gewünschte View auswählen. Aus Menu:</p>
+ <p><img src="images/help/open_view1.jpg"/></p>
+ <p>oder aus <a href="views">View Liste</a>:</p>
+ <p><img src="images/help/open_view2.jpg"/></p>
+ <p>Es erscheint dann eine Tabellenansicht der gewählten View.</p>
+ <p><a href="images/help/survey_table.jpg"><img src="images/help/survey_table.jpg" width="610"/></a></p>
+ <p>Beschreibung der Elemente:</p>
+ <ol>
+ <li>Hier kann durch die Datensätze navigiert werden.</li>
+ <li>Dies ist der Aktuelle aktive Filter. Hier kann die Zeitspanne in Worten eingegeben werden.</li>
+ <li>Wenn mit der Maus über eine Tabellenzelle gefahren wird erscheint dieses Menu. Hier können neue Bedingungen eingefügt werden. Die neuen Bedingungen werden dann bei 2. aufgeführt.<br>
+ <img src="images/add.png"/> Es werden nur noch Zeilen angezeigt welche in dieser Spalte diesen Wert haben.<br>
+ <img src="images/remove.png"/> Es werden alle Zeilen ausgeschlossen welche diesen Wert haben.</li>
+ <li>Wenn mit der Maus über einen Tabellkopf gefahren wird erscheint dieses Menu. <br>
+ <img src="images/up.png"/>,<img src="images/down.png"/> Datensätze auf- oder absteigend sortieren.<br>
+ <img src="images/pie-chart.png"/> <img src="images/bar-chart.png"/> Pie- oder Barchart mit der Verteilung der Werten dieser Spalte.<br>
+ <img src="images/line-chart.png"/> Wenn der Typ der Spalte numerisch ist, oder ein Datum/Zeit enthält, können auch Liniengrafiken dargestellt werden.</li>
+ </ol>
+
+ <h2><a name="filter"><img src="images/flat-theme/filter.png"/> Filter</a></h2>
+ <h3>Erstellen</h3>
+ <p>Entweder den aktuellen Filter aus der View-Azeige speicher:</p>
+ <p><img src="images/help/create_filter1.jpg"/></p>
+ <p>Oder den Menupunkt Reporting -> Filters -> <a href="filters/new">New...</a> wählen:</p>
+ <p><img src="images/help/create_filter2.jpg"/></p>
+ <p>Es erscheint dann folgende Maske:</p>
+ <p><img src="images/help/filter_edit.jpg"/></p>
+ <ol>
+ <li>Hier können Bedingungen entfernt werden.</li>
+ <li>Hier können die Bedingungen bearbeitet werden.</li>
+ <li>Die Beschreibung des Filters</li>
+ <li>Hier kann ein Filter aus in Zip-Form geladen werden. (Wird nur zum hin- und herkopieren zwischen verschiedenen Servern verwendet)</li>
+ </ol>
+
+
+ <h2><a name="chart">Chart</a></h2>
+ <h3>Erstellen</h3>
+ <p>Ãber den Tabellenkopf in der View-Ansicht.</p>
+ <p><img src="images/help/create_chart1.jpg"/></p>
+ <p>Oder über den Knopf "Chart" in der View-Ansicht.</p>
+ <p><img src="images/help/create_chart2.jpg"/></p>
+ <h3>Bearbeiten in View-Ansicht</h3>
+ <p><a href="images/help/modify_chart.jpg"><img width="592" src="images/help/modify_chart.jpg"/></a></p>
+ <ol>
+ <li>Indem auf die Grafik geklickt wird können die Werte weiter eingegrenzt werden. Es werden dann die Tabelleneinträge angezeigt welche das ausgewählte Element repräsentieren.</li>
+ <li>Hier kann angegeben werden aufgrund welcher Spalten die Grafik erstellt werden soll.</li>
+ <li>Hier kann die Sortierung bestimmt werden.</li>
+ <li>Hier kann der Grafiktyp gewählt werden. vlnr: Bar-Chart, Line-Chart, Pie-Chart. Einschränkungen: Line-Charts können nur für X-Achsen mit numerischen Typen oder Datum/Zeit gewählt werden. Die Multichart Spalte kann nicht für Pie Charts gewählt werden.</li>
+ <li>Nachdem änderungen in der Maske vorgenommen wurden, kann die Grafik mit dem Update-Knopf aktualisiert werden.</li>
+ <li>Unter der Grafik erscheint die Erstellungszeit der Grafik. Zum Teil werden die Daten zwischengespeichert. Um die Daten und die Grafik neu zu generieren, den Reload Knopf verwenden.</li>
+ </ol>
+ <h3>Chart Typen Ãbersicht</h3>
+
+ <table border=1>
+ <tr>
+ <th>Typ</th>
+ <th>2 Dim.</th>
+ <th>3 Dim.</th>
+ <th>4 Dim.</th>
+ </tr>
+ <tr>
+ <th>Spalten</th>
+ <td>date</td>
+ <td>date,level</td>
+ <td>date,level,facility</td>
+ </tr>
+ <tr>
+ <td>Pie</td>
+ <td><a href="images/help/pie-chart-1.png"><img width="300" src="images/help/pie-chart-1.png"/></a>
+ <td><a href="images/help/pie-chart-2.png"><img width="300" src="images/help/pie-chart-2.png"/></a>
+ <td>-</a>
+ </tr>
+ <tr>
+ <td>Bar</td>
+ <td><a href="images/help/bar-chart-1.png"><img width="300" src="images/help/bar-chart-1.png"/></a>
+ <td><a href="images/help/bar-chart-2.png"><img width="300" src="images/help/bar-chart-2.png"/></a>
+ <td><a href="images/help/bar-chart-3.png"><img width="300" src="images/help/bar-chart-3.png"/></a>
+ </tr>
+ <tr>
+ <td>Line</td>
+ <td><a href="images/help/line-chart-1.png"><img width="300" src="images/help/line-chart-1.png"/></a>
+ <td><a href="images/help/line-chart-2.png"><img width="300" src="images/help/line-chart-2.png"/></a>
+ <td><a href="images/help/line-chart-3.png"><img width="300" src="images/help/line-chart-3.png"/></a>
+ </tr>
+ <tr>
+ <td>Bar Stacked</td>
+ <td>-</a>
+ <td><a href="images/help/bar-stacked-chart-2.png"><img width="300" src="images/help/bar-stacked-chart-2.png"/></a>
+ <td><a href="images/help/bar-stacked-chart-3.png"><img width="300" src="images/help/bar-stacked-chart-3.png"/></a>
+ </tr>
+ <tr>
+ <td>Line Stacked</td>
+ <td>-</a>
+ <td><a href="images/help/line-stacked-chart-2.png"><img width="300" src="images/help/line-stacked-chart-2.png"/></a>
+ <td><a href="images/help/line-stacked-chart-3.png"><img width="300" src="images/help/line-stacked-chart-3.png"/></a>
+ </tr>
+ </table>
+
+ <p></p>
+ <h2><a name="report_template"><img src="images/flat-theme/edit.png"/> Report Template</a></h2>
+ <h3>Erstellen</h3>
+ <p>Im Menu Reporting -> Report Template -> <a href="report_templates/new">New...</a></p>
+ <p><img src="images/help/new_report_template.jpg"></p>
+ <p>Es erscheint folgende Maske:</p>
+ <p><img src="images/help/new_report_template_maske.jpg"></p>
+ <ol>
+ <li>Hier kann der Report beschrieben werden. Bei Title kann der Name angegeben werden welcher in den Emails als Subject erscheinen soll.</li>
+ <li>Hier wird das eigentliche Template in HTML eingegeben. Die Werte, welche unten am Textfeld angegeben sind, werden beim Report erstellen ersetzt.</li>
+ <li>View hat keinen Einfluss auf die Erstellung eines Reports. Sie wird nur für Plausibilitäts-Prüfungen verwendet und kann auch leer sein. Wenn ein Wert eingefügt ist, dann können nur Charts und Tables ausgewählt werden, welche auf die angegebene View anwendbar sind.</li>
+ <li>Charts und Tables können erst hinzugefügt werden wenn das ReportTemplate einmal gespeichert wurde.</li>
+ </ol>
+
+ <h3>Hinzufügen von Charts und Tables</h3>
+ <p>Bei der Ansicht eines Report-Templates können nun die Charts angegeben werden.</p>
+ <p><img src="images/help/show_report_template.jpg"/></p>
+ <ol>
+ <li>Hier kann ein Chart ausgewählt und hinzugefügt werden.</li>
+ <li>Hier kann eine Voransicht mit Zufällig generierten Daten angezeigt werden.</li>
+ <li>Hier kann eine Voransicht mit Daten aus der oberhalb angegebenen Datasource und Time Range erstellt werden.</li>
+ <li>Hier kann ein Report mit Daten aus der oberhalb angegebenen Datasource und Time Range erstellt werden. Der Report wird dann gespeichert und erscheint unter <a href="reports">Reports</a></li>
+ </ol>
+
+ <h2><a name="report"><img src="images/flat-theme/gkrellm.png"/> Report</a></h2>
+ <h3>Manuell erstellen</h3>
+ <table>
+ <tr>
+ <th>Data Set</th>
+ <th></th>
+ <th>Report Template</th>
+ <th></th>
+ <th>Report</th>
+ </tr>
+
+ <tr>
+ <td style="text-align:center;"><img src="images/flat-theme/smallcal.png"/></td>
+ <td><img src="images/flat-theme/edit_add.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/edit.png"/></td>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/gkrellm.png"/></td>
+ </tr>
+ </table>
+ <p>Das gewünschte ReportTemplate aus Menu auswählen:</p>
+ <p><img src="images/help/select_report_template.jpg"/></p>
+ <p>Es erscheint die Detailansicht des Report-Templates mit folgender Maske:</p>
+ <p><img src="images/help/render_report_template.jpg"/></p>
+ <ol>
+ <li>Die View für das Data-Set auswählen.</li>
+ <li>Die Zeitspanne für das Data-Set eingeben.</li>
+ <li>Knopf "Save as Report" betätigen.</li>
+ </ol>
+ <p>Es sollte dann nach einiger Zeit der Report angezeigt werden. Wenn wieder die Detail-Anzeige des Report-Templates erscheint, Fehlermeldung beachten.</p>
+
+
+
+ <h2><a name="sentinel"><img src="images/police_man_ganson.png" width="60" /> Sentinel</a></h2>
+ <p>Sentinel Editieren</p>
+ <p><img src="images/help/edit_sentinel.jpg"></p>
+ <ol>
+ <li>Hier kann angegeben, was bei der Ausführung dieses Sentinels generiert werden soll. Der Sentinel ist ausgeschaltet wenn hier disabled gewählt wird.</li>
+ <li>Hier wird angegeben in welchen Intervallen dieser Sentinel ausgeführt wird. Bitte konsultieren Sie die Online-Hilfe für mehr Details: <img src="images/help/help_button.jpg"> dann <img src="images/help/cron_interval_help.jpg"></li>
+ <li>Hier kann die Email-Versendung ein oder ausgeschaltet werden. Das Email wird an die in Mail to definerte Adresse versendet.</li>
+ <li>Geben sie hier die "Schwelle" an, ab wann die in 1. ausgewählte Aktion ausgelöst werden soll. D.h. wenn die Anzahl Zeilen den angegebenen Wert übersteigt, wird ein Report und/oder Alarm generiert und ggf. eine Email verschickt.</li>
+ <li>Hier wird die View für das Daten Set definiert.</li>
+ <li>Hier wird die Zeitspanne für die zu selektierenden Daten angegeben.</li>
+ <li>Hier werden die anzuwendenden Filter für die View angegeben. (Kommaseparierte Liste)</li>
+ <li>Hier wird das Alarm-Level angegeben, wenn ein Alarm generiert werden soll.</li>
+ <li>Hier wird das Report-Template angegeben, wenn ein Report generiert werden soll.</li>
+ </ol>
+
+
+ <h3><a name="report_generate">Periodische Reporte generieren</a></h3>
+ <table>
+ <tr>
+ <th>Data Set</th>
+ <th></th>
+ <th>Report Template</th>
+ <th></th>
+ <th>Sentinel</th>
+ <th></th>
+ <th>Report</th>
+ </tr>
+
+ <tr>
+ <td style="text-align:center;"><img src="images/flat-theme/smallcal.png"/></td>
+ <td><img src="images/flat-theme/edit_add.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/edit.png"/></td>
+ <td><img src="images/flat-theme/edit_add.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/police_man_ganson.png" width="60" /></td>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/gkrellm.png"/></td>
+ </tr>
+ </table>
+
+ <p>Damit periodisch ein Report generiert wird, muss ein Sentinel mit folgenden Angaben erstellt werden (vgl. Sentinel Erstellen):</p>
+ <ul>
+ <li>Bei 1: Action = report</li>
+ <li>Bei 2: Cron interval = GEWÃNSCHTES INTERVAL<br>
+ Zum Beispiel einmal täglich um 17:15 Uhr: 15 17 * * *</li>
+ <li>Bei 4: Threshold = GEWÃNSCHTEN WERT<br>
+ Normalerweise 0</li>
+ <li>Bei 5,6,7: Gewünschte View, Time Range und Filter auswählen</li>
+ <li>Bei 9: Das Report Template auswählen</li>
+ </ul>
+
+ <h3><a name="alarm_generate">Alarme generieren</a></h3>
+ <table>
+ <tr>
+ <th>Data Set</th>
+ <th></th>
+ <th>Sentinel</th>
+ <th></th>
+ <th>Alarm</th>
+ </tr>
+
+ <tr>
+ <td style="text-align:center;"><img src="images/flat-theme/smallcal.png"/></td>
+ <td><img src="images/flat-theme/edit_add.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/police_man_ganson.png" width="60" /></td>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/bell.png"/></td>
+ </tr>
+ </table>
+
+ <p>Damit periodisch Alarme generiert wird, muss ein Sentinel mit folgenden Angaben erstellt werden (vgl. Sentinel Erstellen):</p>
+ <ul>
+ <li>Bei 1: Action = alarm</li>
+ <li>Bei 2: Cron interval = GEWÃNSCHTES INTERVAL<br>
+ Zum Beispiel einmal täglich um 17:15 Uhr: 15 17 * * *</li>
+ <li>Bei 4: Threshold = GEWÃNSCHTEN WERT<br>
+ Normalerweise 0</li>
+ <li>Bei 5,6,7: Gewünschte View, Time Range und Filter auswählen</li>
+ <li>Bei 8: Alarm Level auswählen</li>
+ </ul>
+
+ <h3>Alarm mit Report generieren</h3>
+ <table>
+ <tr>
+ <th>Data Set</th>
+ <th></th>
+ <th>Report Template</th>
+ <th></th>
+ <th>Sentinel</th>
+ <th></th>
+ <th>Alarm mit Report</th>
+ </tr>
+
+ <tr>
+ <td style="text-align:center;"><img src="images/flat-theme/smallcal.png"/></td>
+ <td><img src="images/flat-theme/edit_add.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/edit.png"/></td>
+ <td><img src="images/flat-theme/edit_add.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/police_man_ganson.png" width="60" /></td>
+ <td><img src="images/flat-theme/tab_right.png" height="20"/></td>
+ <td style="text-align:center;"><img src="images/flat-theme/bell.png"/><img src="images/flat-theme/gkrellm.png"/></td>
+ </tr>
+ </table>
+
+ <p>Damit periodisch Alarme generiert wird, muss ein Sentinel mit folgenden Angaben erstellt werden (vgl. Sentinel Erstellen):</p>
+ <ul>
+ <li>Bei 1: Action = alarm_and_report</li>
+ <li>Bei 2: Cron interval = GEWÃNSCHTES INTERVAL<br>
+ Zum Beispiel einmal täglich um 17:15 Uhr: 15 17 * * *</li>
+ <li>Bei 4: Threshold = GEWÃNSCHTEN WERT<br>
+ Normalerweise 0</li>
+ <li>Bei 5,6,7: Gewünschte View, Time Range und Filter auswählen</li>
+ <li>Bei 8: Alarm Level auswählen</li>
+ <li>Bei 9: Das Report Template auswählen</li>
+ </ul>
+
+ <h2><a name="alarm">Alarm</a></h2>
+ <h3>Ampel</h3>
+ <p><img src="images/help/ampel.jpg"/></p>
+ <ul>
+ <li>Grün: Es gibt keine zu bearbeitenden Alarme.</li>
+ <li>Orange: Es gibt zu bearbeitende Alarme mit Level error oder warning.</li>
+ <li>Rot: Es gitb zu bearbeitende Alarme mit Level emergency, alert oder critical.</li>
+ </ul>
+ <h3>Alarm Liste</h3>
+ <p>Auf <a href="prisma/overview">Overview</a> Seite oder im Header auf die Ampel klicken.</p>
+ <p><img src="images/help/ampel.jpg"/></p>
+ <p>Es erscheint folgende Seite:</p>
+ <p><img src="images/help/alarm_list.jpg"></p>
+ <ol>
+ <li>Hier sind die aktuellen (zu bearbeitenden) Alarme sortiert nach Level Zeit.</li>
+ <li>Hier sind die zuletzt bestätigten alarme.</li>
+ <li>Hier sind die aktuellen Alarme welche nur zu Informationszwecken eingerichtet wurden. (Alarm Level <= 5: notice)</li>
+ </ol>
+
+ <h3>Details</h3>
+ <p><img src="images/help/alarm_detail.jpg"/></p>
+ <ul>
+ <li>Created at: Wann der Alarm ausgelöst wurde.</li>
+ <li>Data: Die Datensätze welche den Alarm ausgelöst haben in Textform.</li>
+ <li>Report: Falls vorhanden, Link auf zugehörigen Report.</li>
+ <li>Sentinel: Falls vorhanden, Sentinel welcher den Alarm ausgelöst hat. Hier ist auch die Beschreibung des Alarmes und allfällig auszulösende Massnahmen enthalten.</li>
+ </ul>
+ <h3>Acknowlege</h3>
+ <p>In der Alarmliste auf edit klicken:</p>
+ <p><img src="images/help/alarm_edit_click.jpg"></p>
+ <p>Es erscheint folgende Maske:</p>
+ <p><img src="images/help/alarm_edit.jpg"></p>
+ <ul>
+ <li>Kommentar einfügen, warum der Alarm ausgelöst wurde und weshalb der Alarm acknowledged werden kann.</li>
+ <li>Acknowledge checkbox betätigen.</li>
+ <li>Update drücken.</li>
+ </ul>
+
+ <h2><a name="database">Database</a></h2>
+ <h3>Datenbank Details anzeigen</h3>
+ <p><img src="images/help/database_status.jpg"/></p>
+ <h3>Unnötige (zu lange laufende) Queries abbrechen.</h3>
+ <p><img src="images/help/database_detail.jpg"/></p>
+ <ol>
+ <li>Mit "Kill" kann die angezeigte Query abgebrochen werden.</li>
+ </ol>
+
+
+ <hr>
+ <address><a href="mailto:flavio.pellanda@logintas.ch">Flavio Pellanda</a></address>
+<!-- Created: Mon Jul 7 13:56:19 CEST 2008 -->
+<!-- hhmts start -->
+Last modified: Tue Jul 8 01:02:53 CEST 2008
+<!-- hhmts end -->
+ </body>
+</html>
Added: incubator/alois/trunk/rails/public/images/add.png
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/images/add.png?rev=1031127&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/alois/trunk/rails/public/images/add.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/alois/trunk/rails/public/images/bar-chart.png
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/images/bar-chart.png?rev=1031127&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/alois/trunk/rails/public/images/bar-chart.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/alois/trunk/rails/public/images/bookmark_add.png
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/images/bookmark_add.png?rev=1031127&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/alois/trunk/rails/public/images/bookmark_add.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/alois/trunk/rails/public/images/close.png
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/images/close.png?rev=1031127&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/alois/trunk/rails/public/images/close.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/alois/trunk/rails/public/images/delete.png
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/images/delete.png?rev=1031127&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/alois/trunk/rails/public/images/delete.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/alois/trunk/rails/public/images/dot.gif
URL: http://svn.apache.org/viewvc/incubator/alois/trunk/rails/public/images/dot.gif?rev=1031127&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/alois/trunk/rails/public/images/dot.gif
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream