8. Use Cases

This section contains sample applications or use cases written for the SIETS system. Each use case is in a separate section and contains a short description and source code.

This section contains the following use cases:

8.1. Use Case in C: Importing Text Files

This application is implemented in the C programming language.

The application reads files from the file system and imports them to the SIETS storage. The application is receiving file names as command line arguments.

It also detects whether the file is a text file or a binary file by counting whitespaces in them: if a file contains relatively less whitespaces, it is considered to be a binary file, and if a file contains relatively more whitespaces, it is considered to be a text file.

/**

* This application is implemented in the C programming language.

*

* The application reads files from the file system and imports them to the

* SIETS storage via HTTP POST interface using libcurl.

*

* The application receives file names as command line arguments.

*

* It also detects whether the file is a text file or a binary file by counting

* whitespaces in it: if a file contains relatively less whitespaces, it is

* considered to be a binary file, and if a file contains relatively more

* whitespaces, it is considered to be a text file.

*/

/* include standard headers */

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <ctype.h>

/* libcurl */

#include <curl/curl.h>

/* connection parameters */

char *url = "http://195.244.157.173/cgi-bin/siets/api.cgi";

char *storage = "ljur";

char *user = "guest";

char *passwd = "guest";

char *encoding = "US-ASCII";

char *post_fmt = "storage=%s&command=insert&user=%s&password=%s&id=%s&title=%s&rate=%d&text=%s&encoding=%s";

#define REQUIRED_WHITESPACE_FRACTION 0.12

typedef struct { int len, used; char *buf; } curl_reply;

size_t read_reply(void *buffer, size_t size, size_t nmemb, void *userp)

{

int new_len;

curl_reply *r = (curl_reply *) userp;

for (new_len = r->len; new_len < r->used + size * nmemb + 1; new_len *= 2);

if (new_len > r->len) r->buf = realloc(r->buf, new_len);

memcpy(r->buf + r->used, buffer, size * nmemb);

r->len = new_len;

r->used += size * nmemb;

r->buf[r->used] = '\0';

return size * nmemb;

}

int main(int argc, char *argv[])

{

CURL *curl_handle;

char *storage_esc, *user_esc, *passwd_esc, *title_esc, *text_esc, *encoding_esc;

curl_reply reply;

char *err_buf[CURL_ERROR_SIZE];

int i;

if (argc == 1) {

printf("Usage: [-r url] [-s storage] [-u user] [-p password] [-e encoding] files\n");

return 0;

}

/* read options */

for (i = 1; i < argc; i++) {

if (argv[i][0] == '-') {

if (i + 1 >= argc) break; /* no option value */

switch(argv[i][1]) {

case 'r':

url = argv[i+1];

break;

case 's':

storage = argv[i+1];

break;

case 'u':

user = argv[i+1];

break;

case 'p':

passwd = argv[i+1];

break;

case 'e':

encoding = argv[i+1];

break;

default:

printf("Unknown option: %s\n", argv[i]);

break;

}

i++;

}

}

/* initialization */

curl_global_init(CURL_GLOBAL_ALL);

curl_handle = curl_easy_init();

curl_easy_setopt(curl_handle, CURLOPT_URL, url);

curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, read_reply);

curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &reply);

curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, err_buf);

storage_esc = curl_escape(storage, 0);

user_esc = curl_escape(user, 0);

passwd_esc = curl_escape(passwd, 0);

encoding_esc = curl_escape(encoding, 0);

/* names of files to be imported are passed as arguments

* process each of them */

for (i = 1; i < argc; i++) {

FILE *f;

struct stat st;

int k, spaces;

char *buf, *post_data;

/* check if argument is option */

if (argv[i][0] == '-') {

if (i + 1 >= argc) break; /* no option value */

i++;

continue;

}

printf("Reading file: '%s'\n", argv[i]);

/* open file */

f = fopen(argv[i], "r");

if (!f) {

fprintf(stderr, "Couldn't open file '%s'\n", argv[i]);

continue;

}

/* retrieve file information */

if (fstat(fileno(f), &st) < 0) {

fprintf(stderr, "Filesystem error retrieving info on '%s'\n", argv[i]);

fclose(f);

continue;

}

if (!S_ISREG(st.st_mode)) {

fprintf(stderr, "File '%s' is not regular file\n", argv[i]);

fclose(f);

continue;

}

printf("\tSize: %d bytes\n", st.st_size);

/* read all of it into memory */

/* note: this sample program asumes all of file fits into memory

* so if you need to work with larger files figure out something else */

buf = (char *) malloc(st.st_size + 1);

if (!buf) {

fprintf(stderr, "Memory allocation failed\n");

}

k = fread(buf, 1, st.st_size, f);

fclose(f);

if (k < st.st_size) {

fprintf(stderr, "Error reading file\n");

free(buf);

continue;

}

buf[k] = '\0';

/* see if it is text file

* estimate that by counting white space:

* natural language text in contrary to binary data

* must contain significant portion of whitespace */

spaces = 0;

for (k = 0; k < st.st_size; k++) {

if (isspace(buf[k])) spaces++;

}

if (spaces < st.st_size * REQUIRED_WHITESPACE_FRACTION) {

printf("\tBinary file: ignored\n");

free(buf);

continue;

}

/* execute SIETS insert command through HTTP POST interface */

title_esc = curl_escape(argv[i], 0);

text_esc = curl_escape(buf, k);

post_data = malloc(strlen(storage_esc) + strlen(user_esc) + strlen(passwd_esc) + strlen(post_fmt) + 2 * strlen(title_esc) + 20 + strlen(text_esc) + strlen(encoding_esc));

sprintf(post_data, post_fmt, storage_esc, user_esc, passwd_esc, title_esc, title_esc, 100, text_esc, encoding_esc);

curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, post_data);

reply.buf = malloc(reply.len = 1);

reply.used = 0;

if (curl_easy_perform(curl_handle) != CURLE_OK) {

fprintf(stderr, "Error connecting to SIETS server: %s\n", err_buf);

} else if (strstr(reply.buf, "<siets:error>")) { /* simplified error check */

*((char *) strstr(reply.buf, "</text>")) = '\0';

fprintf(stderr, "Error returned from SIETS server: %s\n", strstr(reply.buf, "<text>") + 6);

} else {

*((char *) strstr(reply.buf, "</docid>")) = '\0';

printf("Document inserted with id %s\n", strstr(reply.buf, "<docid>") + 7);

}

/* cleanup */

free(buf);

free(reply.buf);

free(title_esc);

free(text_esc);

free(post_data);

}

/* final cleanup */

free(storage_esc);

free(user_esc);

free(passwd_esc);

free(encoding_esc);

curl_easy_cleanup(curl_handle);

curl_global_cleanup();

return 0;

}

8.2. Use Case in Perl: Importing Text Files

This application is implemented in the Perl programming language.

The application reads files from the file system and imports them to the SIETS storage. The application is receiving file names as command line arguments.

#

# This application is implemented in the Perl programming language.

#

# The application reads files from the file system and imports them to the

# SIETS storage through HTTP POST interface using libcurl.

#

# The application receives file names as command line arguments.

#

# It also detects whether the file is a text file or a binary file by counting

# whitespaces in it: if a file contains relatively less whitespaces, it is

# considered to be a binary file, and if a file contains relatively more

# whitespaces, it is considered to be a text file.

#

use HTTP::Request::Common;

use LWP::UserAgent;

use File::stat;

# connection parameters

$url = "http://127.0.0.1/cgi-bin/siets/api.cgi";

$storage = "test";

$user = "guest";

$passwd = "guest";

$encoding = "US-ASCII";

$REQUIRED_WHITESPACE_FRACTION = 0.12;

if (@ARGV == 0) {

print "Usage: [-r url] [-s storage] [-u user] [-p password] [-e encoding] files\n";

exit;

}

# read options

for ($i = 0; $i < @ARGV; $i++) {

if (substr($ARGV[$i], 0, 1) eq '-') {

if ($i + 1 >= @ARGV) { last; } # no option value

$opt = substr($ARGV[$i], 1, 1);

$val = $ARGV[$i + 1];

if ($opt eq 'r') {

$url = $val;

} elsif ($opt eq 's') {

$storage = $val;

} elsif ($opt eq 'u') {

$user = $val;

} elsif ($opt eq 'p') {

$passwd = $val;

} elsif ($opt eq 'e') {

$encoding = $val;

} else {

print "Unknown option: ", $ARGV[$i], "\n";

}

$i++;

}

}

$ua = LWP::UserAgent->new;

# names of files to be imported are passed as arguments

# process each of them

for ($i = 0; $i < @ARGV; $i++) {

# check if argument is option

if (substr($ARGV[$i], 0, 1) eq '-') {

if ($i + 1 >= @ARGV) { last; } # no option value

$i++;

next;

}

print "Reading file: '", $fn = $ARGV[$i], "'\n";

# open file

if (open(f, $fn)) {

# retrieve file information

if ($st = stat(*f)) {

if (($st->mode & S_IFMT) == S_IFREG) {

print "\tSize: ", $st->size, " bytes\n";

# read all of it into memory

# note: this sample program asumes all of file fits into memory

# so if you need to work with larger files figure out something else

if (sysread(*f, $buf, $st->size) == $st->size) {

# see if it is text file

# estimate that by counting whitespace in it:

# natural language text in contrary to binary data

# must contain significant portion of whitespace

$nspaces = $buf =~ s/(\s)/$1/g;

if ($nspaces >= $st->size * $REQUIRED_WHITESPACE_FRACTION) {

# execute SIETS insert command through HTTP POST interface */

$response = $ua->request(POST $url, [

storage => $storage,

command => 'insert',

user => $user,

password => $passwd,

id => $fn,

title => $fn,

rate => 100,

text => $buf,

encoding => $encoding

]);

if ($response->is_success && $response->content) {

if ($response->content !~ /<siets:error>/) { # simplified error check

$response->content =~ /<docid>([^<]*)<\/docid>/;

print "Document inserted: docid = $1\n";

} else {

$response->content =~ /<code>([^<]*)<\/code>/;

print STDERR "Error returned from SIETS server: $1 - ";

$response->content =~ /<text>([^<]*)<\/text>/;

print STDERR "$1\n";

}

} else {

print STDERR "Error connecting to SIETS server: ", $response->code, ' - ', $response->message, "\n";

}

} else {

print "\tBinary file: ignored\n";

}

} else {

print STDERR "Error reading file\n";

}

} else {

print STDERR "File '$fn' is not a regular file\n";

}

} else {

print STDERR "Filesystem error retrieving info on '$fn'\n";

}

close(f);

} else {

print STDERR "Could not open file '$fn'\n";

}

}

8.3. Use Case in PHP: Searching SIETS Storage and Returning Results in HTML

This application is implemented in the PHP programming language.

The application searches the SIETS storage and returns the results in HTML.

<?

//

// This application is implemented in the PHP programming language.

//

// The application searches the SIETS storage using HTTP API and returns the

// results in HTML.

//

$SIETS_SERVER = "http://195.244.157.173/cgi-bin/siets/api.cgi";

$SIETS_STORAGE = "ljur";

$SIETS_USER = "guest";

$SIETS_PASSWD = "guest";

//search query

$query = $_GET["q"];

//current position in results

$curr_position = $_GET["p"];

//data encoding

$encoding = "UTF-8";

//send http header with correct encoding

send_headers($encoding);

//max results on page

$result_on_page = 10;

if (empty($curr_position) || $curr_position < 0) {

$curr_position = 0;

}

//max page from one domain to show

$max_page_from_domain = 2;

$xml_text = file_get_contents($SIETS_SERVER . "?storage=$SIETS_STORAGE&command=search&user=" . urlencode($SIETS_USER) . "&password=" . urlencode($SIETS_PASSWD) . "&query=" . urlencode($query) . "&docs=$result_on_page&offset=$curr_position&from_domain=$max_page_from_domain&encoding=UTF-8");

if ($xml_text == "") {

die("Siets_search error!");

}

//initialize xml to array object

$xml2a = new XMLToArray();

//parse xml

$root_node = $xml2a->parse($xml_text);

//pop root node from array

$siets_reply = array_shift($root_node["_ELEMENTS"]);

//array for storing data from search results

//like total time spent, hits, and so on

$spec_data = array();

// examining SIETS reply elements

foreach ($siets_reply["_ELEMENTS"] as $siets_reply_el) {

if ($siets_reply_el["_NAME"] == "seconds") {

$spec_data[$siets_reply_el["_NAME"]] = $siets_reply_el["_DATA"];

}

// examining SIETS content elements folder

foreach ($siets_reply_el["_ELEMENTS"] as $siets_content) {

$spec_data[$siets_content["_NAME"]] = $siets_content["_DATA"];

$last_domain = '';

foreach($siets_content["_ELEMENTS"] as $results) {

$tit = "";

$others = "";

//parse each document tag from the result set

foreach($results["_ELEMENTS"] as $documents) {

switch ($documents["_NAME"]) {

case "title" :

$tit_array = explode(":_:_:", $documents["_DATA"]);

$tit .= '<b>'.$tit_array[0].'</b>';

break;

case "link" :

$others .= '<br/><font size="-1"> Link: '.$documents["_DATA"].'</font>';

break;

case "domain" :

if ($last_domain == $documents["_DATA"])

$blockquote = TRUE;

else

$blockquote = FALSE;

$others .= '<br/><font size="-1"> Domain: <i>'.$documents["_DATA"].'</i></font>';

$last_domain = $documents["_DATA"];

break;

case "rate" :

break;

case "info" :

break;

case "text" :

if (!empty($documents["_DATA"]))

$others .= '<br/><font size="-1"> Snippet: <i>'.$documents["_DATA"].'</i></font>';

break;

}

}

//tab domains

if ($blockquote)

$output .= '<blockquote>'.$tit.$others.'</blockquote>';

else

$output .= '<br>'.$tit.$others.'<br>';

}

}

}

if ($spec_data["hits"] == 0) {

$output = "Your search <b>$query</b> did not match any documents!";

} else {

//page listing

$from = $curr_position + 1;

$to = $curr_position + strval($spec_data["found"]);

$list_begin_pos=0;

$list_end_pos=$curr_position+($result_on_page*10);

$page_list .= "<font size=\"-1\">";

$p = 1;

if($curr_position > ($result_on_page * 10)){

$list_begin_pos=$curr_position-($result_on_page*10);

$p=intval($list_begin_pos/$result_on_page)+1;

}

if ($curr_position > 0) {

$page_list .= " <a href=\"sietsu.php?p=". ($curr_position - $result_on_page) ."&q=".urlencode(stripslashes($query))."\">&lt;&lt;Previous</a> &nbsp;&nbsp;";

}

$more_tag = $spec_data["more"];

if ($more_tag[0] == '=') {

$more = substr($more_tag,1);

} else {

$more = substr($more_tag,1) + 1;

}

for ($i = $list_begin_pos; $i - ($curr_position + $more) < $result_on_page && $i < $list_end_pos; $i+= $result_on_page) {

if($i>=1000) break;

if ($i != $curr_position) {

$page_list .= "<a href=\"sietsu.php?p=$i&q=".urlencode(stripslashes($query)).(!empty($dir)?"&dir=$dir":"")."\">$p</a> ";

} else {

$page_list .= "<b>$p </b>";

}

$p++;

}

if (($result_on_page+$curr_position)-($curr_position+$more) < 10 && $curr_position + $result_on_page < 1000) {

$page_list .= "&nbsp;&nbsp; <a href=\"sietsu.php?p=".($curr_position + $result_on_page)."&q=".urlencode(stripslashes($query))."\">Next&gt;&gt;</a>";

}

$page_list .= "</font>";

//end of page listing

}

//echo output to client

echo '

<html>

<head>

<style><!--

body,td,p,a{font-family:arial,sans-serif;}

.servkat{color:003399; text-decoration:none}

.homepage{color:003399; text-decoration:none; font-size:10px;}

//-->

</style>

</head>

<body>

<table>

<tr bgcolor=\"#cccc66\">

<td><font size=\"-1\">&nbsp; Searched for: <b>'.$query.'</b> Results: <b>'.$from.'</b> - <b>'.$to.'</b> from <b>'.$spec_data["hits"].'</b> Search lasted <b>'.$spec_data["seconds"].'</b> seconds </font>&nbsp;</td>

<tr>

</table>

'.$output.'<br>

'.$page_list.'

</body>

</html>';

//#########################################################

class XMLToArray

{

//----------------------------------------------------------------------

// private variables

var $parser;

var $node_stack = array();

//----------------------------------------------------------------------

// PUBLIC

// If a string is passed in, parse it right away.

function XMLToArray($xmlstring="")

{

if ($xmlstring) return($this->parse($xmlstring));

return(true);

}

//----------------------------------------------------------------------

// PUBLIC

// Parse a text string containing valid XML into a multidimensional array

// located at root node.

function parse($xmlstring="")

{

// set up a new XML parser to do all the work for us

$this->parser = xml_parser_create();

xml_set_object($this->parser, $this);

xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);

xml_set_element_handler($this->parser, "startElement", "endElement");

xml_set_character_data_handler($this->parser, "characterData");

// Build a Root node and initialize the node_stack

$this->node_stack = array();

$this->startElement(null, "root", array());

// parse the data and free the parser...

xml_parse($this->parser, $xmlstring);

xml_parser_free($this->parser);

// recover the root node from the node stack

$rnode = array_pop($this->node_stack);

// return the root node

return($rnode);

}

//----------------------------------------------------------------------

// PROTECTED

// Start a new Element. This is done by pushing the new element onto the stack

// and reseting its properties.

function startElement($parser, $name, $attrs)

{

// create a new node

$node = array();

$node["_NAME"] = $name;

foreach ($attrs as $key => $value) {

$node[$key] = $value;

}

$node["_DATA"] = "";

$node["_ELEMENTS"] = array();

// add the new node to the end of the node stack

array_push($this->node_stack, $node);

}

//----------------------------------------------------------------------

// PROTECTED

// End an element. This is done by popping the last element from the

// stack and adding it to the previous element on the stack.

function endElement($parser, $name)

{

// pop this element off the node stack

$node = array_pop($this->node_stack);

$node["_DATA"] = trim($node["_DATA"]);

// and add it an element of the last node in the stack...

$lastnode = count($this->node_stack);

array_push($this->node_stack[$lastnode-1]["_ELEMENTS"], $node);

}

//----------------------------------------------------------------------

// PROTECTED

//Collect the data onto the end of the current chars.

function characterData($parser, $data)

{

// add this data to the last node in the stack...

$lastnode = count($this->node_stack);

$this->node_stack[$lastnode-1]["_DATA"] .= $data;

}

//----------------------------------------------------------------------

}

//#########################################################

//## END OF CLASS

//#########################################################

//sends Content-type header to client browser

function send_headers($encoding)

{

Header("Content-type: text/html;charset=$encoding");

}

?>

8.4. Use Case in ASP: Searching SIETS Storage and Returning Results in HTML

This application is implemented in the ASP programming language.

The application searches the SIETS storage and returns the results in HTML.

<%

'

' This application is implemented in the VBScript programming language.

'

' The application searches the SIETS storage using HTTP API and returns the

' results in HTML.

'

%>

<html>

<head>

<title>Search</title>

<style>

#results div.header { margin-bottom: 35px; }

#results div.result { padding-left: 15px; }

#results p.title { margin-bottom: 3px; }

#results p.snip { margin: 0px; }

#results p.link { margin-top: 3px; font-size: 0.9em; color: gray; }

#results p.error { color: red; }

#results .pagelist { padding-top: 20px; }

#results .pagelist p { display: inline; }

#results .pagelist ul { margin: 0px; padding: 0px; display: inline; }

#results .pagelist li { display: inline; }

</style>

</head>

<body>

<div id="results">

<%

nDocs = 10 'results per page

nPages = 10 'pages listed

Offset = Int(Request.QueryString("page")) * nDocs 'pages are numbered from 0, displayed from 1

sQuery = Request.QueryString("query")

Set Http = Server.CreateObject("MSXML2.ServerXMLHTTP")

Http.Open "POST", "http://127.0.0.1/cgi-bin/siets/api.cgi", False

Http.Send "storage=test&command=search&docs=" & nDocs & "&offset=" & Offset & "&relevance=yes&query=" & Server.URLEncode(sQuery)

if Http.Status = 200 and not Http.ResponseXML is Nothing then

Set Dom = Http.ResponseXML

Dom.SetProperty "SelectionNamespaces", "xmlns:s='www.siets.net'"

Set Content = Dom.SelectSingleNode("s:reply/s:content")

if not Content is Nothing then

'command executed ok

n = Int(Content.SelectSingleNode("hits").Text)

%><div class="header"><p>Found <b><% if n > 0 then Response.Write n else Response.Write "no"

%></b> document<% if n <> 1 then Response.Write "s"

if not Content.SelectSingleNode("real_query") is Nothing then sRealQuery = Content.SelectSingleNode("real_query").Text else sRealQuery = ""

%> matching &quot;<%= Server.HTMLEncode(sRealQuery)

%>&quot; (<b><%= Dom.SelectSingleNode("s:reply/s:seconds").Text %></b> seconds)</p></div><%= vbCrLf %><%

if n > 0 then

'something has been found

for each Result in Content.SelectNodes("results/document")

%><div class="result"><%

sTitle = Result.SelectSingleNode("title").Text

p = InStr(sTitle, ":_:_:")

if p > 0 then sTitle = Left(sTitle, p - 1)

%><p class="title"><a href="<%= Server.HTMLEncode(Result.SelectSingleNode("id").Text) %>"><%= Server.HTMLEncode(sTitle) %></a></p><%

%><p class="snip"><%= Replace(Result.SelectSingleNode("text").Text, "#", " ") %></p><%

%><p class="link"><%= Server.HTMLEncode(Result.SelectSingleNode("id").Text) %></p><%

%></div><%= vbCrLf %><%

next

'page listing

iFrom = Int(Content.SelectSingleNode("from").Text)

nMore = Int(Mid(Content.SelectSingleNode("more").Text, 2))

nSure = Int((nMore + iFrom + 2 * nDocs - 1) / nDocs)

if iFrom > 0 or nMore > 0 then

%><div class="pagelist"><%= vbCrLf %><p>Result pages:<%= vbCrLf %><%

iPage = Int(iFrom / nDocs)

i = Int((iPage - 1) / (nPages - 2)) * (nPages - 2)

if i < 0 then i = 0

%><ul><%= vbCrLf %><%

sLink = "<a href=""search.asp?query=" & Server.URLEncode(sQuery) & "&page="

if iPage > 0 then

%><li><%= sLink & (iPage - 1) %>">&lt;&lt;&lt; Previous</a></li><%= vbCrLf %><%

end if

j = i

do while j < i + nPages and j < nSure

%><li><%

if j = iPage then

%><b><%= j + 1 %></b><%

else

%><%= sLink & j %>"><%= j + 1 %></a><%

end if

%></li><%= vbCrLf %><%

j = j + 1

loop

if nMore > 0 then

%><li><%= sLink & (iPage + 1) %>">Next &gt;&gt;&gt;</a></li><%= vbCrLf %><%

end if

%></ul><%= vbCrLf %></p><%= vbCrLf %></div><%= vbCrLf %><%

end if

end if

else

'error

Set Content = Dom.SelectSingleNode("s:reply/s:error")

%><p class="error">Error <%= Content.SelectSingleNode("code").Text %>: <%= Server.HTMLEncode(Content.SelectSingleNode("text").Text) %></p><%= vbCrLf %><%

end if

else

%><p class="error">Search failed!</p><%= vbCrLf %><%

end if

%> </div>

</body>

</html>

8.5. Use Case in Java: Searching SIETS Storage from applet

This application is implemented as Java applet.

The application searches the SIETS storage and displays results.

8.5.1. SietsJApi.java

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;

import java.util.Random;

public class SietsJApi extends JApplet implements ActionListener {

private JPanel contentPane;

private JPanel Buttons = new JPanel();

private JPanel Results = new JPanel();

private JPanel Properties = new JPanel();

private JPanel MainPan = new JPanel();

private JLabel HostLabel = new JLabel("Host:");

private JLabel StorageLabel = new JLabel("Storage:");

private JLabel QueryLabel = new JLabel("Query:");

private JButton SearchButt = new JButton("Search");

private JButton ClearButt = new JButton("Clear");

private JTextField QueryField = new JTextField(10);

private JTextField HostField = new JTextField("http://",20);

private JTextField StorageField = new JTextField(10);

private JTextArea ResultArea = new JTextArea();

public void init() {

//ContentPane Layout

contentPane = (JPanel) this.getContentPane();

contentPane.setLayout(new BorderLayout());

//Main pane

MainPan.setLayout(new GridBagLayout());

//Properties pane

Properties.setLayout(new GridBagLayout());

Properties.setBorder(BorderFactory.createTitledBorder("Properties"));

//Buttons pane

Buttons.setLayout(new GridLayout(1,2,5,0));

//Results pane

GridLayout gridLayout1 = new GridLayout();

gridLayout1.setVgap(0);

gridLayout1.setHgap(0);

gridLayout1.setColumns(1);

gridLayout1.setRows(10);

Results.setLayout(new BorderLayout());

Results.setBorder(BorderFactory.createTitledBorder("Results"));

//Add Main pane to contentPane

contentPane.add(MainPan,BorderLayout.NORTH);

//Properties pan to Main pane

MainPan.add(Properties,new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0

,GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 1, 1), 0, 0));

//Add controls to Properties Pane

Properties.add(HostLabel,new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0

,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1), 1, 0));

Properties.add(HostField,new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0

,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 1, 1), 0, 0));

Properties.add(StorageLabel, new GridBagConstraints(2, 1, 1, 1, 1.0, 1.0

,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1), 1, 0));

Properties.add(StorageField, new GridBagConstraints(3, 1, 1, 1, 1.0, 1.0

,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 1, 1), 0, 0));

Properties.add(QueryLabel, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0

,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1), 0, 0));

Properties.add(QueryField, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0

,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 1, 1), 0, 0));

//Add Buttons to Main Pan

MainPan.add(Buttons,new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0

,GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(1, 1, 1, 1), 20, 0));

Buttons.add(SearchButt,null);

Buttons.add(ClearButt,null);

MainPan.add(Results,new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0

,GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(1, 1, 0, 1), 0,0));

Results.add(ResultArea);

SearchButt.addActionListener(this);

ClearButt.addActionListener(this);

}

//Action listener search and clear buttons

public void actionPerformed(ActionEvent e) {

if (e.getSource() == ClearButt) {

QueryField.setText("");

} else if (e.getSource() == SearchButt) {

String cgiUrl = new String(HostField.getText());

SietsExch sietsReq;

//Create Siets XML query

SietsMess sietsXMLQuery = new SietsMess("search",StorageField.getText(),"guest","guest",QueryField.getText());

//Do data exchange with Siets server

sietsReq = new SietsExch(cgiUrl,sietsXMLQuery.getMess());

sietsReq.doQuery();

String temp = sietsReq.getResponse();

//Parse out XML results

SietsXMLParser sietsXMLResp = new SietsXMLParser(temp.trim());

String[][] resArray = new String[10][];

resArray = sietsXMLResp.parse();

String outp = "";

//Format output

for (int i = 0; i < sietsXMLResp.getResultLength(); i++) {

System.out.println("URL["+i+"]: "+resArray[i][1]+" Title: "+resArray[i][0]);

JLabel u;

outp += "Title: "+resArray[i][0]+"\n";

outp += "Link: "+resArray[i][1]+"\n\n";

}

ResultArea.setText(new String(outp));

}

}

}

8.5.2. SietsMess.java

import java.util.Calendar;

public class SietsMess {

private String iComm;

private String iData;

private String iUser;

private String iPass;

private String iStorage;

private String message;

/** Creates new SietsMess */

public SietsMess(String command,String storage,String user, String passwd) {

iComm = command;

iData = null;

iUser = user;

iPass = passwd;

iStorage = storage;

message = ComposeMess();

}

public SietsMess(String command,String storage, String user, String passwd,String data) {

iComm = command;

iData = data;

iUser = user;

iPass = passwd;

iStorage = storage;

message = ComposeMess();

}

public String getMess() {

return message;

}

private String ComposeMess() {

String mess = "";

long current = System.currentTimeMillis();

mess = "<siets:request xmlns:siets=\"www.siets.net\">";

mess += "<siets:timestamp>"+Calendar.YEAR+"/"+Calendar.MONTH+"/"+Calendar.DAY_OF_MONTH+" "+Calendar.HOUR+":"+Calendar.MINUTE+":"+Calendar.SECOND+"</siets:timestamp>";

mess += "<siets:command>"+iComm+"</siets:command>";

mess += "<siets:requestid>"+current+"</siets:requestid>";

mess += "<siets:storage>"+iStorage+"</siets:storage>";

mess += "<siets:reply_charset>UTF-8</siets:reply_charset>";

mess += "<siets:user>"+iUser+"</siets:user>";

mess += "<siets:password>"+iPass+"</siets:password>";

mess += "<siets:application>JavaApi</siets:application>";

mess += "<siets:content>";

if (iComm == "search") {

mess += "<query>"+iData+"</query>";

mess += "<docs>10</docs>";

}

mess += "</siets:content>";

mess += "</siets:request>";

return mess;

}

}

8.5.3. SietsExch.java

import java.io.*;

import java.net.*;

import javax.swing.*;

public class SietsExch {

private String iHost;

private String iData;

private String query;

private String response;

private String iFname;

/** Creates new siets_network */

public SietsExch(String Host, String data) {

iData = data;

URL aURL=null;

try {

aURL = new URL(Host);

} catch (MalformedURLException e) {

System.out.println("Malformed URL");

}

iHost = aURL.getHost();

iFname = aURL.getFile();

}

public int doQuery() {

try {

Socket socket = new Socket(iHost,80);

BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

socket.setSoTimeout(60000); // set 1 minute timeout

String header = "POST "+iFname+" HTTP/1.0\r\n";

header += "Host: "+iHost+"\r\n";

header += "User-Agent: SIETS Client Sample\r\n";

header += "Content-Length: " + iData.getBytes("UTF-8").length+"\r\n\r\n";

wr.write(header);

wr.write(iData);

wr.flush();

response = read_socket(socket);

wr.close();

socket.close();

} catch (UnknownHostException e) {

System.err.println("Exception: Unknown host " + iHost + "!");

System.exit(1);

} catch (IOException e) {

System.err.println("Exception: I/O error during connection!");

System.exit(1);

}

return 1;

}

public String getResponse() {

return response;

}

private String read_socket(Socket fsocket){

String reply="";

try{

BufferedReader rd= new BufferedReader(new InputStreamReader(fsocket.getInputStream()));

StringBuffer tempresp = new StringBuffer();

int ch=0;

while (true){

ch = rd.read();

if (ch < 0)

break;

else

tempresp.append((char)ch);

}

reply = new String(tempresp);

reply = reply.substring(reply.indexOf("\r\n\r\n"));

} catch (InterruptedIOException e){

return "<siets:reply>\n<siets:error>\n<text>"+e.getMessage()+"</text><source>API</source><level>failed</level>\n</siets:error>\n</siets:reply>";

} catch (UnknownHostException e){

return "<siets:reply>\n<siets:error>\n<text>"+e.getMessage()+"</text><source>API</source><level>failed</level>\n</siets:error>\n</siets:reply>";

} catch (IOException e){

return "<siets:reply>\n<siets:error>\n<text>"+e.getMessage()+"</text><source>API</source><level>failed</level>\n</siets:error>\n</siets:reply>";

} catch (NullPointerException e){

return "<siets:reply>\n<siets:error>\n<text>"+e.getMessage()+"</text><source>API</source><level>failed</level>\n</siets:error>\n</siets:reply>";

}

return reply;

}

}

8.5.4. SietsXMLParser.java

import java.io.*;

import javax.xml.parsers.*;

import org.w3c.dom.*;

import org.xml.sax.*;

public class SietsXMLParser {

private String iData;

private String[][] Resultset = new String[10][2];

private int ResCount = 0;

/** Creates new SietsXMLParser */

public SietsXMLParser(String data) {

iData = data;

}

public String[][] parse() {

try {

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

Document doc = builder.parse(new InputSource(new StringReader(iData)));

NodeList nodes = doc.getElementsByTagName("document");

ResCount = nodes.getLength();

for (int i = 0; i < nodes.getLength(); i++) {

Element element = (Element) nodes.item(i);

NodeList title = element.getElementsByTagName("title");

Element line = (Element) title.item(0);

Resultset[i][0] = new String(getCharacterDataFromElement(line));

NodeList url = element.getElementsByTagName("id");

line = (Element) url.item(0);

Resultset[i][1] = new String(getCharacterDataFromElement(line));

}

} catch (Exception e) {

e.printStackTrace();

return null;

}

return Resultset;

}

public int getResultLength() {

return ResCount;

}

public String getCharacterDataFromElement(Element e) {

Node child = e.getFirstChild();

if (child instanceof CharacterData) {

CharacterData cd = (CharacterData) child;

return cd.getData();

}

return "?";

}

}

8.6. Use Case in FoxPro I: Updating SIETS Storage from Database Table Data

This application is implemented in the Microsoft Visual FoxPro programming language.

The application reads data from a database table and imports them to the SIETS storage.

Note: In this use case, a simple function called XTAGC for searching XML tags is used instead of the fetch functions.

PROCEDURE siets_update

*!* variables for the SIETS session initiation parameters

LOCAL lcAplication,lcServer,lnPort,lcStorage,lcUsr,lcPasswd;

lcAplication=[siets_update] && application name

lcServer=[111.111.111.111] && IP adress of the server

lnPort=1111 && port number

lcStorage=[mani-dati] && storage name

lcUsr=[my-user] && user name

lcPasswd=[my-passwd] && user password

lcTimeout=60 && timeout

LOCAL lcReplyXml,lcError,lcSession

*!* initialization of SIETS API library

SIETS_DECLARE()

*!* initialization of SIETS parameters

lcSession = SIETS_OPEN_SESSION(lcServer,lnPort,lcStorage,lcUser,lcPasswd,lcTimeout)

*!* if the error ocured, returns

IF lcSession < 0

? [Error opening session]

RETURN .F.

ENDIF

*!* variables to which the indexing data will set

LOCAL lcText, lcTitle, lcLink, lnRateing, lcCharset

*!* encoding of data to be updated

lcCharset=[windows-1257]

*!* opens a table with data that are to be stored to the SIETS storage

USE dati ALIAS dati

SELECT dati

SET ORDER TO id

GO TOP

SCAN

lcLink=ALLTRIM(dati.id) && id

lcTitle=ALLTRIM(dati.title) && title

lcText=ALLTRIM(dati.text) && textual information

*!* rate is calculated by the updating date: the newer the document, the greater the rate

lnRateing=dati.date-DATE(1970,1,1)

*!* replaces the & and “ characters with the XML entities

lcTitle=STRTRAN(lcTitle,[&],[&amp;]);

lcTitle=STRTRAN(lcTitle,["],[&quot;]);

lcText=STRTRAN(lcText,[&],[&amp;]);

lcText=STRTRAN(lcText,["],[&quot;]);

*!* sends data to the SIETS storage

lcReplyXml=SIETSXML_UPDATE(lcSession,lcLink,lcTitle,lnRateing,lcText,lcCharset)

*!* parses the error message from the XML reply

lcError=XTAGC([siets_error],lcReplyXml,1);

IF NOT EMPTY(lcError)

IF XTAGC([level],lcError,1)==[failed]

*!* if the error level is failed, the system work can be continued,

*!* because the error refers only to the input data

? [The update was not executed successfully for a document with id: ]+lcLink

? [Error message: ]+XTAGC([text],lcError,1)

ELSE

*!* if the error level is error or fatal, the function returns

? [The update is interrupted for a document with id: ]+lcLink

? [Error message: ]+XTAGC([text],lcError,1)

RETURN .F.

ENDIF

ENDIF

ENDSCAN

*!* when the update is complete, the index command is executed

lcReplyXml=SIETS_INDEX(lcSession)

*!* parses the error message from the XML reply

lcError=XTAGC([siets_error],lcReplyXml,1);

*!* if the error message is not empty, returns

IF NOT EMPTY(lcError)

? [Error:] + lcError

RETURN .F.

ENDIF

SIETS_CLOSE_SESSION(lcSession)

RETURN .T.

*!* additional function XTAGC, which is used in this use case for a easier XML parsing

*!* the XTAGC function returns a substring from a given string, which contains data

*!* between the tags <m.tag>...</m.tag>

PARAMETER m.t, m.s, m.o

PRIVATE m.i,m.j

STORE .F. TO m.XTAGC_ISTAG, m.ISTAG

IF EMPTY(m.s)

RETURN ""

ENDIF

IF EMPTY(m.o)

IF !EMPTY(m.t)

m.i=ATC("<"+m.t+">",m.s)

m.j=ATC("</"+m.t+">",m.s)

ELSE

m.i=ATC(">",m.s)

m.j=ATC("</",m.s)

ENDIF

ELSE

IF !EMPTY(m.t)

m.i=ATC("<"+m.t+">",m.s,m.o)

m.j=ATC("</"+m.t+">",m.s,m.o)

ELSE

m.i=ATC(">",m.s)

m.j=ATC("</",m.s)

ENDIF

ENDIF

IF m.i=0 OR m.j=0

RETURN ""

ENDIF

STORE .T. TO m.XTAGC_ISTAG, m.ISTAG

m.i=m.i+LEN(m.t)+IIF(!EMPTY(m.t),2,1)

IF SUBSTR(m.s,m.i,2)==CHR(13)+CHR(10)

m.i=m.i+2

ENDIF

IF SUBSTR(m.s,m.j-2,2)==CHR(13)+CHR(10)

m.j=m.j-2

ENDIF

IF m.j>m.i

RETURN SUBSTR(m.s,m.i,m.j-m.i)

ENDIF

RETURN ""

8.7. Use Case in FoxPro II: Searching SIETS Storage and Returning Results to Cursor

This application is implemented in the Microsoft Visual FoxPro programming language.

The application searches the SIETS storage and returns the results to the cursor.

Note: In this use case, a simple function called XTAGC for searching XML tags is used instead of the fetch functions.

PROCEDURE siets_search

*!* parameters:

*!* tcCursorName – name of the cursor to which the search results will be returned

*!* tnMaxDoc – number of results to be returned

*!* tnOffset – intend from the beginning of the result set

*!* tcOrder – mechanism by which results are to be sorted: by relevance (.T.), or rate (.F.)

*!* tcErrorMsg – returns error message

*!* tcQuery – search query

LPARAMETERS tcCursorName, tnMaxDoc, tnOffset, tlOrder, tcErrorMsg, tcQuery

*!* variables for the SIETS session initiation parameters

LOCAL lcAplication,lcServer,lnPort,lcStorage,lcUsr,lcPasswd;

lcAplication=[siets_update] && application name

lcServer=[111.111.111.111] && IP address of the server

lnPort=1111 && port number

lcStorage=[mani-dati] && storage name

lcUsr=[my-user] && user name

lcPasswd=[my-passwd] && user password

lcTimeout=60 && timeout

LOCAL lcReplyXml,lcError,lcSession

*!* initialization of SIETS API library

SIETS_DECLARE()

*!* initialization of SIETS parameters

lcSession = SIETS_OPEN_SESSION(lcServer,lnPort,lcStorage,lcUser,lcPasswd,lcTimeout)

*!* if the error ocured, returns

IF lcSession < 0

? [Error opening session]

RETURN .F.

ENDIF

*!* creation of the cursor where to return the search results

CREATE CURSOR (tcCursorName) (link C(10) , Title C(254), date D, Highlight M)

LOCAL lcReplyXml,lcError,lnFound,lcCaseSensitive,lcRelevance,lcFromDomain

lcRelevance=.F.

lcFromDomain=0

lcCaseSensitive=.F.

*!* performs FTS with the given search parameters

lcReplyXml=SIETSXML_SEARCH(lcSession,tcQuery,tnMaxTrans,tnOffset,lcRelevance,lcFromDomain,lcCaseSensitive,[windows-1257]) && Perform search

*!* parses an error message from the XML reply

lcError=XTAGC([siets_error],lcReplyXml,1)

*!* if the error message is not empty, returns

IF NOT EMPTY(lcError)

tcErrorMsg=XTAGC([text],lcError,1) && returns the error message

RETURN .F.

ENDIF

*!* parses the number of results from the XML reply

lnFound=VAL(XTAGC("found",lcReplyXml,1))

LOCAL lnI,lclink,lnRate,lcTitle,lcText,ldDate

*!* parses the search results from the XML reply and saves them in the cursor

FOR lnI=1 TO lnFound STEP 1

lcLink=XTAGC([link],lcReplyXml,lnI) && id

lnRate=VAL(XTAGC([rate],lcReplyXml,lnI)) && rate

lcTitle=XTAGC([title],lcReplyXml,lnI) && title

lcText=XTAGC([text],lcReplyXml,lnI) && snippet of text with search terms

ldDate=DATE(1970,1,1)+lnRate && rate converted back to the date format

*!* saving data to the cursot

INSERT INTO (tcCursorName) (link,Title,date,Highlight) VALUES (lcLink,lcTitle,ldDate,lcText)

ENDFOR

SIETS_CLOSE_SESSION(lcSession)

RETURN .T.

*!* additional function XTAGC, which is used in this use case for a easier XML parsing

*!* the XTAGC function returns a substring from a given string, which contains data

*!* between the tags <m.tag>...</m.tag>

PARAMETER m.t, m.s, m.o

PRIVATE m.i,m.j

STORE .F. TO m.XTAGC_ISTAG, m.ISTAG

IF EMPTY(m.s)

RETURN ""

ENDIF

IF EMPTY(m.o)

IF !EMPTY(m.t)

m.i=ATC("<"+m.t+">",m.s)

m.j=ATC("</"+m.t+">",m.s)

ELSE

m.i=ATC(">",m.s)

m.j=ATC("</",m.s)

ENDIF

ELSE

IF !EMPTY(m.t)

m.i=ATC("<"+m.t+">",m.s,m.o)

m.j=ATC("</"+m.t+">",m.s,m.o)

ELSE

m.i=ATC(">",m.s)

m.j=ATC("</",m.s)

ENDIF

ENDIF

IF m.i=0 OR m.j=0

RETURN ""

ENDIF

STORE .T. TO m.XTAGC_ISTAG, m.ISTAG

m.i=m.i+LEN(m.t)+IIF(!EMPTY(m.t),2,1)

IF SUBSTR(m.s,m.i,2)==CHR(13)+CHR(10)

m.i=m.i+2

ENDIF

IF SUBSTR(m.s,m.j-2,2)==CHR(13)+CHR(10)

m.j=m.j-2

ENDIF

IF m.j>m.i

RETURN SUBSTR(m.s,m.i,m.j-m.i)

ENDIF

RETURN ""


PreviousTopNext