Wednesday, February 1, 2012

MPI - Message Passing Interface

MPI is a message-passing library specification. Interface specifications have been defined for C/C++ and Fortran programs[1]. Provided examples use language C and LAM/MPI. LAM/MPI is a high quality implementation of the Message Passing Interface (MPI) Standard.

Example1: demo.c
#include "mpi.h"
#include <stdio.h>

   int main(int argc,char *argv[])
   {
   int  numtasks, rank, rc; 

   MPI_Init(&argc,&argv);
   
   MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
   printf ("Number of tasks= %d My rank= %d\n", numtasks,rank);  

   MPI_Finalize();
   }
Commands

lamboot
mpicc -o demo demo.c
mpirun -np <number of processes> demo


Result
The next example is the in class assignment we got for the course module 'High performance computing', to design matrix multiplication using MPI.

Matrix size N is divisible by the number of workers (eg. if matrix size is 4 and the number of workers is 4, each worker will get 1 row from matrix A). Master sends each worker equal number of rows from matrix A, full matrix B and an offset to track down the position of rows. Each worker receives the information master sends and completes the matrix multiplication for the relevant rows and creates the relevant rows of result matrix C and sends it along with the offset to track down the position of the rows. Master receives all the rows of the result matrix C from every worker and the result matrix is completed.

Example2
/**********************************************************************
 * MPI-based matrix multiplication AxB=C  
 *********************************************************************/


#include <stdio.h>
#include "mpi.h"
#define N    4        /* number of rows and columns in matrix */

MPI_Status status;

double a[N][N],b[N][N],c[N][N];  
       
main(int argc, char **argv) 
{
  int numtasks,taskid,numworkers,source,dest,rows,offset,i,j,k;

  struct timeval start, stop;
  
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
  MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

  numworkers = numtasks-1;

  /*---------------------------- master ----------------------------*/
  if (taskid == 0) {
    for (i=0; i<N; i++) {
      for (j=0; j<N; j++) {   
 a[i][j]= 1.0;
 b[i][j]= 2.0;
      }
    }

    gettimeofday(&start, 0);

    /* send matrix data to the worker tasks */
    rows = N/numworkers;
    offset = 0;
    
    for (dest=1; dest<=numworkers; dest++) 
    {       
      MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
      MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
      MPI_Send(&a[offset][0], rows*N, MPI_DOUBLE,dest,1, MPI_COMM_WORLD);
      MPI_Send(&b, N*N, MPI_DOUBLE, dest, 1, MPI_COMM_WORLD);
      offset = offset + rows;
    }

    /* wait for results from all worker tasks */
    for (i=1; i<=numworkers; i++) 
    {   
      source = i;
      MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
      MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
      MPI_Recv(&c[offset][0], rows*N, MPI_DOUBLE, source, 2, MPI_COMM_WORLD, &status);
    }

    gettimeofday(&stop, 0);

    printf("Here is the result matrix:\n");
    for (i=0; i<N; i++) { 
      for (j=0; j<N; j++) 
 printf("%6.2f   ", c[i][j]);
      printf ("\n");
    }
  
    fprintf(stdout,"Time = %.6f\n\n",
         (stop.tv_sec+stop.tv_usec*1e-6)-(start.tv_sec+start.tv_usec*1e-6));

  } 

  /*---------------------------- worker----------------------------*/
  if (taskid > 0) {
    source = 0;
    MPI_Recv(&offset, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status);
    MPI_Recv(&rows, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status);
    MPI_Recv(&a, rows*N, MPI_DOUBLE, source, 1, MPI_COMM_WORLD, &status);
    MPI_Recv(&b, N*N, MPI_DOUBLE, source, 1, MPI_COMM_WORLD, &status);
  
    /* Matrix multiplication */
    for (k=0; k<N; k++)
      for (i=0; i<rows; i++) {
        c[i][k] = 0.0;
        for (j=0; j<N; j++)
   c[i][k] = c[i][k] + a[i][j] * b[j][k];
      }


    MPI_Send(&offset, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
    MPI_Send(&rows, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
    MPI_Send(&c, rows*N, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD);
  }  
    
  MPI_Finalize();
} 
Result
As the part 2 of the assignment we were suppose to optimize the code so it will fulfill following requirements,
  • The matrix size should be defined using #define N
  • The type of elements in the matrix should be ``float''
  • The matrices can be square (e.g., NXN) but N may not be exactly divisible by the number of processors
  • Should check the correctness of computations by printing the result matrix. May use #define PRINT to enclose the code segments for printing
  • Should find the speedup of the code (e.g., for N=100, 200, etc.) compared with a sequential matrix multiplication code.
Example 3: Solution
/**********************************************************************
 * MPI-based matrix multiplication AxB=C  
 *********************************************************************/


#include <stdio.h>
#include <sys/time.h>
#include "mpi.h"
#define N    500        /* number of rows and columns in matrix */

MPI_Status status;

float a[N][N],b[N][N],c[N][N];  
       
main(int argc, char **argv) 
{
  int numtasks,taskid,numworkers,source,dest,rows,offset,remain,i,j,k;
  struct timeval start, stop;
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
  MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

  numworkers = numtasks-1;

  /*---------------------------- master ----------------------------*/
  if (taskid == 0) {
    for (i=0; i<N; i++) {
      for (j=0; j<N; j++) {   
        a[i][j]= 1.0;
        b[i][j]= 2.0;
      }
    }

#ifdef PRINT
        /* print matrices */
        printf("Matrix A:\n");           
        for (i=0; i<N; i++){      
           for (j=0; j<N; j++)  
              printf("%.3f\t",a[i][j]); 
           printf("\n");  
        }        

        printf("Matrix B:\n");       
        for (i=0; i<N; i++){  
           for (j=0; j<N; j++)
              printf("%.3f\t",b[i][j]);
           printf("\n");
        }   

#endif

    gettimeofday(&start, 0);

    /* send matrix data to the worker tasks */
    if (N <= numworkers)
    {
 rows = 1;  
    }
    else
    {
      if (N%numworkers!=0) // Not divisible by numworkers
      {        
 rows = N/numworkers+1;
        remain = N%numworkers;
      }
      else
      {
        rows = N/numworkers;  
      }
    }
    offset = 0;
    
    for (dest=1; dest<=numworkers; dest++, remain--) 
    {       
      MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
      MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
      MPI_Send(&a[offset][0], rows*N, MPI_FLOAT,dest,1, MPI_COMM_WORLD);
      MPI_Send(&b, N*N, MPI_FLOAT, dest, 1, MPI_COMM_WORLD);
      offset = offset + rows;
      if(remain==1) rows-=1;
    }

    /* wait for results from all worker tasks */
    for (i=1; i<=numworkers; i++) 
    {   
      source = i;
      MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
      MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
      MPI_Recv(&c[offset][0], rows*N, MPI_FLOAT, source, 2, MPI_COMM_WORLD, &status);
    }

    gettimeofday(&stop, 0);
#ifdef PRINT
    printf("Here is the result matrix:\n");
    for (i=0; i<N; i++) { 
      for (j=0; j<N; j++) 
 printf("%6.2f   ", c[i][j]);
      printf ("\n");
    }
#endif  
    fprintf(stdout,"Time = %.6f\n\n",
         (stop.tv_sec+stop.tv_usec*1e-6)-(start.tv_sec+start.tv_usec*1e-6));

  } 

  /*---------------------------- worker----------------------------*/
  if (taskid > 0) {
    source = 0;
    MPI_Recv(&offset, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status);
    MPI_Recv(&rows, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status);
    MPI_Recv(&a, rows*N, MPI_FLOAT, source, 1, MPI_COMM_WORLD, &status);
    MPI_Recv(&b, N*N, MPI_FLOAT, source, 1, MPI_COMM_WORLD, &status);
  
    /* Matrix multiplication */
    for (k=0; k<N; k++)
      for (i=0; i<rows; i++) {
        c[i][k] = 0.0;
        for (j=0; j<N; j++)
   c[i][k] = c[i][k] + a[i][j] * b[j][k];
      }


    MPI_Send(&offset, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
    MPI_Send(&rows, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
    MPI_Send(&c, rows*N, MPI_FLOAT, 0, 2, MPI_COMM_WORLD);
  }  
    
  MPI_Finalize();
}
 

Example 4: Sequential code
/* Matrix Multiplication */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <assert.h>

#define RANDLIMIT 5 /* Magnitude limit of generated randno.*/
#define N  500   /* Matrix Size */
#define NUMLIMIT 70.0

float a[N][N];
float b[N][N];
float c[N][N];

int main(int argc, char *argv[])
{
    struct timeval start, stop; 
    int i,j,k;

 
    /* generate mxs  */
    for (i=0; i<N; i++)
        for (j=0; j<N; j++) {
            a[i][j] = 1+(int) (NUMLIMIT*rand()/(RAND_MAX+1.0)); 
            /*a[i][j] = 1.0; 
            b[i][j] = 2.0;*/
            b[i][j] = (double) (rand() % RANDLIMIT);
            /*c[i][j] = 0.0;*/
        }

#ifdef PRINT
        /* print matrices */
        printf("Matrix A:\n");           
        for (i=0; i<N; i++){      
           for (j=0; j<N; j++)  
              printf("%.3f\t",a[i][j]); 
           printf("\n");  
        }        

        printf("Matrix B:\n");       
        for (i=0; i<N; i++){  
           for (j=0; j<N; j++)
              printf("%.3f\t",b[i][j]);
           printf("\n");
        }   

        printf("Matrix C:\n");       
        for (i=0; i<N; i++){  
           for (j=0; j<N; j++)
              printf("%.3f\t",c[i][j]);
           printf("\n");
        }   
#endif

    gettimeofday(&start, 0);

    for (i=0; i<N; i++) {
 for (j=0; j<N; j++) {
           c[i][j] = 0.0;
    for (k=0; k<N; k++)
              c[i][j] = c[i][j] + a[i][k]*b[k][j]; /* Working;standard way */
            /*c[j][i] = c[j][i] + a[j][k]*b[k][i];*/ /* Working; Makes C column by col */
        } /* end j loop */
    }

    gettimeofday(&stop, 0);

#ifdef PRINT
    /* print results*/
    printf("Answer c:\n");
    for (i=0; i<N; i++){
        for (j=0; j<N; j++) 
           printf("%.3f\t",c[i][j]);
        printf("\n");
    }
#endif

    fprintf(stdout,"Time = %.6f\n\n",
         (stop.tv_sec+stop.tv_usec*1e-6)-(start.tv_sec+start.tv_usec*1e-6));
    return(0);
}

Result
Examining the results we can clearly see that sequential program takes more time for matrix multiplication than the parallel program when the size of matrix is large.

[1] http://en.wikipedia.org/wiki/Message_Passing_Interface

Friday, July 29, 2011

Using Drupal menu system callback mapping to retrieve JSON or XML data

In my previous post I talked about Drupal menu system callback mapping. Today I'm going to show you how Drupal menu system callback mapping can be used to retrive JSON or XML data.

The way to accomplish the task is to register a path for a menu item with an optional argument. If you pass that optional argument along with the request URL callback function will return JSON data else it will return XML data. In that way callback function will serve both data formats.

Following is a coding example of above mentioned scenario.

<?php
//hook_perm implementation
function example_perm() {
    return array(
        'access city'
    );
}

//hook_menu implementation
function example_menu() {
    $items = array();
 
    //menu item 
    $items['full_city_list'] = array(
        'title' => t('City List JSON'
        ), 'page callback' => 'full_city_list', 'page arguments' => array(
            1
        ), 'access arguments' => array(
            'access city'
        ), 'type' => MENU_CALLBACK);   

    return $items;
}

function full_city_list() {
 $jsonParam=arg(1);//optional argument
 $result = db_query("SELECT  tid,name FROM term_data  WHERE  vid=2 order by name ASC");
 
 if(strcmp($jsonParam, "json") == 0){
    $response = array();
    
    while ($city_data = db_fetch_object($result)) {
        $response[$city_data->name]['city_name'] = $city_data->name;
        $response[$city_data->name]['tid'] = $city_data->tid;
    }

    if (!empty($response)) {
        //encodes city data as json  
        $jsonstrCityList = json_encode($response);
        echo $jsonstrCityList;
    } else {
        return false;
    }
 }elseif(strcmp($jsonParam, "") == 0){
 //sending city data as xml
 $dom = new DOMDocument("1.0");
    $root_elm = $dom->createElement("markers");
    $root = $dom->appendChild($root_elm);    

    while ($city_data = db_fetch_object($result)) {

        $marker_elm = $dom->createElement("marker");
        $marker_node = $root->appendChild($marker_elm);

        $marker_node->setAttribute("name", $city_data->name);
        $marker_node->setAttribute("tid", $city_data->tid);
    }
    header("Content-type: text/xml");
    echo $dom->saveXML();
 }
}
?>



output for http://example.com/full_city_list/json
{"Agalawatta":{"city_name":"Agalawatta","tid":"156"},"Ahungalla":{"city_name":"Ahungalla","tid":"214"},"Akurana":{"city_name":"Akurana","tid":"164"},"Akuressa":{"city_name":"Akuressa","tid":"162"},"Aluthgama":{"city_name":"Aluthgama","tid":"120"},"Ambalangoda":{"city_name":"Ambalangoda","tid":"125"},"Ampara":{"city_name":"Ampara","tid":"211"},"Anuradhapura":{"city_name":"Anuradhapura","tid":"46"},"Arugambay":{"city_name":"Arugambay","tid":"114"},"Avissawella":{"city_name":"Avissawella","tid":"212"},"Badulla":{"city_name":"Badulla","tid":"108"},"Balangoda":{"city_name":"Balangoda","tid":"149"},"Balapitiya":{"city_name":"Balapitiya","tid":"486"},"Bandarawela":{"city_name":"Bandarawela","tid":"197"}}


output for http://example.com/full_city_list
<markers>
<marker name="Agalawatta" tid="156"/>
<marker name="Ahungalla" tid="214"/>
<marker name="Akurana" tid="164"/>
<marker name="Akuressa" tid="162"/>
<marker name="Aluthgama" tid="120"/>
<marker name="Ambalangoda" tid="125"/>
<marker name="Ampara" tid="211"/>
<marker name="Anuradhapura" tid="46"/>
<marker name="Arugambay" tid="114"/>
<marker name="Avissawella" tid="212"/>
<marker name="Badulla" tid="108"/>
<marker name="Balangoda" tid="149"/>
<marker name="Balapitiya" tid="486"/>
<marker name="Bandarawela" tid="197"/>
</markers>

Wednesday, July 20, 2011

Drupal menu system callback mapping

How does drupal menu system callback mapping happen?

When a user makes a request to drupal through a browser, using the request URL drupal menu system decides which callback function to invoke.

what is a callback function?

Callback function in this case is a php function which gets called when a user trying to access a path that has already been registered in a menu item.

In the given example-1 if a browser makes a request using the URL "http://example.com/hello", menu system will look for a menu item which contains that path and invokes the relevant callback function in this case, "hello()".

example-1

<?php

//hook_perm implementation  
function example_perm() {
    return array(
        'access hello'
    );
}

//hook_menu implementation  
function example_menu() {
    $items = array();
    //menu item   
    $items['hello'] = array(
    'title' =--> t('hello'
    ), 'page callback' => 'hello', 'page arguments' => array(
    0
    ), 'access arguments' => array(
    'access hello'
    ), 'type' => MENU_CALLBACK);

    return $items;
}

//callback function  
function hello() {
    echo "hello!";
}
?>  

Output for example-1
hello!

example-2

This example shows how to get city data in json or xml using a request URL.

<?php

//hook_perm implementation
function example_perm() {
    return array(
        'access hello'
    );
}

//hook_menu implementation
function example_menu() {
    $items = array();
    //menu item 
    $items['hello'] = array(
        'title' => t('hello'
        ), 'page callback' => 'hello', 'page arguments' => array(
            0
        ), 'access arguments' => array(
            'access hello'
        ), 'type' => MENU_CALLBACK);

    $items['full_city_list_json'] = array(
        'title' => t('City List JSON'
        ), 'page callback' => 'full_city_list_json', 'page arguments' => array(
            0
        ), 'access arguments' => array(
            'access hello'
        ), 'type' => MENU_CALLBACK);

    $items['full_city_list_xml'] = array(
        'title' => t('City List XML'
        ), 'page callback' => 'full_city_list_xml', 'page arguments' => array(
            0
        ), 'access arguments' => array(
            'access hello'
        ), 'type' => MENU_CALLBACK);

    return $items;
}

function hello() {
    echo "hello!";
}

function full_city_list_json() {
    $response = array();
    $result = db_query("SELECT  tid,name FROM term_data  WHERE  vid=2 order by name ASC");
    while ($city_data = db_fetch_object($result)) {
        $response[$city_data->name]['city_name'] = $city_data->name;
        $response[$city_data->name]['tid'] = $city_data->tid;
    }

    if (!empty($response)) {
        //encodes city data as json  
        $jsonstrCityList = json_encode($response);
        echo $jsonstrCityList;
    } else {
        return false;
    }
}

function full_city_list_xml() {
//sending city data as xml
    $dom = new DOMDocument("1.0");
    $root_elm = $dom->createElement("markers");
    $root = $dom->appendChild($root_elm);

    $result = db_query("SELECT  tid,name FROM term_data  WHERE  vid=2 order by name ASC");

    while ($city_data = db_fetch_object($result)) {

        $marker_elm = $dom->createElement("marker");
        $marker_node = $root->appendChild($marker_elm);

        $marker_node->setAttribute("name", $city_data->name);
        $marker_node->setAttribute("tid", $city_data->tid);
    }
    header("Content-type: text/xml");
    echo $dom->saveXML();
}

?>

Outputs for example-2

for http://example.com/full_city_list_json

{"Agalawatta":{"city_name":"Agalawatta","tid":"156"},"Ahungalla":{"city_name":"Ahungalla","tid":"214"},"Akurana":{"city_name":"Akurana","tid":"164"},"Akuressa":{"city_name":"Akuressa","tid":"162"},"Aluthgama":{"city_name":"Aluthgama","tid":"120"},"Ambalangoda":{"city_name":"Ambalangoda","tid":"125"},"Ampara":{"city_name":"Ampara","tid":"211"},"Anuradhapura":{"city_name":"Anuradhapura","tid":"46"},"Arugambay":{"city_name":"Arugambay","tid":"114"},"Avissawella":{"city_name":"Avissawella","tid":"212"},"Badulla":{"city_name":"Badulla","tid":"108"},"Balangoda":{"city_name":"Balangoda","tid":"149"},"Balapitiya":{"city_name":"Balapitiya","tid":"486"},"Bandarawela":{"city_name":"Bandarawela","tid":"197"}}

for http://example.com/full_city_list_xml

<markers>
<marker name="Agalawatta" tid="156"/>
<marker name="Ahungalla" tid="214"/>
<marker name="Akurana" tid="164"/>
<marker name="Akuressa" tid="162"/>
<marker name="Aluthgama" tid="120"/>
<marker name="Ambalangoda" tid="125"/>
<marker name="Ampara" tid="211"/>
<marker name="Anuradhapura" tid="46"/>
<marker name="Arugambay" tid="114"/>
<marker name="Avissawella" tid="212"/>
<marker name="Badulla" tid="108"/>
<marker name="Balangoda" tid="149"/>
<marker name="Balapitiya" tid="486"/>
<marker name="Bandarawela" tid="197"/>
</markers>


As in example-2 after you grabbed the city data in json or in xml you can parse them and use in any of your applications.

Wednesday, July 6, 2011

Parsing JSON (comes as a response to a web request) using java

JSON (JavaScript Object Notation) as in definition is a light weight data exchange format, a fat free alternative to XML. In today's post I will show you how to parse JSON (comes as a response to a web request) using java.

First download json-lib and add it to your classpath. You'll also have to add following libraries to your classpath

  1. commons-lang.jar
  2. commons-beanutils.jar
  3. commons-collections.jar
  4. commons-logging.jar
  5. ezmorph.jar

What you need next is a request url and it's response should be JSON data. You will see mine in the example code I've provided, if you know how to use firebug the task will be much more simpler. In your browser run that request you'll get the JSON data which I parse, it's lengthy that's why I didn't add it in here. If you get untidy JSON data, format it using jasonlint.

Now let's move on to the example code, it's not hard to understand, simply go through it. Refer comments for clarifications.

java code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

public class JsonParse { 

 public static void main(String[] args) {
  String jsonString = "";

  String city = "London";
  String country = "United+Kingdom";

  //This is the request url  
  String requestUrl = "http://www.bing.com/travel/hotel/hotelReferenceData.do?q="
    + city
    + "%2C+"
    + country
    + "+leave+07%2F08%2F2011+return+07%2F10%2F2011+adults%3A2+rooms%3A1&distanceFrom=22&HotelPriceRange=1%2C2%2C3%2C4&pageOffset=0&pageCount=240&cim=2011-07-08&com=2011-07-10&a=2&c=0&r=1&sortBy=PopularityDesc";
  try {
   URL url = new URL(requestUrl.toString());
   BufferedReader in = new BufferedReader(new InputStreamReader(
     url.openStream()));
   String inputLine;

   while ((inputLine = in.readLine()) != null) {
    //JSON data get stored as a string
    jsonString = inputLine;

   }
   in.close();
   //the way to parse JSON array
   JSONArray json = (JSONArray) JSONSerializer.toJSON(jsonString);
   //getting another JSON string to parse
   String parse1 = json.getString(0);
   
   //the way to parse JSON object
   JSONObject json2 = (JSONObject) JSONSerializer.toJSON(parse1);
   //getting a json array inside JSON object
   JSONArray array1 = json2.getJSONArray("hotels");

   for (int i = 0; i < array1.size(); i++) {
    //getting a JSON object inside JSON array
    JSONObject jhotelrec = array1.getJSONObject(i);    
    System.out.println("Hotel Name= "+jhotelrec.getString("name")+"\n"+"Geo Codes= "+jhotelrec.getJSONArray("geoPoint").getString(0)+","+jhotelrec.getJSONArray("geoPoint").getString(1));
    }

  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 

}


Monday, July 4, 2011

xml parsing with java

In certain situations we java programmers may need to access information in XML documents using a java xml parser. This post will guide you to parse a xml document with java, using DOM parser and Xpath.

xmlfile.xml

Given XML document is quite lengthy, but do not worry because parsing a lengthy XML document is as easy as parsing a short XML document :) .

<a>
<e>
<hotels class="array">
   <e class="object">
    <addressLine1 type="string">4 Rue du Mont-Thabor</addressLine1>
    <amenities class="array">
     <e type="string">24</e>
     <e type="string">31</e>
     <e type="string">42</e>
     <e type="string">52</e>
     <e type="string">9</e>
    </amenities>
    <brandCode type="string">69</brandCode>
    <cachedPrice type="number">935</cachedPrice>
    <city type="string">Paris</city>
    <country type="string">US</country>
    <geoPoint class="array">
     <e type="number">48.86536</e>
     <e type="number">2.329584</e>
    </geoPoint>
    <hotelRateIndicator type="string">2</hotelRateIndicator>
    <id type="number">56263</id>
    <name type="string">Renaissance Paris Vendome Hotel</name>
    <neighborhood type="string" />
    <popularity type="number">837</popularity>
    <starRating type="string">5</starRating>
    <state type="string">IdF</state>
    <telephoneNumbers class="array">
     <e type="string" />
    </telephoneNumbers>
    <thumbnailUrl type="string">http://www.orbitz.com//public/hotelthumbnails/53/97/85397/85397_TBNL_1246535840051.jpg
    </thumbnailUrl>
    <total type="number">250</total>
    <ypid type="string">YN10001x300073304</ypid>
   </e>
   <e class="object">
    <addressLine1 type="string">39 Avenue de Wagram</addressLine1>
    <amenities class="array">
     <e type="string">24</e>
     <e type="string">31</e>
     <e type="string">42</e>
     <e type="string">9</e>
    </amenities>
    <brandCode type="string">69</brandCode>
    <cachedPrice type="number">633</cachedPrice>
    <city type="string">Paris</city>
    <country type="string">US</country>
    <geoPoint class="array">
     <e type="number">48.877106</e>
     <e type="number">2.297451</e>
    </geoPoint>
    <hotelRateIndicator type="string">3</hotelRateIndicator>
    <id type="number">112341</id>
    <name type="string">Renaissance Paris Arc de Triomphe Hotel</name>
    <neighborhood type="string" />
    <popularity type="number">796</popularity>
    <starRating type="string">5</starRating>
    <state type="string">IdF</state>
    <telephoneNumbers class="array">
     <e type="string" />
    </telephoneNumbers>
    <thumbnailUrl type="string">http://www.orbitz.com//public/hotelthumbnails/21/72/302172/302172_TBNL_1246535872514.jpg
    </thumbnailUrl>
    <total type="number">250</total>
    <ypid type="string">YN10001x300073331</ypid>
   </e>
   <e class="object">
    <addressLine1 type="string">35 Rue de Berri</addressLine1>
    <amenities class="array">
     <e type="string">24</e>
     <e type="string">31</e>
     <e type="string">42</e>
     <e type="string">9</e>
    </amenities>
    <brandCode type="string">82</brandCode>
    <cachedPrice type="number">706</cachedPrice>
    <city type="string">Paris</city>
    <country type="string">US</country>
    <geoPoint class="array">
     <e type="number">48.873684</e>
     <e type="number">2.306411</e>
    </geoPoint>
    <hotelRateIndicator type="string">3</hotelRateIndicator>
    <id type="number">108606</id>
    <name type="string">Crowne Plaza Hotel PARIS-CHAMPS ELYSÉES</name>
    <neighborhood type="string" />
    <popularity type="number">796</popularity>
    <starRating type="string">5</starRating>
    <state type="string">IdF</state>
    <telephoneNumbers class="array">
     <e type="string" />
    </telephoneNumbers>
    <thumbnailUrl type="string">http://www.orbitz.com//public/pegsimages/CP/thumb_PARAT.jpg
    </thumbnailUrl>
    <total type="number">250</total>
    <ypid type="string">YN10001x300161106</ypid>
   </e>
   </hotels>
 </e>
</a>   


XMLsample.java

In this code I have used DOM parser and xpath java library to query xml document. Here I am trying to extract hotel information[Hotel name, geo codes, star rating] from xmlfile.xml document

package com.eviac.blog;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class XMLsample {

 public static void main(String[] args) {

  try {
   // loading the xml document into DOM Document object
   DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
   domFactory.setNamespaceAware(true);
   DocumentBuilder builder = domFactory.newDocumentBuilder();
   Document doc = builder.parse("xmlfile.xml");

   // XPath object using XPathFactory
   XPath xpath = XPathFactory.newInstance().newXPath();
   
   // XPath Query, compiling the path using the compile() method
   XPathExpression expr = xpath.compile("//hotels/e/name | //hotels/e/starRating | //hotels/e/geoPoint/e/text()");
   Object result = expr.evaluate(doc, XPathConstants.NODESET);
   NodeList nodes = (NodeList) result;
   for (int i = 0; i < nodes.getLength(); i++) {
    System.out.println(nodes.item(i).getTextContent());
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}


Output
48.86536
2.329584
Renaissance Paris Vendome Hotel
5
48.877106
2.297451
Renaissance Paris Arc de Triomphe Hotel
5
48.873684
2.306411
Crowne Plaza Hotel PARIS-CHAMPS ELYSÉES
5

Monday, June 20, 2011

Working with drupal API

It's been a while since I started working with drupal, without a doubt the best CMS ever. I find working with drupal extremely interesting with all those API functions in hand.

Drupal has convenient ways to handle database work for us, therefore it is advisable to use drupal API as much as possible to get the work done. Moreover updating to a new drupal version from an older version is quite less conflicting if we have followed the drupal API.

recently I got the chance to work with some interesting drupal API functions and thought they might be useful for you as well at some point.

  1. node_load()
  2. Given nid(node id) as the parameter this function loads that node from drupal database. I'm not exaggerating if I say this functions helps us to get full control over any node.dreamy isn't it?

    Example usage 1
    <?php 
    $node=node_load(820);//loads the node with the nid equals to 820 and store it in $node variable
    print_r($node);//prints all the information associated with the node, yikes it's lengthy :P 
    ?>
    
    After loading a particular node it is possible to get almost every information related to it.

    Example usage 2
    <?php 
    echo $node->body;//prints the content of the node
    echo $node->title;//prints the title of the node
    ?>
    
  3. truncate_utf8()
  4. truncate_utf8() function truncates a string to a specified number of characters.

    Example usage
    <?php 
    $node=node_load(820);
    $content=truncate_utf8(strip_tags($node->body),400,true,true);//limits the body content of a node to 400 characters
    ?>
    
  5. l()
  6. Creating a link using html is super easy even for a web development newbie, it is possible to use the same method in drupal development, but if you follow drupal API that's not the best way to create a link. l() function comes to the stage at this moment as the drupal's way to create links.

    Example usage
    <?php 
    print l("click here","node/820");
    ?>
    
    above is exactly identical to following
    <a href="node/820">click here</a>
    
  7. url()
  8. url() generates and internal(eg: node/1) or external url.

    Example usage
    <?php 
    $path="node/820";
    $link=url($path,array('absolute'=>TRUE));
    ?>
    
  9. drupal_get_path_alias()
  10. Given an internal drupal path this function returns the alias set by admin.

    Example usage
    <?php 
    $path="node/820";
    $alias=drupal_get_path_alias($path);
    ?>
    

Tuesday, May 24, 2011

Getting started with drupal module development

Drupal is a very handy CMS, there are tons of modules written to extend the functionalities of drupal. This post will guide you to write a simple drupal module.

There must be at least two files to create a drupal module,

  • module_name.info
  • module_name.module

In this example I will use module_name as "cities". Then my two files would be cities.info and cities.module

Create a folder inside sites/all/modules which has the same name as your module, in this case it's "cities". Inside cities create two files cities.info and cities.module

It is possible to save your module in module folder but it is not recommended as that folder is kinda reserved for drupal core module. Instead of messing with core guys it is advisable to maintain a separate place for custom modules.

cities.info

cities.info file contains all the necessary information for drupal to know about your module. name, description, core are the musts in this file. There are also set of optional info which you can include but here in this example I only use required information only.

; $Id$
name = cities
description = This is a module that display list of cities 
core = 6.x


cities.module

what exactly is a hook?

Here is a good question if you are a newbie to drupal module development. Concept of hook is very important when it comes to drupal module development. Module system in drupal is based on hook, simply it's a php fuction which defines set of parameters and a result type. Hooks allow modules to interact with the drupal core.

In this example module I've used three hooks, hook_help, hook_perm and hook_block.

hook_help : provides help and additional information.
hook_perm : defines permissions for the module.
hook_block: creates a block or set of blocks.

We have to replace hook with our module name when using them.

This example block module cities will display a list of cities pulled out of a database.

<?php
// $Id: cities.module$

/**
 * @file
 * This is a module that display list of cities
 */

/**
 * Implementation of hook_help().
 */
function cities_help($path, $arg) {
  switch ($path) {
    case 'cities':
      return '<p>'. t('<b>help hook. This is a module that display list of cities.</b>') .'</p>';
  }
}

/**
 * Implementation of hook_perm().
 */
function cities_perm() {
  return array('access cites');
}

/**
 * grabbing data from the database
 */

global $arr; 
$arr=array();
global $datas;
$datas="";

$link = mysql_connect ('localhost', 'root', '');
$db = mysql_select_db ('cities', $link);

$sql = "SELECT name FROM city";
$sel = mysql_query($sql);
   
   if (mysql_num_rows($sel) > 0) { 
    $i=0;
    while($row = mysql_fetch_array($sel)) {
          
     $arr[$i]=$row['name'];
     $i=$i+1;
    }
    }
    
 foreach( $arr as $key => $value){
   $datas=$datas." ".$value."<br/>";
  }
  mysql_close();

/**
 * Implementation of hook_block().
 */
function cities_block($op = 'list', $delta = 0, $edit = array()) {
global $datas;
  if ($op == "list") {
    $block = array();
    $block[0]["info"] = t('cities');
    return $block;
  }
  elseif ($op == 'view') {
    $block_content = '<p>This is a block that display list of cities.</p>';
    $block['subject'] = 'City List';
    $block['content'] = $datas;
    return $block;
  }
}


Omitting the closing php tag is a drupal coding standard which prevents runtime issues.


Don't forget to enable your module (administrator-->modules) and pick a suitable place (administrator-->block) for it. Available permissions for this module can be viewed and customized from administrator-->permissions

That's it, now with this basic knowledge in hand it's not far away when you write more complex modules.