Thursday, December 26, 2013

Synchronized access to a List and other Java Collections

Java 1.2 collections are not sychronized for faster performance but are not thread safe in a multithreaded environment.  These collections can be synchronized using Collections.synchronizedXxx() methods.

The Java Collections class has several static methods that return synchronized (thread-safe)  collections. These methods are:

Collections.synchronizedCollection(Collection<T> c)
Collections.synchronizedList(List<T> list)
Collections.synchronizedMap(Map<K,V> m)
Collections.synchronizedSet(Set<T> s)
Collections.synchronizedSortedMap(SortedMap<K,V> m)
Collections.synchronizedSortedSet(SortedSet<T> s

See the javadoc for the Collections class.

Example:

package com.example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class SynchronizedExample {

 public static void main(String[] args) {

  List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

  syncList.add("mango");
  syncList.add("orange");
  syncList.add("apple");

  // manually synchronize on the returned synchronized list 'syncList' (using 'synchronized') when iterating over it
  // failure to use a 'synchronized' block may result in non-deterministic behavior
  synchronized (syncList) {
   Iterator<String> iterator = syncList.iterator();
   while (iterator.hasNext()) {
    System.out.println("fruit: " + iterator.next());
   }
  }

 }

} 

It is imperative to manually synchronize on 'syncList' (the list returned by Collections.synchronizedList) by using a synchronized block when iterating over it to lock the synchronized List object.

Sunday, November 17, 2013

Websphere Commerce: Command Caching and DynaCache

Java objects and the command cache

DynaCache provides support for caching the returned results from Java™ object calls. DynaCache provides a very straightforward mechanism that allows you to cache the results from these Java command objects; it is called command caching.

Commands written to the WebSphere® command architecture access databases, file systems, and connectors to perform business logic, and often run remotely on another server. Significant performance gains can be achieved by caching command results and avoiding their repeated invocation.

To take advantage of command caching, applications must be written to the WebSphere command framework API. This API is based on a common programming model, and uses a series of getters(), setters() and execute() methods to retrieve its results. To use a command, the client creates an instance of the command and calls the execute() method for the command. Depending on the command, calling other methods could be necessary. The specifics will vary with the application.

With Command cache, the data is cached before it is transformed into HTML. In order to take advantage of command caching, you must make simple code changes to your Java objects so that DynaCache can call them to retrieve the data. Command objects inherit from com.ibm.websphere.command.cachableCommandImpl and must provide certain methods to function properly.

Executed command objects can be stored in the cache so that subsequent instances of that command object's execute method can be served by copying output properties of the cached command to the current command for retrieval by its get methods. DynaCache supports caching of command objects for later reuse by servlets, JSPs, EJBs, or other business logic programming.


Interface (Example):

public interface CustomerRepsRetrieveCmd extends TargetableCommand{
    // set default command implement class
    static final String defaultCommandClassName =  "com.abccompany.commerce.commands.CustomerRepsRetrieveCmdImpl";
    /* property getters and setters go here */
    public String getCustomerId();
    public void setCustomerId(String customerId);  
    public List getCustomerRepsList();
}


Implementation Class (Example):

public class CustomerRepsRetrieveCmdImpl extends CacheableCommandImpl implements CustomerRepsRetrieveCmd {
    
     private String customerId; 
     private List customerRepsList;
 
     // called to validate that command input parameters have been set
     public boolean isReadyToCallExecute() {
          return (getCustomerId() != null && !"".equals(getCustomerId()));
     }
    
     // called by a cache-hit to copy output properties to this object
     public void setOutputProperties(TargetableCommand cmd) {
          CustomerRepsRetrieveCmd repsRetrieveCmd = (CustomerRepsRetrieveCmd) cmd;
          setCUstomerRepsList(repsRetrieveCmd.getCustomerRepsList());
     }
 
     public void performExecute() throws Exception {          
          /* business logic code goes here */
  
          ABCSession abcSession = Utilities.getABCSession();
          if(getCustomerId() != null && !"".equals(getCustomerId())) {
             setCustomerRepsList(abcSession.getCustomerReps(getCustomerId()));
          } else {
             setCustomerRepsList(new ArrayList());
          }
     }
 
     /* property getters and setters go here */
 
     public List getCustomerRepsList() {
          return customerRepsList;
     }
 
     protected void setCustomerRepsList(List repsList) {
          this.customerRepsList = repsList;
     }
 
     public String getCustomerId() {
          return customerId;
     }
 
     public void setCustomerId(String customerId) {
          this.customerId = customerId;
     }
}

Cacheable objects are also defined in the cachespec.xml file found inside the Web application archive (WAR) , Web module WEB-INF directory, or enterprise bean WEB-INF directory. A global cachespec.xml file can also be placed in the application server properties directory, but the recommended method is to place the cache configuration file with the deployment module.



Info pulled from the IBM documentation:

Command cache

CacheableCommandImpl

CacheableCommand

Configuring the dynamic cache service in cachespec.xml






Saturday, November 16, 2013

Websphere Commerce: Setting the view in a ControllerCommand

In the performExecute() method of the controller command, set the view in the response properties like:

     TypedProperty responseProperties = getResponseProperties();
     responseProperties.put(ECConstants.EC_VIEWTASKNAME, "MyNewView"); 
     setResponseProperties(responseProperties);


     OR

     TypedProperty responseProperties = getResponseProperties();
     responseProperties.put(“viewTaskName”, "MyNewView"); 
     setResponseProperties(responseProperties);



 When redirecting the view to the same jsp page do:

         responseProperties.put("redirecturl", "CustomerAccountForm");
         responseProperties.put("viewTaskName", "RedirectView");
         setResponseProperties(responseProperties);


where: CustomerAccountForm is the URL mapped to the same jsp page, i.e. CustomerAccount.jsp


For Commerce built- in commands (blackbox):

See IBM infocenter’s documentation for the command’s implementation class (cmdimpl).

Example -  RequisitionListDisplayCmdImpl:

IBM Documentation states that  for the View:
  • If requisitionListId is specified, it sets RequisitionListDetailView.
  • If requisitionListId is not specified, it sets RequisitionListView.

So, in order to return a view for this command, you need to map either the RequisitionListView or RequisitionListDetailView url to a jsp file in your configuration file (such as struts-config.xml file).

DOJO: Destroy then create a ContentPane

There may be instances where you may need to destroy an existing dojo ContentPane then replace it with a new ContentPane and place it in the same container div element.

Since all of this may also occur after the DOM (web page) has been rendered, you will also need to parse the widget to execute any javascipt code you may have in the new ContentPane. An example scenario is when your new ContentPane invokes a JSP page with a javascript code for an ajax call (nested ajax calls).

Here is a simple javascript function to destroy then create a ContentPane.

function destroyCreateContentPane() {
      
      // destroy the existing content pane 
      dijit.byId("cpId").destroyRecursive();
 
      // get the containing div element
      var containerDiv = dojo.byId("divContId");
 
      // create the new content pane (widget) and set the values for it's id and class properties
      var cpWidget = new dojox.layout.ContentPane({
                  id:"cpId",
                  class:"cpClass",
      });
 
      // use the contentpane's 'domNode' property to get the top level DOM node of the new contentpane widget (the visible representation of the widget)  
      var cpDiv = cpWidget.domNode;
 
      // put the new contentpane div as the last node of the containing div 
      dojo.place(cpDiv, containerDiv, 'last');
      cpDiv.id = "cpId";
 
      // optional: hide the new empty div
      cpDiv.style.display = "none";
 
      // parse the new contentpane widget
      dojo.parser.parse(dojo.byId('cpId'));
}

Sunday, November 3, 2013

Javascript: onfocus event and focus() method

onfocus in HTML

The onfocus event occurs when an element gets focus.

onfocus is often used with <input>, <select>, and <a>.

Check out the onfocus event here.

HTML Example:

<input type="text" onfocus="yourFunction()">


You may also pass the 'input' element as a parameter to your onfocus handler's function using the keyword 'this'.

<input type="text" onfocus="yourFunction(this)">


JavaScript Example:

HTMLElementObject.onfocus = function(){ your javascript code here }


The onfocus attribute can be used within ALL HTML elements, EXCEPT: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, and <title>.

So in javascript, you can also use the focus() method on any HTML element except on what’s listed above.


focus() Method

The focus() method is used to give focus to a HTML element.

Syntax:

HTMLElementObject.focus()

Example:

<script type="text/javascript">
  document.getElementById("targetElementId").focus();
</script>

Check out the focus() method here.

CSS: Showing the horizontal and vertical scrollbars

It is pretty easy to show the horizontal and vertical scrollbars for block DOM elements such as a DIV.

You just need to set the following CSS properties for your div:
  • width
  • height
  • overflow
You may also use the overflow-x property to show or hide the horizontal scrollbar and the overflow-y property to show or hide the vertical scrollbar.

Just use the following class with the style rules to show the horizontal and vertical scrollbars.

.scrollableContainer {
  background-color: #FCFCDD !important; 
  font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif; 
  font-size:.9em; 
  padding: 10px; 
  width: auto;  
  height: auto;
  max-height: 500px; 
  overflow: auto; 
  word-wrap: normal;
  white-space: nowrap; 
}


Or you may apply it inline like this:

<div style="background-color: #FCFCDD; font-family: courier; font-size:.9em; padding: 10px; width: auto; height: auto; max-height: 500px; overflow: auto; word-wrap: normal; white-space: nowrap;" >
</div> 

Thursday, October 24, 2013

Java: Iterator

The Iterator interface is a member of the  Java Collections Framework.

Important notes about Iterator:

  • We can iterate in only one direction.
  • Iteration can be done only once. If you reach the end of the collection its done. If we need to iterate again we should get a new Iterator.
  • We cannot add or remove elements to the underlying collection when we are using an iterator except by calling the Iterator's remove() method.


Here is the Iterator interface documentation.

ITERATOR WITHOUT GENERICS USING FOR-LOOP

import java.util.ArrayList;
import java.util.Iterator;

public class ExampleIterator {

  public static void main(String args[]){
    List brands = new ArrayList();
    brands.add("Honda");
    brands.add("Nissan");
    brands.add("Toyota");

    for (Iterator iter = brands.iterator(); iter.hasNext();) {
    String brand = (String)iter.next();
      System.out.println(brand);
    } 
  }

}

Note: Without generics, Iterator returns an Object so you need to typecast it.


ITERATOR WITH GENERICS USING FOR-LOOP

public class ExampleIterator {

  public static void main(String args[]){
    List<String> brands = new ArrayList<String>();
    brands.add("Honda");
    brands.add("Nissan");
    brands.add("Toyota");

    for (Iterator<String> iter = brands.iterator(); iter.hasNext();){
    String brand = iter.next();      
      System.out.println(brand);
    }
  }

}


ITERATOR WITHOUT GENERICS USING WHILE-LOOP

import java.util.ArrayList;
import java.util.Iterator;

public class ExampleIterator {

  public static void main(String args[]){
    List brands = new ArrayList();
    brands.add("Honda");
    brands.add("Nissan");
    brands.add("Toyota");

    Iterator iter = brands.iterator();

    while(iter.hasNext()) {
      String brand = (String)iter.next();
      System.out.println(brand);
    }
  }

}


ITERATOR WITH GENERICS USING WHILE-LOOP

import java.util.ArrayList;

public class ExampleIterator {

  public static void main(String args[]){
    List<String> brands = new ArrayList<String>();
    brands.add("Honda");
    brands.add("Nissan");
    brands.add("Toyota");

    Iterator<String> iter = brands.iterator();

    while (iter.hasNext()){
      String brand = iter.next();
      System.out.println(brand);
    }
  }

}


ITERATE USING FOR-EACH OF GENERICS
(No explicit reference to the Iterator object)

import java.util.ArrayList;

public class ExampleIterator {

  public static void main(String args[]){
    List<String> brands = new ArrayList<String>();
    brands.add("Honda");
    brands.add("Nissan");
    brands.add("Toyota");

    for(String brand : brands) {
      System.out.println(brand);
    }
  }

}



Tuesday, October 15, 2013

Java: Best way to use the equals() method

The equals() method compares values for equality. Since this method is defined in the Object class, which is the root of the class hierarchy, it's automatically defined for every class such as the String class.

The best way to use the  .equals() method when comparing values of String objects is to write it as:

"Hello World".equals(fooBar);
"".equals(fooBar);

rather than:

fooBar.equals("Hello World");
fooBar.equals("");


Both sets of examples will compile but the first set guarantees that a NullPointerException is never thrown when you perform the comparison. The second set may risk throwing a  NullPointerException if the object fooBar happens to be null.

Thursday, October 10, 2013

Websphere Application Server: Use a cleanup batch file instead of coding in debug mode

Typically, we run our application servers in debug mode when we code so it picks up our changes on java files without the need to restart the server before we run our applications. However, early on at some point the Websphere Application Server (WAS) stops picking up our changes even  in debug mode.

A better alternative to running in debug mode (and the method I much prefer) is starting the application server  through a normal start and using a batch file to clean up the WAS temporary files.

I just run the batch file below to clean up  the application server's temporary files every time I make changes to java and jspf files. You should also clear your browser's cache and reload the application on your browser. No need to restart the application server.

Here is the code for the batch file:

@echo off
set WCT_WASPROFILE=D:\IBM\WCToolkitEE60\wasprofile
REM Delete WebSphere Commerce Developer Temp Files
set DIR=%WCT_WASPROFILE%\temp\localhost\server1\WC\Stores.war
set DIR2=%WCT_WASPROFILE%\wstemp
set FILE=%WCT_WASPROFILE%\javacore.*.txt
set FILE2=%WCT_WASPROFILE%\heapdump.*.phd
set FILE3=%WCT_WASPROFILE%\logs\server1\*.*

ECHO.
ECHO Cleaning WAS Temp Directory:
ECHO    %DIR%
rmdir /Q /S %DIR%
ECHO.
ECHO Cleaning WSTEMP Directory:
ECHO    %DIR2%
rmdir /Q /S %DIR2%
ECHO.

ECHO Cleaning Javacore Files:
ECHO    %FILE%
DEL /Q /F %FILE%
ECHO.
ECHO Cleaning Heapdump Files:
ECHO    %FILE2%
DEL /Q /F %FILE2%
ECHO.
ECHO Cleaning Server1 Logs Files:
ECHO    %FILE3%
DEL /Q /F %FILE3%
ECHO.
ECHO Cleaning Complete...
ECHO.
PAUSE


Remember though that at some point the application server will stop picking up your changes and will need a restart. But it will be way much longer before that happens compared to when running in debug mode.

Happy coding!


Wednesday, October 9, 2013

Dojo: Using dojo.query with pseudo-selectors

Changing HTML markup programmatically is dependent on locating nodes. You may go the traditional way of  selecting HTML elements in Javascript by using the browser's native DOM API like "document.getElementsByTagName( )" and "document.getElementsByClassName( )". But your code can get long, verbose and slow.

dojo.query is a better, faster, and more compact way to do this. It can also handle sophisticated DOM element relationships.

dojo.query() returns a list of DOM nodes based on a CSS selector.

Using dojo.query with pseudo-selectors is very interesting because it's a very compact way of getting a list of DOM nodes with several attributes.

Example:
Get the input checkbox elements with its "checked" property equal to true (a checked checkbox element) contained within an unordered list with an ID of  "sidebarCategories", then put the focus on the first checked input checkbox.

var checkboxes = dojo.query("ul#sidebarCategories  input[type=checkbox]:checked");
if (checkboxes.length > 0) {
    checkboxes[0].focus();
} 

Now that code is pretty compact and clean.

Check out the dojo.query documentation for more simple and compound queries using CSS, descendant and attribute selectors.

Monday, October 7, 2013

Websphere Commerce: Controller Command Design Pattern

Commands are beans that perform business logic. Command beans follow a specific design pattern. Every command includes both an interface class (for example, CategoryDisplayCmd) and an implementation class (for example, CategoryDisplayCmdImpl). See the Websphere Commerce Command Framework and Command implementation documentation for more info.

The four main types of commands are: controller, task, view and data bean commands.

This blog post is about the controller command design pattern.

Controller Command Interface

Pattern:

public interface MyNewControllerCmd extends ControllerCommand {

   // set default command implement class
   static final String defaultCommandClassName  =  "com.ibm.commerce.sample.commands.MyNewControllerCmdImpl
}


Saturday, October 5, 2013

jQuery Plugin: modified Image Magnifier plugin for multiple images

I had a project requirement for an image magnifier for multiple images in a single page. The page will have a list of products where each product have an image magnifier as part of its listing.

I found this jQuery plugin called Easy Image Zoom among other plugins while googling for the term "image magnifier jquery".

The original jQuery plugin, demo and instructions are found on the plugin author's page.

The plugin was easy to use but only worked with just one image for each page.

So I modified the image magnifier plugin so that it will work with multiple images in one page. The plugin's javascript code with the annotated modifications is listed below. The code in blue text are the new codes and codes in red text are commented out codes.

/*
 * Easy Zoom 1.0 - jQuery plugin
 * written by Alen Grakalic
 * http://cssglobe.com/post/9711/jquery-plugin-easy-image-zoom
 *
 * Copyright (c) 2011 Alen Grakalic (http://cssglobe.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Built for jQuery library
 * http://jquery.com
 *
 */

 /*

 Required markup sample

 <a href="large.jpg"><img src="small.jpg" alt=""></a>

 */

(function($) {

$.fn.easyZoom = function(options){

var defaults = {
id: 'easy_zoom',
parent: 'body',
append: true,
preload: 'Loading...',
error: 'There has been a problem with loading the image.'
};

var obj;
var img = new Image();
var loaded = false;
var found = true;
var timeout;
var w1,w2,w3,w4,h1,h2,h3,h4,rw,rh;
var over = false;
//new code 
var hoveredLink;

var options = $.extend(defaults, options);

this.each(function(){

obj = this;
// works only for anchors
var tagName = this.tagName.toLowerCase();
if(tagName == 'a'){
/* - commented out this code because the img var only stores the image of the last <a> link element
var href = $(this).attr('href');
img.src = href + '?' + (new Date()).getTime() + ' =' + (new Date()).getTime();
$(img).error(function(){ found = false; })
img.onload = function(){
loaded = true;
img.onload=function(){};
};
*/
$(this)
.css('cursor','crosshair')
//.click(function(e){ e.preventDefault(); })
.click(function(){ hide(); })
.mouseover(function(e){ start(e, this); })
.mouseout(function(){ hide(); })
.mousemove(function(e){ move(e); })
};

});

function start(e, imgLink){
hide();

/* begin new code */
//assign mouseovered image link to global var hoveredLink
hoveredLink = imgLink;
//load the zoom image (big image) for the mouseovered image link
var href = imgLink.href;
img = new Image();
img.onload = function(){
loaded = true;
};
img.src = href;
$(img).error(function(){ found = false; })
/* end new code */

var zoom = $('<div id="'+ options.id +'">'+ options.preload +'</div>');
if(options.append) { zoom.appendTo(options.parent) } else { zoom.prependTo(options.parent) };
$('#'+ options.id).html('').append(options.preload);
if(!found){
error();
} else {
if(loaded){
show(e);
} else {
loop(e);
};
};
};

function loop(e){
if(loaded){
show(e);
clearTimeout(timeout);
} else {
timeout = setTimeout(function(){loop(e)},200);
};
};

function show(e){
over = true;
w1 = 0; h1 = 0; w2 = 0; h2 = 0; w3 = 0; h3 = 0; w4 = 0; h4 = 0; rw = 0; rh = 0;
$(img).css({'position':'absolute','top':'0','left':'0'});
//put the big image in the popup DIV
$('#'+ options.id).html('').append(img);
/* - commented out and replaced this code because $('img', obj) wrongly gets the last small image in the page
w1 = $('img', obj).width();
h1 = $('img', obj).height();
*/

/* begin new code */
/* use children[0] to get the thumb image because firstElementChild returns null in IE10 and
firstChild returns a text node in Chrome. children is a collection of just the child nodes that are elements */
//get small image properties
w1 = $(hoveredLink.children[0]).width();
h1 = $(hoveredLink.children[0]).height();
/* end new code */

//get popup zoom DIV properties
w2 = $('#'+ options.id).width();
h2 = $('#'+ options.id).height();

//get big image properties
w3 = $(img).width();
h3 = $(img).height();

//get difference between big image properties and  DIV (of big image) properties
w4 = w3 - w2;
h4 = h3 - h2;

//get ratio of w4 and h4 against small image properties
rw = w4/w1;
rh = h4/h1;

move(e);
};

function hide(){
over = false;
/* begin new code */
loaded = false;
found = true;
/* end new code */
$('#'+ options.id).remove();
};

function error(){
$('#'+ options.id).html(options.error);
};

function move(e){
if(over){
// target image movement
//var p = $('img',obj).offset();

//replaced code above with new code below to get the correct thumb image (small image link)
/* begin new code */
/* use children[0] to get the thumb image because firstElementChild returns null in IE10 and
firstChild returns a text node in Chrome. children is a collection of just the child nodes that are elements */
var thumbImg = hoveredLink.children[0];
var p = $(thumbImg).offset(); //get the 'top' and 'left' coordinates of the small image
/* end new code */

//pageX returns the mouse position relative to the LEFT edge of the document
//pl = difference between the mouse position and LEFT coordinate of the small image
var pl = e.pageX - p.left;

//pageY returns the mouse position relative to the TOP edge of the document
//pt = difference between the mouse position and TOP coordinate of the small image
var pt = e.pageY - p.top;

//rw is the RATIO of the big image width against the width of the zoom DIV (of big image)
//xl = the new LEFT coordinate of the big image
var xl = pl*rw;

//rh is the RATIO of the big image height against the height of the zoom DIV (of big image)
//xt = the new TOP coordinate of the big image
var xt = pt*rh;

xl = (xl>w4) ? w4 : xl;
xt = (xt>h4) ? h4 : xt;

//if big image is smaller than popup DIV container, center the image in the DIV
//else, do the image magnifier scroll
if (w4 < 0 && h4 < 0) {
//top property of big image = (Div height - big image height) / 2
var topVal = (h2-h3)/2;
$(img).css({'position':'relative', 'top':topVal, 'display':'block', 'margin':'0 auto'});
} else {
//$('#'+ options.id + ' img').css({'left':xl*(-1),'top':xt*(-1)});   --> original code replaced with the one below
$(img).css({'left':xl*(-1),'top':xt*(-1)});
}
};
/* begin new code */
//check if big image was loaded (is available)
if (!loaded) {
$('#'+ options.id).html('').append("Big image is not available");
};
/* end new code */
};

};

})(jQuery);


Monday, September 30, 2013

Javascript: Dynamically setting width and height properties for scrollbars of fluid pages

It is usually pretty straight-forward to set a div to handle horizontal and vertical scrolling for fixed-width elements.

You will just need to set the following CSS properties for your div:
  • width
  • height
  • overflow
You may also just use the overflow-x property to display the horizontal scrollbars or clip just the left/right edges of the content inside the div element.

You may also just use the overflow-y property to display the vertical scrollbars or clip the top/bottom edges of the content inside the div element.

Here's the link for values that you may use for these overflow properties.

But how do you handle a fluid page that adjusts to screen sizes and the width of the div is not fixed?

Wednesday, September 25, 2013

Javascript: Commented out HTML markup and DOM traversal

Here's the use case and different behaviors I observed in IE, Chrome and Firefox browsers today.

I have the markup snippet below in my jspf.

<table>
    <tr>
      <td>
          <input type="checkbox" id="someId" class="inputClass">
      </td>
      <td>
          <!-- <label  for="someId" >Your Label Here</label>  -->
          <label  for="someId" class="labelClass">Your Label Here</label>
      </td>
    </tr>
</table>

I wanted to get the first element node found inside the second <td>. 
When traversing this particular snippet using the nextElement method, IE is returning the commented out <label> tag as the first element node. Chrome and Firefox is smart enough to return the uncommented <label> tag.

I thought of trying jsp comment tags in place of the html comment tags to see if I would get a different result. I just didn't have enough time.

Javascript: Getting the next element node with cross-browser compatibility

Getting the next element node in IE is a pain. IE does not support the nextElementSibling method of the DOM Element object and using the nextSibling method also returns text nodes.

So I wrote the javascript function below which will only return an element node (node type of 1).

function getNextElement(srcElement) {
      var nextElement = srcElement.nextSibling;
      while (nextElement.nodeType != 1) {
            nextElement = nextElement.nextSibling;
      }
      return nextElement;
}