Thursday, September 5, 2013

Android - Displaying Formatted Text

Bugging me for a while but all you do is:

Step 1: Format the Java String as html
   String formattedMessage = document.replaceAll("(\\r|\\n)", "<br/>");
   formattedMessage = formattedMessage.replaceAll("\\s", "&nbsp;");

Step 2: Display the text in a pre tags
    StringBuilder sb = new StringBuilder();
    sb.append("<html><body><pre>");
    sb.append(formattedMessage);
    sb.append("</pre></body></html>");
    return sb.toString();

Step 3: Display in an AlertDialog using a WebView
   public void showHtml(String html) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setIcon(R.drawable.dialog_information);    
    WebView webView = new WebView(this);
    webView.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    webView.loadData(html, "text/html", "utf-8");
    builder.setView(webView);
    builder.show();
  }   

   

Thursday, May 2, 2013

Regular Expressions (Again! Yes, I have forgotten the basics... meh)

So to match a couple of sub-strings, use this: .*(One|Two|Three|Example).*

Monday, October 1, 2012

Now Novel, an online book writing course

For my latest project, please check out the Now Novel website -  it's an online novel writing course designed to get you started quickly.

I had to learn how to program in ruby using ruby on rails (RoR) - I am a Java developer usually, so it was quite a steep learning curve, but very enjoyable. 

I am a new convert to to RoR and was amazed about how quick it was to get a website up and running. For front-end heavy websites, I'd definitely use RoR again. I am really glad that the initial plan of hacking together a WordPress site was abandoned. That would have been php hell!

For more information: I am using Devise for my user registration framework - awesome! Wicked wizard for all the wizards (basically the whole site) and Radar's Forem for the forum. All great libraries that I would recommend to anyone.

Monday, September 27, 2010

GWT: Developer Mode and Spring Contex Listener

I could not get the usual Spring web context listener to work with GWT 2.0.4 in developer mode, running within Eclipse.

Usually the context listener will load the bootstrap Spring files and then parse the classpath to do auowiring, etc. Running the GWT application in Developer mode failed to parse the classpath so any @Autowired annotations threw exceptions with no bean found error message.

The same Spring files loaded fine when loaded "old school way" - IE remove the web context loader listener and use a manual creation of the Spring application context using the same XML files.

Code Change:

In order to get the Developer mode working within Eclipse, I followed what other monkeys had done and nastily copy & paste the GWT class used to start up Developer mode (which is essentially a Jetty-specific class) and made one small change to get it working for Spring classpath parsing.

The class is called com.google.gwt.dev.shell.jetty.JettyLoader
located here: gwt-src-2010-09-02/trunk/dev/core/src (where gwt-src-2010-09-02 is the root of where the GWT code was checked out to from Subversion).

I copy the whole class as a new class called SpringJettyLoader and changed it as follows:
private final ClassLoader bootStrapOnlyClassLoader = new ClassLoader(null) {};
to
private final ClassLoader bootStrapOnlyClassLoader = Thread.currentThread().getContextClassLoader();

I also had to copy the additional class called JettyNullLogger and include it with my new loader class to reduce hassles.

Running GWT Web Application:

A change is required to the Eclipse Run Configuration used to run your GWT web application. Open up the Run Configuration.
On the Server (2nd) tab, uncheck the "Run built-in server" option.
On the Arguments tab, change the current arguments to include your new class as the -server option.
-noserver 
-remoteUI "${gwt_remote_ui_server_port}:${unique_id}" 
-startupUrl PropertyWeb.html 
-server com.tradecraft.property.web.server.jetty.SpringJettyLauncher 
-logLevel INFO 
-war /home/aisling/development/workspaces/workspace2/property-web/war com.tradecraft.property.web.PropertyWeb

Eclipse Classpath:

I was using m2eclipse to do my dependency resolution for me within Eclipse. This ended up being more trouble than it was worth as I kept getting other dependencies includes that I didn't expect. This especially caused issues with Hibernate 3.3.5.FINAL and JPA 1.0 and 2.0.

I ended up putting all my libs in the usual WEB-INF/lib directory and all the other Eclipse projects specifically pointed to those jars.

Eclipse Source Folders Additional Note:

Removing m2eclipse from the projects, left the classes output pointing to /target/classes which is fine but then I attempted to change all the output directories to /bin. The previously added source folders contain to point to the old location and you wonder why nothing works.

It is cleaner to remove all the source folders within each Eclipse project and then re-add them as they then point to where you expect them to.

Thursday, September 16, 2010

GWT: Custom context menu on a Tree

Monkeys, in order to add a custom pop up menu to a tree (or any similar widget I suppose) which is displayed instead of the usual browser's context menu when you right-click on the tree, you can do the following:

Create a Tree class that implements the correct interface for adding a context menu handler:
package com.tradecraft.property.web.client.view.type;

import com.google.gwt.event.dom.client.ContextMenuEvent;
import com.google.gwt.event.dom.client.ContextMenuHandler;
import com.google.gwt.event.dom.client.HasContextMenuHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Tree;

public class MenuContextTree extends Tree implements HasContextMenuHandlers {

  @Override
  public HandlerRegistration addContextMenuHandler(ContextMenuHandler handler) {
    return addDomHandler(handler, ContextMenuEvent.getType());
  }

}

Then add a handler instance to your tree:
public class PropertyTypesAdminScreen extends BaseClientContentScreen {
  ...
  @Override
  public void initScreenUi() {
    tree = new MenuContextTree();
    tree.addContextMenuHandler(new ContextMenuHandler() {      
      @Override
      public void onContextMenu(ContextMenuEvent event) {
        showContextMenu();
        //Don't let the browser display its default context menu
        event.preventDefault();
      }
    });
    mainPanel.add(tree);
  }

  private void showContextMenu() {
    TreeItem selectedTreeItem = tree.getSelectedItem();
    if (selectedTreeItem != null && selectedTreeItem.getUserObject() != null) {
      //do your thing like display a pop up menu
      MenuDialog menuDialog = new MenuDialog(menuBar);
      menuDialog.showRelativeTo(selectedTreeItem);
    }
  }
}


Wednesday, September 15, 2010

Hibernate SQLQuery

In the last week I have seen this error twice when running native SQL queries to a MySQL database using Hibernate. (I am forced to use SQL - not my first choice.)
No Dialect mapping for JDBC type: -1

It took me a while to find the answer, so I thought I would share.

The problem this time is that the data I was retrieving was a longtext column (not a regular varchar) and this is not automatically mapped by the MySQL dialect (I believe this is fixed in Hibernate 3.5).

I solved the problem by using "addScalar" to define the mapping to use. It worked!


Query query = getSession()
.createSQLQuery("select data from form_data where form_data_id = ?")
.addScalar("data", Hibernate.TEXT)
.setInteger(0, formData.getId());
String oldData = ((String)query.uniqueResult());

Hibernate: Parent and Children --> Retrieving Children using a Filter

Same classes as the previous post but this time to avoid an issue with lazy loading the children outside of a closed Hibernate session, load the parent and its children together in the DAO.

This is slightly more complicated as the data model class now has a status attribute (true || false). Either load all the data or only load the data that is active (If a parent is not active, it is not loaded so none of its children is loaded either).

Using the Criteria API, there doesn't seem to be a way to specify a join criteria on the children join.
You can do it easily using a query:
from Cat as cat
left join cat.kittens as kitten
with kitten.bodyWeight > 10.0
Hence the use of a filter when using the Criteria API. The filter either restricts the children to be active or just loads all of them.

@Repository
public class HibernatePropertyTypeDaoImpl extends BaseHibernateDao implements PropertyTypeDao {
  
  private static final String ACTIVE_WHERE_CLAUSE = "where active = true";
  
  private static Logger LOG = LoggerFactory.getLogger(HibernatePropertyTypeDaoImpl.class);

  @Override
  @SuppressWarnings("unchecked")
  public List getCommercialPropertyTypes(boolean onlyActive) {
    List commercialTypes = (List) getPropertyTypesWithoutChildren(CommercialPropertyType.class, onlyActive);
    for(CommercialPropertyType commercialType : commercialTypes) {
      getChildren(commercialType, onlyActive);
    }
    return commercialTypes;
  }
  
  @SuppressWarnings("unchecked")
  private List getPropertyTypesWithoutChildren(Class clazz, boolean onlyActive) {
    Criteria criteria = sessionFactory.getCurrentSession().createCriteria(clazz); 
    criteria.add(Restrictions.isNull("parent"));
    if (onlyActive) {
      criteria.add(Restrictions.eq("active", true));
    }
    criteria.addOrder(Order.asc("id"));
    return criteria.list();
  }

  @SuppressWarnings("unchecked")
  protected void getChildren(CommercialPropertyType type, boolean onlyActive) {
    List children = null;
    if (onlyActive) {
      children = sessionFactory.getCurrentSession()
                               .createFilter(type.getChildren(), ACTIVE_WHERE_CLAUSE)
                               .list();
    } else {
      children = sessionFactory.getCurrentSession()
                               .createFilter(type.getChildren(), "")
                               .list();
    }
    type.setChildren(children);
    LOG.debug("Set children:"+children);
  } 
}