Thursday, September 29, 2011

Extjs Applet Integration

         In recent years most of the systems are getting upgraded with the new User Interface and Extjs is once of the most widely used technology for the rich look and feel. In most of the domain mostly in DMS (Document Management System) upload and download functionality is provided. To achieve the performance most of the system uses applets for upload and downloading the content from the systems. One of the major problem with applet is they used different tags (applet, object and embed) for different browsers. I came across such issues so decided to write a blog on it.

To achieve the mention problem i am writing few steps that will be helpful to you guys.

1) Create a main.html page and in the same directory put the ext-base.js and ext-all.js files.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" src="ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>
<script type="text/javascript" src="applet.js"></script>
<script>
Ext.onReady(function(){
my.appletRenderer.getFileSelector();
my.appletRenderer.getUploadApplet();
});
</script>
</head>
<body scroll="no">
<div id="center">
<div id="x-desktop">
<div id="center-panel-container" style="background:transparent;"></div>
</div>
</div>
</body>
</html>



2) Create an applet.js file in the same directory with following contents.


my.appletRenderer = {

getFileSelector : function() {
if (new ActiveXObject("Scripting.Dictionary") != null) {
return this.getActiveXFileSelector();
} else {
return this.getSwingFileSelector();
}
},

getSwingFileSelector : function(){
if (Ext.isIE || Ext.isChrome) {
if (Ext.isIE8 ) {
return new Ext.Panel({
renderTo: 'center-panel-container',
height : 0,
html : '<object ' +
'id = "SwingFileSelectorApplet" ' +
'name="SwingFileSelectorApplet" ' +
'codebase="" ' +
'archive="" ' +
'code="" ' +
'cache_archive="" ' +
'cache_version="" ' +
'width="0" ' +
'height="0" ' +
'mayscript="true"  ' +
'bodyStyle="display:none;"> ' +
'</object>'
});
}else{
return new Ext.Panel({
renderTo: 'center-panel-container',
height : 0,
html : '<applet ' +
'id="SwingFileSelectorApplet" ' +
'name="SwingFileSelectorApplet" ' +
'codebase="" ' +
'archive="" ' +
'code="" ' +
'width=0 ' +
'height=0 ' +
'mayscript="true">' +
'<param name="cache_archive" value="" />'+
'<param name="cache_version" value="" />'+
'</applet>'
});
}
}else{
return new Ext.Panel({
renderTo: 'center-panel-container',
height : 0,
html : '<EMBED '
+ 'id="SwingFileSelectorApplet" '
+ 'name="SwingFileSelectorApplet" '
+ 'codebase="" '
+ 'archive="" '
+ 'code="" '
+ 'type="application/x-java-applet;version=1.4" '
+ 'cache_archive="" '
+ 'cache_version="" '
+ 'EMBEDDED="true" '
+ 'mayscript="true" '
+ 'width="0" '
+ 'height="0"> '
+ '<NOEMBED> No Java 2 SDK, Standard Edition v 1.4.1 support for APPLET!! </NOEMBED> '
+ '</EMBED>'
});
}
},

getActiveXFileSelector : function() {
return new Ext.Panel({
renderTo:'center-panel-container',
height : 0,
html : ' <object classid="" align="baseline" border="0">'
+ '<param name="LPKPath" value="">'
+ '</object>'
+ '<object classid="" codebase="" '
+ 'VIEWASTEXT name="fileDialog" id="CommonDialog1"><param NAME="CancelError" VALUE="0">'
+ '<param NAME="DialogTitle" VALUE="'+ fs.locale.write("docUpload", "selectFile") +'">'
+ '<param NAME="" VALUE=""><param NAME="" VALUE="">'
+'</object>'
});
},

getUploadApplet : function(){
if(Ext.isWindows){
return this.getWindowsUploadApplet();
}
else{
return this.getUnixUploadApplet();
}
},

getWindowsUploadApplet : function(){
if (Ext.isIE) {
if (Ext.isIE8 ) {
return new Ext.Panel({
renderTo:'center-panel-container',
height : 0,
html : '<object '
+ 'id = "FileUpload" '
+ 'name="FileUpload" '
+ 'codebase="" '
+ 'archive="" '
+ 'code="" '
+ 'width=0 '
+ 'height=0 '
+ 'mayscript="true" '
+ 'bodyStyle="display:none;">'
+ '<param name="cache_archive" value="" />'
+ '<param name="cache_version" value="" />'
+ '</object>'
});
}else{
return new Ext.Panel({
renderTo:'center-panel-container',
height : 0,
html : '<applet '
+ 'id = "FileUpload" '
+ 'name="FileUpload" '
+ 'codebase="" '
+ 'archive="" '
+ 'code="" '
+ 'width=0 '
+ 'height=0 '
+ 'mayscript="true" '
+ 'bodyStyle="display:none;">'
+ '<param name="cache_archive" value="" />'
+ '<param name="cache_version" value="" />'
+ '</applet>'
});
}
}else if (Ext.isChrome) {
return new Ext.Panel({
renderTo:'center-panel-container',
height : 0,
html : '<applet '
+ 'id = "FileUpload" '
+ 'name="FileUpload" '
+ 'codebase="" '
+ 'archive="" '
+ 'code="" '
+ 'width=0 '
+ 'height=0 '
+ 'mayscript="true" '
+ 'bodyStyle="display:none;">'
+ '<param name="cache_archive" value="" />'
+ '<param name="cache_version" value="" />'
+ '</applet>'
});
}else{
return new Ext.Panel({
renderTo: 'center-panel-container',
height : 0,
html : '<EMBED ' +
'id="FileUpload" ' +
'name="FileUpload" ' +
'codebase="" ' +
'archive="" ' +
'code="" ' +
'type="application/x-java-applet;version=1.4" ' +
'cache_version="" ' +
'cache_archive="" ' +
'width="0" ' +
'height="0" ' +
'mayscript="true"> ' +
'<NOEMBED> No Java 2 SDK, Standard Edition v 1.4.1 support for APPLET!! </NOEMBED>'+
'</EMBED>'
});
}
},

getUnixUploadApplet : function(){

return new Ext.Panel({
renderTo:'center-panel-container',
height : 0,
html : '<applet '
+ 'id = "FileUpload" '
+ 'name="FileUpload" '
+ 'codebase="" '
+ 'archive="" '
+ 'code="" '
+ 'width=0 '
+ 'height=0 '
+ 'mayscript="true" '
+ 'bodyStyle="display:none;">'
+ '<param name="cache_archive" value="" />'
+ '<param name="cache_version" value="" />'
+ '</applet>'
});
}

}




3) In the applet.js file if you pass the proper values of the attribute which i have kept blank like codebase, archive,code,classid etc. the applets will get render.

4) View the main.html and view source the applets be enabled.

5) And this code will work for almost all the browser and OS. (Only you need to create your own jar files operating system specific)

6) Same check can be applied for the download and other applet.

Tuesday, September 27, 2011

Extjs Fix For Firefox Text overflow.

HTML Online Editor Sample
       In the recent Extjs development i faced an issue related to the content overflow for Firefox. i was retrieving a data from the DB table which is having the CLOB field. CLOB type filed is used to store a data more than 4k. The CLOB field in My XML response have a data of around 8k. So i was not able to see the full data (8k) of that field. i was able to see only the 4k data in the Extjs text area. After doing a search i have got the following information.

        A text node in Firefox allows only 4K data. So an XML Ajax response gets split up into multiple text child nodes instead of only one node. Its fine in Internet Explorer(only up to 64k) and opera (only up to 32k). For Firefox, to get the full data you either need to use node.normalize() before you call node.firstChild or use node.textContent, or user node.wholeText both of which are Mozilla specific methods.

To fix this issue in Extjs i did the following steps.

If you are using the XmlReader then you need to override it.

/**
 * Copyright(c) 1998-2009, Sword-global.
 * 
 * The class represents a custom XML reader component for FusionSaas. Hold
 * handle to the current viewer and configuration parameters for XML Reader.
 * 
 */
my.XmlReader=Ext.extend(Ext.data.XmlReader,{
    constructor: function(meta, recordType){
         my.XmlReader.superclass.constructor.call(this, meta, (recordType || meta.fields));
    },
    /**
     * Create a data block containing Ext.data.Records from an XML document.
     * @param {Object} doc A parsed XML document.
     * @return {Object} records A data block which is used by an {@link Ext.data.Store} as
     * a cache of Ext.data.Records.
     */
    readRecords : function(doc){
        this.xmlData = doc;
        var root = doc.documentElement || doc;
        var q = Ext.DomQuery;
        var recordType = this.recordType, fields = recordType.prototype.fields;
        var sid = this.meta.idPath || this.meta.id;
        var totalRecords = 0, success = true;
        if(this.meta.totalRecords){
            totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
        }
        if(this.meta.success){
            var sv = q.selectValue(this.meta.success, root, true);
            success = sv !== false && sv !== 'false';
        }
        var records = [];
        var ns = q.select(this.meta.record, root);
        for(var i = 0, len = ns.length; i < len; i++) {
            var n = ns[i];
            var values = {};
            var id = sid ? q.selectValue(sid, n) : undefined;
            for(var j = 0, jlen = fields.length; j < jlen; j++){
                var f = fields.items[j];
                var v = this.selectMoreThan4KValue(Ext.value(f.mapping, f.name, true), n, f.defaultValue);
                v = f.convert(v, n);
                values[f.name] = v;
            }
            var record = new recordType(values, id);
            record.node = n;
            records[records.length] = record;
        }
        return {
            success : success,
            records : records,
            totalRecords : totalRecords || records.length
        };
    },
    
    selectMoreThan4KValue : function(path, root, defaultValue){
     trimRe = /^\s+|\s+$/g
        path = path.replace(trimRe, "");
        valueCache = {};
        if(!valueCache[path]){
            valueCache[path] = Ext.DomQuery.compile(path, "select");
        }
        var n = valueCache[path](root),
         v;
        n = n[0] ? n[0] : n;
        if(n && Ext.isGecko){
         v = (n && n.firstChild ? n.firstChild.wholeText : null);
        }else{
         v = (n && n.firstChild ? n.firstChild.nodeValue : null);
        }
        return ((v === null||v === undefined||v==='') ? defaultValue : v);
    }
});

Tuesday, September 6, 2011

mxGraph Extjs Integration

HTML Online Editor Sample
This article will help you to integrate the mxGraph in the Extjs.
Follow the following steps to create a setup.

1) Create a folder named mxgraph_extjs_integrtion.
2) Download ext-all.js, ext-base.js and mxClient.js files into mxgraph_extjs_integrtion folder.
3) Create a MxGraphExtjsIntegration.html file in the same folder with the following content.


<html>
<head>
<title>Integrating mxGraph with Extjs</title>
<style>
div.styled {
border-width:2px;
border-color:#ff9900;
border-style: solid solid solid solid;
background: url('workflow-designer/grid_10.png');
}
</style>
<script type="text/javascript" src="ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>
<script type="text/javascript" src="mxClient.js"></script>    
<script>
Ext.onReady(function(){
var centerDiv = document.getElementById('center-panel-container');
var mainDiv = document.createElement('div');
mainDiv.id = 'workflow-designer-main-panel';
// Process Container
var graphDiv= document.createElement('div');
graphDiv.id = 'graph';
graphDiv.style.width = '900px';
graphDiv.style.height = '600px';
graphDiv.style.top = '30px';
graphDiv.className = 'styled';
// Toolbar
var tbarDiv = document.createElement('div');
tbarDiv.id = 'toolbar';
tbarDiv.style.height = '24px';
tbarDiv.style.left= '300px';
tbarDiv.style.width = '500px';
tbarDiv.style.overflow = 'hidden';
tbarDiv.style.display = 'block';
tbarDiv.style.position = 'absolute';
mainDiv.appendChild(tbarDiv);
mainDiv.appendChild(graphDiv);
centerDiv.appendChild(mainDiv);
new loadWFConfig('fsworkflowconfig.xml');
});
selectionChanged = function(graph) {
};
loadWFConfig = function(config) {
try {
if (!mxClient.isBrowserSupported()) {
mxUtils.error('Browser is not supported!', 200, false);
}else {
var node = mxUtils.load(config).getDocumentElement();
var editor = new mxEditor(node);
}
} catch (e) {
// Shows an error message if the editor cannot start
mxUtils.alert('Cannot start application: ' + e.message);
throw e; // for debugging
}
return editor;
};
onInit = function(editor, isFirstTime){
mxEvent.disableContextMenu(document.body);
editor.validation = true;
var editorGraph = editor.graph;
// Defines an icon for creating new connections in the connection handler.
// This will automatically disable the highlighting of the source vertex.
mxConnectionHandler.prototype.connectImage = new mxImage('workflow-designer/connector.gif', 16, 16);
// Highlights the vertices when the mouse enters
var highlight = new mxCellTracker(editorGraph, '#999900');
editorGraph.setConnectable(true);
editorGraph.setDropEnabled(true);
editorGraph.setPanning(true);
editorGraph.setTooltips(true);
editorGraph.setAllowDanglingEdges(false);
editorGraph.connectionHandler.setCreateTarget(true);
mxGraphHandler.prototype.cloneEnabled = false;
// Sets the cursor
editorGraph.container.style.cursor = 'default';
var listener = function(sender, evt){
// This code tests to see if a node is dragged to less than the far left or top and
// if so, re-positions it at the 0px left or top
try{
var change = evt.properties.changes[0];
var cell = change.hasOwnProperty("cell") ? change.cell : change.child;
var geometry = cell.getGeometry();
var x = geometry.x;
var y = geometry.y;
if(x < 0) geometry.x = 10;
if(y < 0) geometry.y = 10;
if(x < 0 || y < 0){
cell.setGeometry(geometry);
editorGraph.refresh();
}
}
catch(e){}
// Perform validation after any change
editorGraph.validateGraph();
};
editorGraph.model.addListener(mxEvent.CHANGE, listener);
// Creates rubberband selection
//var rubberband = new mxRubberband(editorGraph);
// Stop cells from being resized - this stops distortion of teh graphic and over / undersize imagery
editorGraph.setCellsResizable(false);
// mxCellAttributeChange to change properties
// Implements a properties panel that uses
editorGraph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt){
//fs.BPDefinition.hasChange = true;
selectionChanged(editorGraph);
});
};
</script>
</head>
<body>
<div id="center-panel-container" >
</div>
</body>
</html>

4) Create a file named fsworkflowconfig.xml in the same folder with following content.


<mxEditor defaultGroup="group" defaultEdge="Connector">
<add as="onInit"><![CDATA[
function (isFirstTime){
onInit(this, isFirstTime);
}
]]>
</add>
<ui>
<add as="graph" element="graph"/>
<add as="toolbar" element="toolbar"/>
</ui>
<Array as="templates">
<add as="group">
<group name="Group" style="group" description=" ">
<mxCell vertex="1" style="group" connectable="0"/>
</group>
</add>
<add as="Connector">
<connector name="Connector" style="connector" transitionAction=" " actionRequired=" " description=" ">
<mxCell edge="1">
<mxGeometry as="geometry" relative="1"/>
</mxCell>
</connector>
</add>
<add as="text">
<Text name="Label" style="text"  fsStyle=" "  description=" ">
<mxCell vertex="1" style="text" connectable="0">
<mxGeometry as="geometry" width="120" height="40"/>
</mxCell>
</Text>
</add>
<add as="start">
<start name="Start" style="start" description=" ">
<mxCell vertex="1" style="start">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</start>
</add>
<add as="activity">
<activity name="Activity" style="activity" form=" " formId=" " description=" ">
<mxCell vertex="1" style="activity">
<mxGeometry as="geometry" width="80" height="50"/>
</mxCell>
</activity>
</add>
<add as="agent">
<agent name="Agent" style="agent" classname="" type="External" description=" ">
<mxCell vertex="1" style="agent">
<mxGeometry as="geometry" width="80" height="80"/>
</mxCell>
</agent>
</add>
<add as="timer">
<timer name="Timer" style="timer">
<mxCell vertex="1" style="timer">
<mxGeometry as="geometry" width="80" height="80"/>
</mxCell>
</timer>
</add>
<add as="cancel">
<cancel name="Cancel" style="cancel" description=" ">
<mxCell vertex="1" style="cancel">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</cancel>
</add>
<add as="finish">
<finish name="Finish" style="finish" description=" ">
<mxCell vertex="1" style="finish">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</finish>
</add>
<add as="andjoin">
<andjoin name="AND-Join" style="andjoin" description=" ">
<mxCell vertex="1" style="andjoin">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</andjoin>
</add>
<add as="orjoin">
<orjoin name="OR-Join" style="orjoin" description=" ">
<mxCell vertex="1" style="orjoin">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</orjoin>
</add>
<add as="andsplit">
<andsplit name="AND-Split" style="andsplit" description=" ">
<mxCell vertex="1" style="andsplit">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</andsplit>
</add>
<add as="decision">
<decision name="Decision" style="decision" description=" " expression=" ">
<mxCell vertex="1" style="decision">
<mxGeometry as="geometry" width="40" height="40"/>
</mxCell>
</decision>
</add>
<add as="conditionalor">
<conditionalor name="Conditional-OR" style="conditionalor" description=" ">
<mxCell vertex="1" style="conditionalor">
<mxGeometry as="geometry" width="40" height="80"/>
</mxCell>
</conditionalor>
</add>
</Array>
<mxGraph as="graph" alternateEdgeStyle="verticalEdge">
<add as="getTooltipForCell"><![CDATA[
function(cell){
return cell.getAttribute('form');
}
]]>
</add>
<add as="convertValueToString"><![CDATA[
function(cell){
var cellTitle = cell.getAttribute('name');
return cellTitle;
}
]]>
</add>
<mxStylesheet as="stylesheet">
<add as="text">
<add as="shape" value="rectangle"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="12"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="shadow" value="0"/>
<add as="strokeColor" value="none"/>
<add as="fillColor" value="none"/>
<add as="gradientColor" value="none"/>
</add>
<add as="defaultEdge">
<add as="shape" value="connector"/>
<add as="fontSize" value="10"/>
<add as="rounded" value="1"/>
<add as="strokeColor" value="#000000"/>
<add as="strokeWidth" value="2"/>
<add as="edgeStyle" value="elbowEdgeStyle"/>
<add as="endArrow" value="classic"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
<add as="fontColor" value="#111111"/>
</add>
<add as="verticalEdge" extend="defaultEdge">
<add as="elbow" value="vertical"/>
<add as="strokeColor" value="#000000"/>
</add>
<add as="group">
<add as="shape" value="group"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="align" value="center"/>
<add as="verticalAlign" value="middle"/>
<add as="strokeColor" value="#000000"/>
<add as="dashed" value="1"/>
</add>
<add as="start">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-Start.gif"/>
</add>
<add as="activity">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="verticalAlign" value="middle"/>
<add as="image" value="workflow-designer/BPMN-Activity.gif"/>
</add>
<add as="agent">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="verticalAlign" value="middle"/>
<add as="image" value="workflow-designer/Agent.gif"/>
</add>
<add as="timer">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="verticalAlign" value="middle"/>
<add as="image" value="workflow-designer/Timer.gif"/>
</add>
<add as="cancel">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-Cancel.gif"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
</add>
<add as="finish">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-End.gif"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
</add>
<add as="andjoin">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-And-Join.gif"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
</add>
<add as="andsplit">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-And-Split.gif"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
</add>
<add as="decision">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-Conditional.gif"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
</add>
<add as="orjoin">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="center"/>
<add as="imageAlign" value="center"/>
<add as="verticalAlign" value="top"/>
<add as="verticalLabelPosition" value="bottom"/>
<add as="spacingTop" value="2"/>
<add as="image" value="workflow-designer/BPMN-Or-Join.gif"/>
<add as="labelBackgroundColor" value="#f1f1f1"/>
<add as="labelBorderColor" value="#aaa"/>
</add>
<add as="conditionalor">
<add as="shape" value="image"/>
<add as="perimeter" value="rectanglePerimeter"/>
<add as="fontSize" value="10"/>
<add as="fontStyle" value="1"/>
<add as="align" value="right"/>
<add as="verticalAlign" value="bottom"/>
<add as="image" value="workflow-designer/Conditional-OR-Split.gif"/>
</add>
</mxStylesheet>
<mxGraphModel as="model">
<add as="valueForCellChanged"><![CDATA[
function(cell, value){
var previous = null;
if (isNaN(value.nodeType)){
previous = cell.getAttribute('name');
cell.setAttribute('name', value);
}else{
previous = cell.value;
cell.value = value;
}
modified = true;
return previous;
}
]]>
</add>
</mxGraphModel>
</mxGraph>
<mxDefaultKeyHandler as="keyHandler">
<add as="46" action="delete"/>
</mxDefaultKeyHandler>
<mxDefaultToolbar as="toolbar" spacing="8">
<add as="text" template="text" icon="workflow-designer/text.gif"/>
<add as="start" template="start" icon="workflow-designer/Start-24.gif"/>
<add as="cancel" template="cancel" icon="workflow-designer/Cancel-24.gif"/>
<add as="finish" template="finish" icon="workflow-designer/Finish-24.gif"/>
<add as="activity" template="activity" icon="workflow-designer/Workflow-Activity-24.gif"/>
<add as="andjoin" template="andjoin" icon="workflow-designer/AND-Join-24.gif"/>
<add as="andsplit" template="andsplit" icon="workflow-designer/AND-Split-24.gif"/>
<add as="orjoin" template="orjoin" icon="workflow-designer/OR-Join-24.gif"/>
<add as="decision" template="decision" icon="workflow-designer/BPMN-Conditional-24.gif"/>
</mxDefaultToolbar>
</mxEditor>

5) Create workflow-designer folder under the same folder. and put your images mentioned in the  fsworkflowconfig.xml file.

6) Open the MxGraphExtjsIntegration.html in the fireforx browser.
.

Generate Unique String with only Special Characters.


Following code will generate the unique string containing the special characters. You can specify the length of the string to generate.

 public class UniqueStringGenerator {

    /** 
     * Minimum length for a decent string 
     */  
    public static final int MIN_LENGTH = 5;  
   
    /** 
     * The random number generator. 
     */  
    protected static java.util.Random r = new java.util.Random();  
   
    protected static char[] goodChar = {  
        // Comment out next two lines to make upper-case-only, then  
        // use String toUpper() on the user's input before validating.  
        '~', '`', '@', '#', '$', '%', '^','&','*','(',')','{','}','[', ']',':'
    };  
   
    //Generate a Password object with a random password.  
    public static String getNext() {  
        return getNext(MIN_LENGTH);  
    }  
   
    // Generate a unique string with a random function.  
    public static String getNext(int length) {  
        if (length < 1) {  
            throw new IllegalArgumentException(  
                    "Ridiculous password length " + length);  
        }  
        StringBuffer sb = new StringBuffer();  
        for (int i = 0; i < length; i++) {  
            sb.append(goodChar[r.nextInt(goodChar.length)]);  
        }  
        return sb.toString();  
    }  
    
    public static void main(String[] args) {
        System.out.println(getNext());
    }
 }

Monday, September 5, 2011

Convert JSON String to Java Object (POJO)


 
 During the recent development came to a scenario where I want to convert the JSON string into the java object (POJO). to achieve this  i decided to use the "gson" API provided by the google. Following the is example how i have converted the JSON to POJO.

External API  : gson-1.3.jar from google.



import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JsonToPojo {

   /**
    * @param args
    */
public static void main(String[] args) {

String jsonString= "[{name:'Yogesh',address : 'Pimple Saudagar',age:29},
{name:'Puneet',address :'Hadapsar',age:27},                                               {name:'Sameer',address:'Wagholi',age:31}]";

Student [] students = getJsonFormString(jsonString, Student[].class);

for (Student student : students) {
System.out.println("Name  --> " + student.getName());
System.out.println("Address --> " + student.getAddress());
System.out.println("Age --> " + student.getAge());
}
}

/**
 * Returns the JSON representation from string.
 * 
 * @param <T>
 * @param json
 * @param type
 * 
 */
public static <T> T getJsonFormString(String json,  Class<T> type) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();
Gson gson = gsonBuilder.create();
return (T) gson.fromJson(json, type);
}

}

class Student {

private String name;
private String address;
private int age;

/**
 *  Constructor
 */
public Student (){

}

/**
 * @return the name
 */
public String getName() {
return name;
}

/**
 * @param name the name to set
 */
public void setName(String name) {
this.name = name;
}

/**
 * @return the address
 */
public String getAddress() {
return address;
}

/**
 * @param address the address to set
 */
public void setAddress(String address) {
this.address = address;
}

/**
 * @return the age
 */
public int getAge() {
return age;
}

/**
 * @param age the age to set
 */
public void setAge(int age) {
this.age = age;
}
}

Validate Java Expression


    You may come under a scenario where you want to check at runtime if the given expression is valid or not. For example you are building a expression builder on the client side. With the help of of expression builder you can create a expression. Expression may contains different data types like Integer, String and Date. Now the question is how can any one check if the build expression is valid or not. I have the following code that will ensure given expression is valid or not.

Assumption :

1) This code will work on java 6 and above.
2) You have to pass the expression in the form of values.


import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.util.Arrays;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
public class ExpressionEvaluator {

public static boolean isValidExpression( String expression) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
System.out.println("compiler  = " + compiler);
System.out.println("JAVA HOME = " + System.getProperty("java.home"));
System.out.println("CLASSPATH = " + System.getProperty("java.class.path"));
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
out.println("public class TextExpression {");
out.println("  public static void main(String args[]) {");
out.println("    if(" + expression + "){}");
out.println("  }");
out.println("}");
out.close();
JavaFileObject file = new JavaSourceFromString("TextExpression", writer.toString());
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
boolean success = task.call();
return success;
}
}


class JavaSourceFromString extends SimpleJavaFileObject {

final String code;
JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.', '/')+ Kind.SOURCE.extension), Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}

Friday, September 2, 2011

JBPM and JEXL Integration

Following steps need to perform to configure the JEXL as a expression language for the JBPM.


1) Create a jbpm.default.scriptmanager.xml file.
     File contains following tag.

<?xml  version="1.0" encoding="UTF-8" ?>
<jbpm-configuration>
<process-engine-context>
<script-manager default-expression-language="jexl" default-script-language="jexl">
<script-language name="jexl" 
    factory="org.apache.commons.jexl2.scripting.JexlScriptEngineFactory" />
<script-language name="juel" factory="org.jbpm.pvm.internal.script.JuelScriptEngineFactory" />
<script-language name="bsh" factory="org.jbpm.pvm.internal.script.BshScriptEngineFactory" />
<script-language name="groovy"
   factory="org.jbpm.pvm.internal.script.GroovyScriptEngineFactory" />
</script-manager>
</process-engine-context>
</jbpm-configuration>


2) Import jbpm.default.scriptmanager.xml file into jbpm.default.cfg.xml file.
3) For the decision node specify the condition as follows.

  <decision name="evaluate document">
    <transition to="submit document">
      <condition expr="content=='good'" lang="jexl" />
    </transition>
    <transition to="try again">
      <condition expr="content=='not so good'" lang="jexl"/>
    </transition>
    <transition to="give up" />
  </decision>