Some Basic Sed Examples

Grep, Awk and Sed are powerful tools that unfortunately are not part of the Windows default. Here are some commands to get you started.


cat punchcard.txt | grep "[0-9]" | sed "s/[| ]//g" >output.txt

The cat command will output all lines, grep will filter on lines containing any digit 0 through 9, sed will substitute verticalBars, spaces with nothing (ie remove verticalBars, spaces). “g” means global. The output will go into output.txt.


git reset --hard 4d407960fc7ab2a5f31553618025327d6e1d8372
cat pom.xml | sed "s/http:\/\/nxraptor.qa.com\/content\/repositories\/releases\//http:\/\/nxrepository.corp.com\/nexus\/content\/repositories\/releases\//g" > pom2.xml
call mvn -f pom2.xml clean deploy -DskipTests -e

This powerful sed command was used to pull an old version of code and deploy into a separate Maven repository after substituting the old repository url in the pom.xml file.

A Follow Up On Navigation Through JQuery

This is a follow up to Creating Expandable and Collapsable Rows in a Table with JQuery and Using JQuery to Print an Entire HTML Tag.

This article does not follow my standard of plug and play. In other words, it is a snipet of code to show examples, yet it cannot be downloaded and run. I always encourage posts to have a complete runnable page to demonstrate the concept written. However, this is a follow up to the previous posts above which have these. This allows additional snipets to use.


<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

<script type="text/javascript">
	function printTag($node) {
		var $message = '<' + $node.tagName;
		for ( var i = 0; i < $node.attributes.length; i++) {
			$message = $message + ' ' + $node.attributes.item(i).nodeName
					+ '="' + $node.attributes.item(i).nodeValue + '"';
		}
		$message = $message + '>';
		$message = $message + $node.innerHTML;
		$message = $message + '</' + $node.tagName + '>';
		alert($message);
	}

	function printComment($node) {
		var $message = '<!--' + $node.nodeValue + '-->';
		alert($message);
	}

	function printText($node) {
		var $message = $node.nodeName;
		alert($message);
	}

	function findNextSiblingWhichIsNotTextOrComment($node) {
		var $nodeToCheck = $node.nextSibling;
		while ($nodeToCheck.nodeName == '#text'
				|| $nodeToCheck.nodeName == '#comment') {
			if ($nodeToCheck.nodeName == '#text') {
				//printText($nodeToCheck);
			} else {
				//printComment($nodeToCheck);
			}
			$nodeToCheck = $nodeToCheck.nextSibling;
		}
		return $nodeToCheck;
	}

	function infoLayerShow($infoButton) {
		//printTag($infoButton); // A

		$divInformation = findNextSiblingWhichIsNotTextOrComment($infoButton);
		//printTag($divInformation); // DIV information

		$divInformation.style.visibility = 'visible'; // takes up space, can be seen
	}

	function infoLayerHide($closeButton) {
		//printTag($closeButton); // A

		$divInformation = $closeButton.parentNode;
		//printTag($divInformation); // DIV information

		$divInformation.style.visibility = 'hidden'; // takes up space, can't be seen
	}

	//  <tr> rule row
	//    <td> 10%
	//      <a>
	//    <td> 90%
	//      <div>
	//      <table>
	//        <tr> detail row
	function findFirstDetailRowFromAnchor($a) {
		//printTag($a); // A

		var $td10 = $a.parentNode;
		//printTag($td10); // TD 10%

		var $td90 = findNextSiblingWhichIsNotTextOrComment($td10);
		//printTag($td90); // TD 90%

		var $divMask = findNextSiblingWhichIsNotTextOrComment($td90.firstChild);
		//printTag($divMask); // DIV maskLayer

		var $table = findNextSiblingWhichIsNotTextOrComment($divMask);
		//printTag($table); // TABLE content

		var $tbody = findNextSiblingWhichIsNotTextOrComment($table.firstChild);
		//printTag($tbody); // TBODY

		var $firstTR = $tbody.firstChild;
		//printTag($firstTR); // TR

		return $firstTR;
	}
	
	// show all but first row, expand table
	function rowsShow($a) {
		//printTag($node); // A
		$a.innerHTML = '<img src="minusb.jpg">';
		$a.setAttribute('onclick', 'rowsHide(this)');

		var $firstTR = findFirstDetailRowFromAnchor($a);
		var $currentNode = $firstTR.nextSibling;
		while (($currentNode.nodeName != '#comment')
				|| ($currentNode.nodeValue != 'TEST_STEPS')) {
			//alert("whileLoop, $currentNode.nodeName:"+$currentNode.nodeName);
			if ($currentNode.nodeName == 'TR') {
				$currentNode.style.display = ''; // takes up space, can be seen
			}
			$currentNode = $currentNode.nextSibling;
		}
	}

	// collapse all but first row, collapse table
	function rowsHide($a) {
		//printTag($node); // A
		$a.innerHTML = '<img src="plus3.jpg">';
		$a.setAttribute('onclick', 'rowsShow(this)');

		var $firstTR = findFirstDetailRowFromAnchor($a);
		var $currentNode = $firstTR.nextSibling;
		while (($currentNode.nodeName != '#comment')
				|| ($currentNode.nodeValue != 'TEST_STEPS')) {
			//alert("whileLoop, $currentNode.nodeName:"+$currentNode.nodeName);
			if ($currentNode.nodeName == 'TR') {
				$currentNode.style.display = 'none'; // takes up no space, can't be seen
			}
			$currentNode = $currentNode.nextSibling;
		}
	}
	
	// add image to all rows with multiple details
	function rowsInitialize($a) {
		var $firstTR = findFirstDetailRowFromAnchor($a);
		var $currentNode = $firstTR.nextSibling;
		while (($currentNode.nodeName != '#comment')
				|| ($currentNode.nodeValue != 'TEST_STEPS')) {
			//alert("whileLoop, $currentNode.nodeName:"+$currentNode.nodeName);
			if ($currentNode.nodeName == 'TR') {
				$a.innerHTML = '<img src="minusb.jpg">';
				$a.setAttribute('onclick', 'rowsHide(this)');
			}
			$currentNode = $currentNode.nextSibling;
		}
	}

	$(document).ready(function() {
		// Change background colors for rule rows
		$('tr.testRuleRow:even').css('background-color', '#D1D0CE');
		$('tr.testRuleRow:odd').css('background-color', '#BCC6CC');

		// Change background colors for detail rows
		$('tr.testDetailRow:even').css('background-color', '#E5E4E2');
		$('tr.testDetailRow:odd').css('background-color', '#F5F5DC');
		
		// Add expand/collapse to all rule rows with multiple details
		$('tr.testRuleRow').each (function () {
			var $testRuleRow = this;
			//printTag($testRuleRow);
			
			var $td10 = findNextSiblingWhichIsNotTextOrComment($testRuleRow.firstChild);
			//printTag($td10);
			
			var $a = findNextSiblingWhichIsNotTextOrComment($td10.firstChild);
			//printTag($a);
			
			rowsInitialize($a);
		});
	});
</script>

You will notice my javascript coding preference of adding $ to all variables and using single quotes for strings even though neither of these is required.

Using JQuery to Print an Entire HTML Tag

When using JQuery, you might be using code like “$node.parentNode”, “$node.nextSibling”, “$node.firstChild” and “alert(‘$node.nodeName:’ + $node.nodeName);” to navigate through an HTML page, using relative referrences. It may be helpful to see the actual tag you are working with.

In addition, this may be helpful if the tag is dynamcially edited during runtime. “$node.parentNode.style.visibility = ‘hidden’;”

Here is a dummy HTML page that allows you to dynamically print the a tag:


<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
	function printTag($node) {
		var message = '<' + $node.tagName;
		for (var i=0; i<$node.attributes.length; i++){
			message = message + ' ' + $node.attributes.item(i).nodeName + '="' + $node.attributes.item(i).nodeValue + '"';
		}
		message = message + '>';
		message = message + $node.innerHTML;
		message = message + '</' + $node.tagName + '>';
		alert(message);
	}
</script>
</head>
<body>
<a href="http://www.google.com" onclick="printTag(this)">Click Me</a>
</body>
</html>

As usual, add this to a text file and rename with the extension “.html”. Then, try opening with the Google Chrome Internet Browser.

Working with Data in UI Applications

It many different types of applications, you may have a GUI which is responsible for displaying data to the user. Most applications today have this information.

For instance, Facebook takes comments that are probably stored in a database in some data warehouse, somewhere and is responsible for stitching this information to display to the user.

Often, the GUI has the capability to allow the user to change the data. For example, a user may be able to change their home address, thus storing different data.

For sake of this discussion, we will call the underlying data the MODEL and the GUI, the GUI. It may be possible that there are multiple GUIs that can change the MODEL. In addition, maybe certain command line tools have the capability to change the MODEL. You may also have loading data files, open, save, etc.

So, realizing this, lets say, a user interacts with the GUI to make a change. Most developers would make the changes to the MODEL and in addition also make the changes to the GUI. The natural way to update the GUI would then have three different code based to maintain.

1. Update the GUI when the GUI is initialized.
2. Update the GUI when the user makes a change through the GUI.
3. Update the GUI when a user makes a change to the MODEL, through an external source.

The external source as mentioned above may be another GUI, load, command line tool, etc.

Is it wise to maintain three different code bases which all do basically the same thing. The better design choice is to place an emphasis on what the user is trying to do. Make sure the interactions with the GUI focus on changing the MODEL. After all, when your emphasis is here, when bugs occur and they always do, you can just reuse the code base for 1 to refresh the GUI and view the data.

Always focus on changing the MODEL and let the GUI figure out how to update changes to the model. Include enough tracking information so that the GUI may do minimal effort through notification to update itself.

Now, your design should be like this.

1. Initialization code focuses on intializing the GUI with placeholders for data. After initialization, a method focuses on refreshing the data from the MODEL. The GUI may hold some state information, but the ultimate truth of what the data is comes from the MODEL. If the GUI and MODEL both hold the same flag, and they are out of sync, the MODEL is always right.

2. Interactions with the GUI focus on changing the MODEL. After the MODEL is changed internally from the GUI, a method focuses on refreshing the data from the MODEL. Even if the GUI “knows” what the data values are, the GUI pulls the information through the MODEL. For example, a user may click the link “Add Friend”. It is natural to then have the GUI automatically change to “Friend Request Sent”. However, this is a mistake. The internet connection may go down and the change may never be added to the backend database. In this sense, even though the GUI might “know” that a “Friend Request Sent” should be displayed, it may use this as a placeholder, but it should go to the MODEL to check the actual state.

3. Interactions from other tools or GUIs do their own thing. After the MODEL is changed externally, from another GUI, a method focuses on refreshing the data from the MODEL. This may be done via subscription to notifications. The GUI itself may affect the resolution of various notifications that are sent. For instance, a customer can always let the editor of a newsletter what they appreciate or additional news or information they might need. However, it is always up to the editor to determine if the newsletter changes will be welcomed by all customers. A GUI always has the option to pull all data being displayed instead of focusing on changing a small piece. In addition, a GUI always displays a subset of the actual data available. In this sense, the MODEL is the truth. The GUI is just a perspective.

There is always three sides to a story. What he said, what she said and the truth.

Happy Coding!!!

Reading the Project Version from the Maven Pom File

So recently, I came across this issue. Suppose you have a project that is distributed to multiple developers who download the project and run tests. In addition, suppose you want to gather statistics and data based on testing done in local environments. To filter this data, you wish to include the version of the project with the testing data.

So here are some goals:

  1. Only store the project version in a single location.
  2. Allow users to pull project version in development environments through common usage.
  3. Programmatically read the project version.

Sometimes programmers will leave flags throughout their code. For instance, you might have a selection flag which tracks selected objects. I believe that this value should be in a single place. Every attribute should be owned by a single object. When this doesn’t occur, people find themselves questioning why one part of the application thinks an item should be selected but another part does not. Or one part of the application thinks the error color is red and another thinks the error color is pink. One owner for every attribute. In this case, since the pom.xml file holds the version, you would not want to have this version also held in other places where developers may forget to update the version on a release.

When programmers download the project, they often use Eclipse for Java projects and they often have Project->Automatically Build selected. This invokes the Java Builder, not the Maven Builder. What this means is that when you have a properties file in src/main/resources that is read with the Java Properties object, the resource is not filtered:

From the pom.xml file:


<project>
  ...
  <build>
    ...
    <resources>
	  ...
      <resource>
        <filtering>true</filtering>
        <directory>src/main/resources</directory>
      </resource>
    </resources>

From the properties file in src/main/resources/com/mycompany/myapp/projectDefault.properties


MAVEN_PROJECT_VERSION=${project.version}

From the java code:


	private static void loadProperties(){
		String filePath = MyClass.class.getResource(
				"projectDefault.properties").getPath();
		try {
			prop.load(new FileInputStream(filePath));
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
	}

In this scenario, if you use ‘mvn compile’ or ‘mvn test-compile’ the projectDefault.properties file would be found compiled (usually in the target/classes or target/test-classes directory) with the appropriate version via resource filtering. This means that programmatically if the code is run through maven or deployed, the version will be loaded correctly.

However, the issue is that if the Java Builder (which doens’t know about Maven) compiles the Java classes, the resource filtering won’t happen. Being consistent with the 1 click build concept, you should not require your developers to have to know about this. You should pretend as if the developers will never read your documentation or instructions, especially if they are familiar with running common operations.

So what do you do? How do you get the requirements above. In my case, I forked the VM, and checked to see if the version loaded from projectDefault.properties was still ${project.version}. In other words, if the project version was not added through resource filtering, I would invoke maven to process the resources again and then re-read.


	private static Properties prop;
	private static Properties getProperties() {
		if(prop == null) {
			prop = new Properties();
			loadProperties();
		}
		return prop;
	}

String value = System.getProperty("MAVEN_PROJECT_VERSION"); // Check System Properties first to see if user set version

if(value == null) {
    value = getProperties().getPropery("MAVEN_PROJECT_VERSION"); // Check properties file next to see if projectDefault.properties was set
}

if(value.equals("${project.version}")) {
    System.out.println("Reloading pom.xml file for local run start");
    tryCompilingPomFile();
    loadProperties();
    value = getDefaultProperty(this.name());
    System.out.println("Reloading pom.xml file for local run finish, MAVEN_VERSION:"+value);
}

  /**
   * To fix an auto build which did not override the project.version in the projectDefault.properties file
   */
	private void tryCompilingPomFile() {
		try {
			InvocationRequest request = new DefaultInvocationRequest();
			request.setPomFile(new File("pom.xml"));
			request.setGoals(Collections.singletonList("process-resources"));

			Invoker invoker = new DefaultInvoker();
			invoker.setMavenHome(new File(System.getenv("M2_HOME")));
			invoker.execute(request);
		} catch (MavenInvocationException e) {
			e.printStackTrace();
		}
	}

To use this invoker, you will need to include the following in your pom.xml (and provide the resource).


<project>
...
	<dependencies>
	....
		<!-- Process Resources from Maven Dynamically -->
		<dependency>
			<groupId>org.apache.maven.shared</groupId>
			<artifactId>maven-invoker</artifactId>
			<version>2.1.1</version>
		</dependency>
		<!-- Process Resources from Maven Dynamically -->

If you have a single class with a main method that can be downloaded and run that implements the above, please share. 🙂

With code discussions, we should get to the point where we can literally download and run in 5 minutes. Most likely, this discussion will take at least half an hour of testing to get something working. That is just not acceptable. It is a sign of laziness on my part. The sign of a genius is that they can formulate their ideas in such a way that it seems simple.

Adding the Swing Editor Plugin for Eclipse

Related Pages:
www.rcp-vision.com
Install Maven Eclipse Plugin and Test Resources Folder.

Help->Install New Software->Enter http://download.eclipse.org/releases/kepler

SWT Designer
SWT Designer Core
WindowBuilder Core
WindowBuilder Core UI
WindowBuilder GroupLayout Support
WindowBuilder Java Core

I also added Windows Builder XML Core (since I had the WTP plugin from the post mentioned above).

Oops!!!

I actually wanted the Swing Designer: Google – http://dl.google.com/eclipse/inst/d2wbpro/latest/4.2

The purpose of this is to use a designer to create forms. Right click->New->JPanel, for instance…

Working with the SAX Parser in Java

The idea is that for any jar, there should be symmetry. If a class has a method that loads a String from a File, it should also contain a method that persists the File from a String. Preferrably, the method names are also symmetric. For example, you might have:

void read(File file)
void write(File file)

String read(File file)
void write(File file, String)

One of my issues with the SAX Parser is that the method names to parse the File do not have really clear associates for method names to render the File. Even using words like parse and render for symmetry.

Also, people should be able to get up and running quickly, so being able to include commands to install the jar in Maven and include a dependency in the pom.xml file on the fly are helpful.

Here is a generic SAX Parser. Notice, it is coded to an interface meaning that the code can be reused. Also, notice that it includes a main class so someone can simply download and run, without guessing how to use the code. Demos get people up and running quickly.


package com.mycompany.app.util;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XMLFileHelper extends DefaultHandler {
	public static void main(String[] args) { 
		System.out.println("START");
		try {
			final Map valueMap = new LinkedHashMap();
			valueMap.put("red", "10");
			valueMap.put("blue", "80");
			valueMap.put("green", "55");
			
			XMLFileInterface xmlFileInt = new XMLFileInterface(){

				@Override
				public String render() {
					return ""+valueMap.get("red")+""+valueMap.get("blue")+""+valueMap.get("green")+"";
				}
				
				@Override
				public void startElement(String qName, Attributes attributes) {

				}

				@Override
				public void endElement(String qName) {

				}

				@Override
				public void characters(String qName, String string) {
					valueMap.put(qName, string);
				}
			}; 

			XMLFileHelper fileHelper = new XMLFileHelper(xmlFileInt);
			String outputFile = "/Users/Scott/workspace/SoftwareMusicProject/myrepo/my-app/output/xmlHelper.xml";
	    	fileHelper.write(new File(outputFile));
			System.out.println("After Write:"+xmlFileInt.render());

	    	valueMap.clear();
			System.out.println("After Clear:"+xmlFileInt.render());
	    	
	    	String inputFile = "/Users/Scott/workspace/SoftwareMusicProject/myrepo/my-app/output/xmlHelper.xml";
	    	fileHelper.read(new File(inputFile));
			System.out.println("After Read:"+xmlFileInt.render());
		} catch (Exception ex) {
			
		}
		System.out.println("FINISH");
	}
	XMLFileInterface xmlInt;
	public XMLFileHelper(XMLFileInterface xmlInt){
		this.xmlInt = xmlInt;
	}
	
	public void write(File outputFile) throws Exception {
		try {
			String xml = xmlInt.render();
			FileHelper fileHelper = new FileHelper();
			fileHelper.write(outputFile, xml);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void read(File inputFile) throws Exception{
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser saxParser = factory.newSAXParser();
			saxParser.parse(inputFile, this);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	String qName;
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		xmlInt.startElement(qName, attributes);
		this.qName = qName;
	} 
	
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		xmlInt.endElement(qName);
	}
	
	public void characters(char ch[], int start, int length)
			throws SAXException {
		xmlInt.characters(qName, new String(ch, start, length));
	}
	
	public static interface XMLFileInterface {
		public String render();
		public void startElement(String qName, Attributes attributes);
		public void endElement(String qName);
		public void characters(String qName, String string);
	}
}

Commands to use the jar and include the dependency in the local Maven repo and pom.xml file. Run from Git in the same directory as the pom.xml file. This is for a Maven project.

You may have to Google sax parser to download the jar. Another pet peeve is that any jar if they really want to make it available, they should give a url to download it from. What if I want to write and IDE that automatically downloads SAX and includes it in the library for use? What if I want to archetype a Maven project that automatically sets up the pom.xml file and adds it as a default for all programmers in my organization?


-- Download Sax Jar, Can rename as .zip and browse to make sure downloaded correctly
curl http://sourceforge.net/projects/sax/files/sax/SAX%202.0.2%20%28sax2r3%29%20final/sax2r3.zip/download > sax-2.0.2.jar 
-- I have C:\apache-maven-3.1.0\bin\mvn, but can ignore the path and use mvn if path is setup
/c/apache-maven-3.1.0/bin/mvn install:install-file -Dfile=sax-2.0.2.jar -Dpackaging=jar -DgroupId=org.sax -DartifactId=sax -Dversion=2.0.2

-- This is a sed command to add the dependency to the pom.xml file but you can do this mannually
sed 's/<dependencies>/<dependencies>\r\n<!--sax-->\r\n<dependency>\r\n<groupId>org.sax<\/groupId>\r\n<artifactId>sax<\/artifactId>\r\n<version>2.0.2<\/version>\r\n<\/dependency>\r\n<!--sax-->/g' pom.xml > pom2.xml

-- The overwrites the orginal pom.xml file
mv pom2.xml pom.xml

Working with Time in Java

This article talks about timing different events like runs, etc. In general, my belief is that you should build a wrapper class which is runnable in and of itself, which pulls together various items needed from the base functionality of Java.

In other words, there should be Java, then on top of that a layer of your own classes, which are decoupled from Java (programmed to interfaces and only import classes from whatever libraries you are working with), then your various projects.

This can help you keep time or post dates.


import java.text.SimpleDateFormat;
import java.util.Calendar;

public class TimerWatch {
	long startTime;
	String timeStamp;

	public TimerWatch() {
		restart();
	}

	public void restart() {
		startTime = System.currentTimeMillis();
		setcurrentDate();
	}

	public long getTimeInMins() {
		return getTimeInMillis() / 60000;
	}

	public long getTimeInSeconds() {
		return getTimeInMillis() / 1000;
	}

	public long getTimeInMillis() {
		return System.currentTimeMillis() - startTime;
	}

	public static void sleepInSeconds(int seconds) {
		sleepInMillis(seconds * 1000);
	}

	public static void sleepInMillis(int millis) {
		try {
			Thread.sleep(millis);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * This method gets TimeStamp in the MMM-dd-yyyy HH:mm:ss format.
	 * 
	 */

	private void setcurrentDate() {
		Calendar date = Calendar.getInstance();
		SimpleDateFormat dateFormat = new SimpleDateFormat(
				"MMM-dd-yyyyHH:mm:ss");
		timeStamp = dateFormat.format(date.getTime()).replaceAll(":", "")
				.replaceAll("-", "");
		timeStamp = timeStamp.replaceAll(":", "").replaceAll("-", "");
	}

	public String getTimeStamp() {
		return timeStamp;
	}

	public long getStartTimeInMillis() {
		return startTime;
	}

}

In any organization, this same concept applies. You have a wealth of knowledge and information across the web. A subset of that, or relevant sites, information should be held within the organization. It provides a one stop landing page towards all useful information. In this day in age, there is so much information available, it is quite useful to have just pages which focus on pulling together resources for a common purpose.

Adding Mojo Plugin to Your Project

Related to mojo.codehaus.org.

The following would be added to the pom.xml file.


<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>versions-maven-plugin</artifactId>
        <version>2.1</version>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

The groupId, artifactId and version can be found from the Full Name in the documentation: mojo.codehaus.org.

If you are trying to use a different plugin, google “<artifactId>maven-versions-plugin</artifactId>”. Other plugins are available at mojo.codehaus.org.

With this plugin you can run the following to change the version.


mvn versions:set -DnewVersion=1.0.8

If you wish to use, ‘mvn versions:compare-dependencies’, you will get an error “One or more required plugin parameters are invalid/missing for ‘versions:compare-dependencies’. There are two options. Inside the plugin tags of the pom.xml file, add the configuration and remotePom tags to define the remote pom file or specify from the command line via:


mvn versions:compare-dependencies -DremotePom=com.mycompany.myapp:my-app:1.0.3

You will need the pom to compare in a central maven repository.

You can backup your pom.xml file by running the mvn version command above. Then, try


mvn verions:use-latest-versions

Compare the pom.xml files using a diff tool (Like Notepad++).

Here is a command line (Unix) to add a dependency to the pom.xml file.


sed 's/<dependencies>/<dependencies>\r\n<!--ghost-->\r\n<dependency>\r\n<groupId>org.ghost4j<\/groupId>\r\n<artifactId>ghost4j<\/artifactId>\r\n<version>0.5.0<\/version>\r\n<\/dependency>\r\n<!--ghost-->/g' pom.xml > pom2.xml

Creating Expandable and Collapsable Rows in a Table with JQuery

Take this code and put into a file named test.html. Then open that in Google Chrome.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
</head>
<body>
<h1>Expand and Collapse Rows Example</h1>
<table border=1 width=600>
<tr class='parent row1'><td width=30><center>+</center></td><th colspan=16><center>Base Title</center></th></tr>
<tr class='parent_child expandable row2'><td width=30><center>+</center></td><td colspan=8><center>Left</td><td colspan=8><center>Right</center></td></tr>
<tr class='parent_child_child expandable row3'><td width=30><center>+</center></td><td colspan=4><center>A</center></td><td colspan=4><center>B</center></td><td colspan=4><center>A</center></td><td colspan=4><center>B</center></td></tr>
<tr class='parent_child_child_child row4'><td width=30></td><td>John</td><td>10</td><td>Mark</td><td>23</td><td>Mike</td><td>23</td><td>Matt</td><td>23</td><td>Sara</td><td>11</td><td>Jill</td><td>61</td><td>Jane</td><td>11</td><td>Sally</td><td>66</td></tr>
<tr class='parent_child_child_child row5'><td width=30></td><td>John</td><td>8</td><td>Mark</td><td>46</td><td>Mike</td><td>45</td><td>Matt</td><td>45</td><td>Sara</td><td>13</td><td>Jill</td><td>11</td><td>Jane</td><td>22</td><td>Sally</td><td>72</td></tr>
<tr class='parent_child_child_child row6'><td width=30></td><td>John</td><td>7</td><td>Mark</td><td>12</td><td>Mike</td><td>82</td><td>Matt</td><td>23</td><td>Sara</td><td>51</td><td>Jill</td><td>52</td><td>Jane</td><td>31</td><td>Sally</td><td>62</td></tr>
<tr class='parent_child_child_child row7'><td width=30></td><td>John</td><td>45</td><td>Mark</td><td>23</td><td>Mike</td><td>62</td><td>Matt</td><td>44</td><td>Sara</td><td>32</td><td>Jill</td><td>33</td><td>Jane</td><td>14</td><td>Sally</td><td>22</td></tr>
<tr class='parent_child_child expandable row8'><td width=30><center>+</center></td><td colspan=4><center>C</center></td><td colspan=4><center>D</center></td><td colspan=4><center>C</center></td><td colspan=4><center>D</center></td></tr>
<tr class='parent_child_child_child row9'><td width=30></td><td>John</td><td>10</td><td>Mark</td><td>25</td><td>Mike</td><td>23</td><td>Matt</td><td>23</td><td>Sara</td><td>11</td><td>Jill</td><td>21</td><td>Jane</td><td>55</td><td>Sally</td><td>62</td></tr>
<tr class='parent_child_child_child row10'><td width=30></td><td>John</td><td>84</td><td>Mark</td><td>46</td><td>Mike</td><td>45</td><td>Matt</td><td>43</td><td>Sara</td><td>13</td><td>Jill</td><td>14</td><td>Jane</td><td>22</td><td>Sally</td><td>32</td></tr>
<tr class='parent_child_child_child row11'><td width=30></td><td>John</td><td>23</td><td>Mark</td><td>12</td><td>Mike</td><td>82</td><td>Matt</td><td>23</td><td>Sara</td><td>54</td><td>Jill</td><td>32</td><td>Jane</td><td>31</td><td>Sally</td><td>42</td></tr>
<tr class='parent_child_child_child row12'><td width=30></td><td>John</td><td>45</td><td>Mark</td><td>63</td><td>Mike</td><td>62</td><td>Matt</td><td>46</td><td>Sara</td><td>32</td><td>Jill</td><td>35</td><td>Jane</td><td>54</td><td>Sally</td><td>25</td></tr>
<tr class='parent_child expandable row13'><td width=30><center>+</center></td><td colspan=8><center>Top</td><td colspan=8><center>Bottom</center></td></tr>
<tr class='parent_child_child expandable row14'><td width=30><center>+</center></td><td colspan=4><center>A</center></td><td colspan=4><center>B</center></td><td colspan=4><center>A</center></td><td colspan=4><center>B</center></td></tr>
<tr class='parent_child_child_child row15'><td width=30></td><td>John</td><td>13</td><td>Mark</td><td>23</td><td>Mike</td><td>23</td><td>Matt</td><td>25</td><td>Sara</td><td>21</td><td>Jill</td><td>11</td><td>Jane</td><td>51</td><td>Sally</td><td>66</td></tr>
<tr class='parent_child_child_child row16'><td width=30></td><td>John</td><td>3</td><td>Mark</td><td>46</td><td>Mike</td><td>45</td><td>Matt</td><td>43</td><td>Sara</td><td>13</td><td>Jill</td><td>12</td><td>Jane</td><td>25</td><td>Sally</td><td>72</td></tr>
<tr class='parent_child_child_child row17'><td width=30></td><td>John</td><td>44</td><td>Mark</td><td>12</td><td>Mike</td><td>82</td><td>Matt</td><td>23</td><td>Sara</td><td>21</td><td>Jill</td><td>22</td><td>Jane</td><td>61</td><td>Sally</td><td>62</td></tr>
<tr class='parent_child_child_child row18'><td width=30></td><td>John</td><td>15</td><td>Mark</td><td>23</td><td>Mike</td><td>62</td><td>Matt</td><td>24</td><td>Sara</td><td>22</td><td>Jill</td><td>23</td><td>Jane</td><td>84</td><td>Sally</td><td>22</td></tr>
<tr class='parent_child_child expandable row19'><td width=30><center>+</center></td><td colspan=4><center>C</center></td><td colspan=4><center>D</center></td><td colspan=4><center>C</center></td><td colspan=4><center>D</center></td></tr>
<tr class='parent_child_child_child row20'><td width=30></td><td>John</td><td>10</td><td>Mark</td><td>15</td><td>Mike</td><td>26</td><td>Matt</td><td>33</td><td>Sara</td><td>21</td><td>Jill</td><td>51</td><td>Jane</td><td>95</td><td>Sally</td><td>63</td></tr>
<tr class='parent_child_child_child row21'><td width=30></td><td>John</td><td>14</td><td>Mark</td><td>12</td><td>Mike</td><td>65</td><td>Matt</td><td>43</td><td>Sara</td><td>43</td><td>Jill</td><td>54</td><td>Jane</td><td>62</td><td>Sally</td><td>34</td></tr>
<tr class='parent_child_child_child row22'><td width=30></td><td>John</td><td>21</td><td>Mark</td><td>12</td><td>Mike</td><td>86</td><td>Matt</td><td>23</td><td>Sara</td><td>44</td><td>Jill</td><td>35</td><td>Jane</td><td>30</td><td>Sally</td><td>46</td></tr>
<tr class='parent_child_child_child row23'><td width=30></td><td>John</td><td>15</td><td>Mark</td><td>33</td><td>Mike</td><td>66</td><td>Matt</td><td>46</td><td>Sara</td><td>42</td><td>Jill</td><td>35</td><td>Jane</td><td>50</td><td>Sally</td><td>20</td></tr>
</table>

	<script
		src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
	<script>
		$(document).ready(function() {
			$('tr.parent').css('background-color', '#87CEFA');
			$('tr.parent_child').css('display', 'none');
			$('tr.parent_child').css('background-color', '#FAEBD7');
			$('tr.parent_child_child').css('display', 'none');
			$('tr.parent_child_child').css('background-color', '#FFA07A');
			$('tr.parent_child_child_child').css('display', 'none');
			$('tr.parent_child_child_child:even').css('background-color', '#F0F8FF');
			$('tr.parent_child_child_child:odd').css('background-color', '#EFEFEF');
			
			$PLUS_HTML = '<center>+</center>';
			$MINUS_HTML = '<center>-</center>';
			$EXPANDABLE = 'expandable';
			
			$('tr').on('click', function() {
				var $row = $(this);
				if(hasHTMLInFirstColumn($row, $PLUS_HTML)) {
					setHTMLInFirstColumn($row, $MINUS_HTML);
					openImmediateDecendents($row);
				} else if(hasHTMLInFirstColumn($row, $MINUS_HTML)) {
					setHTMLInFirstColumn($row, $PLUS_HTML);
					closeAllDecendents($row);
				}
			});
			
			function closeAllDecendents($row) {
				var $nextRow = $row.next();
				//alert('closeAllDecendents while:'+(isDecendent($row, $nextRow)));
				while(isDecendent($row, $nextRow)) { // Iterate over all descendents
					closeRow($nextRow);
					$nextRow = $nextRow.next();
					//alert('closeAllDecendents nextRowClass:'+(getClasses($nextRow)));
				}	
			}
			
			function openImmediateDecendents($row) {
				var $nextRow = $row.next();
				//alert('openImmediateDecendents while:'+(isDecendent($row, $nextRow)));
				while(isDecendent($row, $nextRow)) { // Iterate over all descendents
					//alert('openImmediateDecendents if:'+(isImmediateDecendent($row, $nextRow)));
					if(isImmediateDecendent($row, $nextRow)) { // Immediate descendent
						//if(isExpandable($nextRow)) {
						//	setHTMLInFirstColumn($nextRow, $PLUS_HTML);
						//}
						openRow($nextRow);
						//alert('openImmediateDecendents expandable if:'+(hasHTMLInFirstColumn($nextRow, $MINUS_HTML)));
						if(hasHTMLInFirstColumn($nextRow, $MINUS_HTML)) {
							openImmediateDecendents($nextRow);
						}
					}
					$nextRow = $nextRow.next();
					//alert('openImmediateDecendents nextRowClass:'+(getClasses($nextRow)));
				}	
			}
			
			function hasHTMLInFirstColumn($row, $html) {
				var $firstColumn = getFirstColumn($row);
				return ($firstColumn.html() == $html);
			}
			
			function setHTMLInFirstColumn($row, $html) {
				var $firstColumn = getFirstColumn($row);
				$firstColumn.html($html);
			}
			
			/* Checks if $rowB is a decendent of rowA */
			function isDecendent($rowA, $rowB) {
				var $rowADecendentPrefix = getDecendentPrefix($rowA);
				var $rowBFirstClass = getFirstClass($rowB);
				return ($rowBFirstClass.indexOf($rowADecendentPrefix) == 0); // startsWith
			}
			
			function isImmediateDecendent($rowA, $rowB) {
				var $rowADecendentPrefix = getDecendentPrefix($rowA);
				return $rowB.hasClass($rowADecendentPrefix);
			}
			
			function getDecendentPrefix($row) {
				var $rowFirstClass = getFirstClass($row);
				return $rowFirstClass+"_child";
			}
			
			function isExpandable($row) {
				return ($row.hasClass($EXPANDABLE));
			}
			
			function getClasses($row) {
				return $row.attr('class');
			}
			
			function getFirstClass($row) {
				var $classes = getClasses($row);
				return $classes.split(' ')[0];
			}
			
			function getFirstColumn($row) {
				return $row.find('td').first();
			}
			
			function openRow($row) {
				$row.show();
			}
			
			function closeRow($row) {
				$row.hide();
			}
		});
	</script>
</body>
</html>