Monday, December 05, 2011

Using a Servlet to generate chart images for BIRT

I've been working with Google's chart tools -- specifically their Image Chart tools.  My problem -- I'm using BIRT as my PDF report engine, but I have a web interface.  I want the report to look the same on the web as it does in BIRT (which has it's own excellent native charting library).  I decided the easiest way is to use an
image tag, but I have the potential for copious data, so I have to use a POST instead of a GET.

Google lists an excellent hack using a form and an Iframe as a way to submit the post and that works for me from the web.   It does not work inside of BIRT -- because as far as I know there is no way to submit a form inside of a report.  Instead I decided to use an image tag which runs through a servlet I host.

So now I can write on my web page:

<img src="../chart/chart.png">

and I can include in a dynamic text in my BIRT report

"<img src='http://mywebserver/chart/chart.png'>"  //outside quotes required for BIRT dynamic text

And now I have the same chart in both!  Voila.



import org.apache.commons.io.IOUtils;


import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.*;
import java.net.*;
import java.util.Enumeration;
import java.util.Hashtable;


public class ChartServlet extends HttpServlet {


    public void service(HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("content-type", "image/png");
        try {
            // Construct data
            Hashtable dataHash = new Hashtable();
            dataHash.put("cht", "lc");
            dataHash.put("chtt", "This is my chart");
            dataHash.put("chs", "600x300");
            dataHash.put("chxt", "x");
            dataHash.put("chd", "t:40,20,50,20,100");
            StringBuilder postBuffer = new StringBuilder();
            Enumeration enumeration = dataHash.keys();
            boolean first = true;
            while (enumeration.hasMoreElements()) {
                String key = (String) enumeration.nextElement();
                String value = (String) dataHash.get(key);
                String prefix = "&";
                if (first) {
                    prefix = "";
                    first = false;
                }
                postBuffer.append(getURLPair(prefix, key, value));
            }
            String params = postBuffer.toString();
            // Send data
            URL url = new URL("http://chart.googleapis.com/chart");
              //?chid=a"+String.valueOf(Math.random()).substring(2)); to avoid caching
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
            wr.write(params);
            wr.flush();
          // Get the response and write it directly to your response
            IOUtils.copy(conn.getInputStream(), response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getURLPair(String prefix, String key, String value) {
        try {
            String parameterString = prefix + URLEncoder.encode(key, "UTF-8") + "=" 
            + URLEncoder.encode(value, "UTF-8");
return parameterString;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();  
        }
        return null;
    }

}

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.

Sunday, August 21, 2011

Followup to the Integer toggle code

My good friend Greg mentioned that I should use bitwise operators to perform a toggle, as opposed to my earlier method of using integer math to manipulate the state.  I had not done that because the bitwise implementation is imho not comprehensible by a developer who does not have a CS degree.

As an example it is not at ALL clear to most people that ~2<<10 != ~(2<<10)

Although I suppose that's the point of a method name.



/**
 * A simple way to implement a toggle switch using an integer to store the state
 * and bitwise operators to manipulate the toggle
 * 
 * @author Dan Fishman http://www.fishdan.com
 *
 * This code released to the public under the CreativeCommons 3.0 license by
 * the author on 8/21/2011
 * 
 * http://creativecommons.org/licenses/by/3.0/
 */

public class TestToggle {

  public static int toggleState=0;
  
  public static void main(String argv[]){
      for(int x=0;x<32;x++){
        System.out.println(x+":"+Integer.toBinaryString(toggleState));
        System.out.println(x+":"+Integer.toBinaryString(2 << x));
        toggle(true,x);
        System.out.println("-----------------------");
        System.out.println(x+":"+Integer.toBinaryString(toggleState));
        System.out.println("isOn "+x+" == "+toggleIsOn(x));
        toggle (false,x);
        System.out.println("isOn "+x+" == "+toggleIsOn(x));
        System.out.println("");
      }    
      
      //PAY ATTENTION TO THESE TWO LINES  order of operations can be tricky in bitwise
      // see http://www.uni-bonn.de/~manfear/javaoperators.php
      System.out.println("**"+Integer.toBinaryString(~2<<10));
      System.out.println("**"+Integer.toBinaryString(~(2<<10)));
  }

  /**
  * if onOff==true we set the value at pos == 1 aka on
  * else we set it to 0;
  * @param onOff
  * @param pos
  */
 public static void toggle(boolean onOff, int pos){
     if(onOff==true){
         toggleState |= 2 << pos;
     }
     else{
         toggleState &= ~(2<<pos);
     }
 }
 
 public static boolean toggleIsOn(int x){
     return (toggleState & 2<<x) == 2<<x;
 }        
    
}

Saturday, August 20, 2011

Using an integer to implement a binary toggle switch in Java

We were talking about a way to use an integer to indicate teh state of a series of switches.  e.g. if there were 5 switches and the first 3 were on we would say think of that as 11100, or 28

Not a bad method -- you can very quickly toggle switches on and off by calling

toggle(boolean on,int position)

and you can quickly check it the toggle at a position is on by calling

toggleIsOn(int position);

The code snippet is below, comments welcome.  you have to declare toggleState yourself of course...;



public int toggleState=0;

       /**
     * if onOff==true we set the value at pos == 1 aka on
     * else we set it to 0;
     * @param onOff
     * @param pos
     */
    public void toggle(boolean onOff, int pos){
        if(toggleState==null){
            toggleState=0;
        }
        if(onOff==true){
            if(toggleIsOn(pos)){
                //do nothing, already on
            }
            else{
                //we want it on, and it is currently off
                toggleState+=2^pos;
            }
        }
        else{
            if(toggleIsOn(pos)){
                //It's on, and we want it off
                toggleState-=2^pos;
            }
            else{
                //it's off and we want it off -- do nothing
            }            
        }
    }
    
    public boolean toggleIsOn(int pos){
        if(toggleState==null || toggleState < (2^pos)) return false;
        //divide toggle state
        int multiple=toggleState/(2^pos);
                //if the switch is on, multiple will be an odd number, otherwise it will be even.
        return multiple%2==1;
    }

Friday, July 08, 2011

Fishman's law

The corporation was initially a construct of government to enable efficiency in business.  Now government is a construct of corporations to enable efficiency in business.

Sunday, May 29, 2011

Thoughts about power

The problem with power is that... well... it's POWERFUL.  It can be used for both good and ill, but regardless of it's usage, the more power there is behind a command, the harder it is for the individual to resist.  That's pretty close to the definition of power.

It's become clear that throughout history there are some people who are driven to accumulate power.  It's also become clear that there is no correlation between a person's ability to accumulate power and his/her desire to use it to benefit mankind.  Certainly there have been examples of power being used very wisely, and for the benefit of man -- but there more than numerous regrettable examples.

The Libertarian viewpoint is that the only way to prevent these tragedies is to prevent the accumulation of power.  We believe that all power originates from the people as individuals, thus governments and corporations only acquire power by a lessening of the power of the people.  If government's sole purpose becomes to protect civil rights and to preserve the power of the people above government and corporations, government immediately becomes more honest.  If government no longer has the ability to help corporations make laws against the people, corporations will have no reason to try to influence government.

I think that man has a natural inclination to accumulate power, and power positively reinforces the people who accumulate it.  It seems to me (and most libertarians) that the only way to stop people from accumulating power is to cut off the source of the power.  That can only be done by refusing to allow people to yield their rights, and refusing to allow governments or corporations to curtail the rights of the people.

Will this hinder our ability to do great good deeds and achieve mighty milestones?  Somewhat.  People can still come together in free associations.  Polio was defeated by just such an organization when the March of Dimes rallied the country and found a cure.

Will it also stop the misappropriation of power?  I believe so.  And that is a benefit that is worthwhile.

Wednesday, May 18, 2011

Concatenating BIRT reports via servlet

I've been using BIRT a bit and in our project we generate alot of PDFs and have found BIRT to be the beswt product there is for that.  One thing BIRT does NOT allow you to do is to combine reports.  The below is my Servlet based solution for that which correctly renumbers the pages  It borrows the concatenation from Abhi on Java.

I also bought IText in Action  A must have for the serious developer of PDF's in Java.

I've stripped out the company specific part of this code, but have not tried compiling this version.  it should be pretty damn close to what you need though.  Ask if you have any questions.

Of course this code is completely free to use and is released under the Academic Free License

**********************************




import javax.servlet.*;
import javax.servlet.http.*;

import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;


import java.io.*;
import java.net.URL;
import java.util.*;

public class PDFServlet extends HttpServlet {

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       response.setContentType("application/pdf"); // Code 1
       List<InputStream> pdfs = new ArrayList<InputStream>();
       String prefix=http://myBirtServer?__report=report/";
       String params="&oid="+request.getParameter("oid")+"&__format=pdf";
       String [] URLs={
                "myReport1.rptdesign",
                "myReport2.rptdesign",
                "myReport3.rptdesign",
                "myReport4.rptdesign",
                "myReport5.rptdesign",
                "myReport6.rptdesign"
       };
       for(int x=0;x<URLs.length;x++){
         URL u1=new URL(prefix+URLs[x]+params);
         System.out.println(u1);  
         InputStream in=u1.openStream();
         pdfs.add(in);
       }
       concatPDFs(pdfs,response.getOutputStream(),true);

    }

/**
* Method written by Abhi
*/ 
public static void concatPDFs(List<InputStream> streamOfPDFFiles, OutputStream outputStream, boolean paginate, String watermark) {
        Document document = new Document(PageSize.LETTER.rotate());
        try {
            List<InputStream> pdfs = streamOfPDFFiles;
            List<PdfReader> readers = new ArrayList<PdfReader>();
            int totalPages = 0;
            Iterator<InputStream> iteratorPDFs = pdfs.iterator();
            int x = 0;
            // Create Readers for the pdfs.
            while (iteratorPDFs.hasNext()) {
                System.out.println((++x) + " through the loop1");
                try {
                    InputStream pdf = iteratorPDFs.next();
                    PdfReader pdfReader = new PdfReader(pdf);
                    readers.add(pdfReader);
                    totalPages += pdfReader.getNumberOfPages();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // Create a writer for the outputstream
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
            if (!STR.isEmpty(watermark)) {
                writer.setPageEvent(new Watermark(watermark));
            }
            document.open();
            BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
            // data

            PdfImportedPage page;
            int currentPageNumber = 0;
            int pageOfCurrentReaderPDF = 0;
            Iterator<PdfReader> iteratorPDFReader = readers.iterator();

            // Loop through the PDF files and add to the output.
            while (iteratorPDFReader.hasNext()) {
                PdfReader pdfReader = iteratorPDFReader.next();

                // Create a new page in the target for each source page.
                while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
                    document.newPage();
                    pageOfCurrentReaderPDF++;
                    currentPageNumber++;
                    page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
                    cb.addTemplate(page, 0, 0);

                    // Code for pagination.
                    if (paginate) {
                        cb.beginText();
                        cb.setFontAndSize(bf, 9);
                        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + " of " + totalPages, 520, 5, 0);
                        cb.endText();
                    }
                }
                pageOfCurrentReaderPDF = 0;
            }
            outputStream.flush();
            document.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document.isOpen())
                document.close();
            try {
                if (outputStream != null)
                    outputStream.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * Inner class to add a watermark to every page.
     */
    static class Watermark extends PdfPageEventHelper {

        private String watermark;

        public Watermark(String wm) {
            watermark = wm;
        }

        Font FONT = new Font(Font.FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));

        public void onEndPage(PdfWriter writer, Document document) {
            ColumnText.showTextAligned(writer.getDirectContentUnder(),
                    Element.ALIGN_CENTER, new Phrase(watermark, FONT),
                    421, 297.5f, writer.getPageNumber() % 2 == 1 ? 45 : -45);
        }
    }

    

}

Tuesday, April 12, 2011

Calvin R. Hill for City of Worcester School Committee

My co ex-MGH Institute of Health Professions colleague and generally good guy Calvin R. Hill is running for School Committee in Worcester MA. Calvin and I worked together for a year, and that was enough for me to form a pretty good impression of the guy.

Calvin's a person who get's things done, but he doesn't act before he understands the situation.  In my role as Software Architect at the IHP, I worked with Calvin (who was the Chief Diversity Officer) on adding diversity questions to the course and faculty evaluations the students completed every semester.  It would have been easy to just hand me a few cookie cutter questions and have them thrown into the evaluations, but Calvin made me wait a few days, while he researched and consulted with some faculty and students so that the questions that ended up in the evaluation were specific about the IHP and the medical profession.  After that I had several more opportunities to work with Calvin, and though we were natural enemies (he being a Kansas fan, and I being from UT), I grew to appreciate the careful and complete way he solved problems.

I'm not sure of Calvin's political affiliation, but for me, all politics are local.  I think we're better off having people who ethical, straight shooting and diligent in public office regardless of party.  Worcester NEEDS people who will be thorough.  I am happy to say that Calvin fits that bill, and it's unusual to see a man of his abilities looking to serve the public in such an important, but thankless roll.

I would like to encourage my readers who live in Worcester to become acquainted with Calvin's campaign, and if you don't live in Worcester, but know someone who does, please send them here.  You can learn more about Calvin and his campaign at the campaign's facebook page.

Tuesday, March 22, 2011

Some thoughts on the world oil market, and the lesson of the last mile

Oil goes to $200/barrel -- an almost certainty in the next 20 years. You don't think that cost constraint will affect the nations that can't afford oil like we can? Maybe they'll be the ones who engineer their way out of this.

This may end up being a cell phone type situation. Because the US was SO wealthy, we were able to wire phones to every house in the US. This wealth made us a late adopter of cell phone technology, because who needed a cell phone when there was a phone in every home and a phone on every corner.

As a result other countries pioneered cell phone technology. We've happily adopted it because it is obviously superior -- but the market brought cell phones to the US when they were finally superior to what the US, with it's enormous wealth could already afford.

The same thing will happen with green technology. China is already the world's leading producer of Solar technology. In fact, our consuming all the oil makes them NEED green technology. When they get it good and ready, we'll happily pay for their pioneering efforts, and move over to a green energy industry that is mature and capable.

We have the wealth to not have to stumble through the green energy growing pains. Other countries don't so they'll HAVE to.

Thursday, March 10, 2011

Ubuntu on Asus 900a

I just installed ubuntu on my asus 900a. If your flash drive isn't being recognized, try a different usb slot. Third time was the charm for me.  The front right slot was the one that worked.  Others have reported left only works for install, so try them ALL

Sent from my Samsung Captivate(tm) on AT&T