Business Blog Directory  Business  Business blogs  Blog Directory  Blog Directory & Search engine 

Sunday, January 8, 2012

EOSS Post Room Assistant

We thought we would take this opportunity to provide a bit more detail about what the EOSS Post Room Assistant is and what it can do for you.

Below is a diagram that shows the component parts of the EOSS Post Room Assistant, followed by a description of how it works.


For those of you that don't know, the EOSS platform is a business platform built by EOSSOnline Limited from a whole bunch of highly integrated Open Source products that we deliver over the Internet, some of which you can see in the image above. There are no license fees so all you pay is a low monthly subscription fee for the hosting and your choice of SLA to suite your business needs.


Pre-requisites:
The EOSS Suite is intended to be a "zero client install". This means that we do not, at this moment, provide any components that need to be installed on any of your machines for EOSS to operate. All functionality is usually delivered through the EOSS Portal.
However, in the case of the EOSS Post Room Assistant we wanted a way for your scanner to pass documents through to the EOSS Suite in an un-intrusive way, we didn't, for example, what you to have to load documents either one by one or in bulk through a web interface. This is not to say that you can't if you want too as this is one of the standard methods supported for getting documents into the EOSS Suite.
In the case of the EOSS Post Room Assistant we extended the EOSS directory interface so that we can use Dropbox as an online shared directory. If your not already using Dropbox, now might be a good time to take a look. In later releases we'll extend this to other online storage mechanisms such as box.com and some of the more popular cloud storage solutions available.

I must stress that this is not absolutely necessary as many scanners can be configured to send documents as email attachments, and in this case you will only need to configure an email address that we will provide you when you sign up for the service and "hey presto" your done. This does mean that you can also send any document you like to the EOSS Suite as an email attachment, even if you don't have a scanner.

For those of you with scanners that can only scan documents to directories, or this is your preferred method in the case that you can setup your scanner for either option, then you will currently need to use Dropbox. Just create a directory to scan too and then share this directory with us. EOSS will then extract your scanned documents from this directory for processing. This also means that you could just bulk copy documents directly to this location and bypass the scanning part altogether if you wanted to.

OK, so lets get on with how it works
1. Scan your document.
2a. Your document is saved to your Dropbox directory - Most scanners will save these in either PDF or TIFF format that may be in "image only" or searchable text versions, EOSS Post Room Assistant handles any of these, and more.
2b. Your document is scanned as above but is then sent directly to the email address we provided you as an email attachment. Again, the formats may be the same as above in 2a.
3 and 4 are just to show that you can just copy files to the Dropbox shared directory or just directly email documents as attachments to the EOSS Post Room Assistant.
5. The EOSS Suite receives the documents and begins processing them. This is the clever bit... The EOSS Suite determines the "classification" of each document and it's intended parties i.e. what they are and where they need to go. The EOSS Suite incorporates an OCR server that turns images into text, if possible. This means that if your scanner only creates embedded image PDF's or TIFF's we'll work it out. Documents that don't require OCR just pass straight through to the next step.
The next step is founded in NLP or "Natural Language Processing". There are other terms associated with NLP but as the EOSS Suite uses the Apache OpenNLP project then this is the term we will use. We use the Maximum Entropy framework to determine "document classification". This means that the EOSS Suite can work out if the document is an Invoice, Receipt, Complaint, CV, Contract, private letter to the CEO etc etc etc.
I won't go into the details here but it means that the EOSS Suite can "learn" new document classifications, defined by you, over time. This takes us to the final step, step 6.
6. When you first start using the EOSS Post Room Assistant it has very little knowledge about your organisation and no knowledge about the "document classifications" you want to assign in your organisation. We load the initial classification model with some broad classifications but these will not cover your requirements and indeed, you may even wish to change our initial offerings.
To do this may seem immensely complicated but is in-fact really really simple, from a users perspective that is.
If a document cannot be automatically classified it will appear in your list of documents to be classified when you access your EOSS Portal. You can easily preview all documents in this list and manually select the classification from a list of all currently know classifications, or even add a new classification if the one you want does not exist. Once a classification has been assigned to that document it is used in the document categorisation corpus training process for future reference, similar documents will now be auto categorised. This is how NLP works.

This process ensures that your EOSS Post Room Assistant is constantly aware of the types of documents your organisations deals with even when those documents have wildly differing structures from different vendors, partners or customers.

The EOSS Portal is also where you configure rules such as "where does this type of document go?". Thus you can make sure that any financial category of document gets to the Finance department Inbox and Contracts get to your legal team.

Just one more point before we finish. As the EOSS Suite has an integrated Content Management System (Alfresco). ALL of your documents, no matter how they are sent, are retained for future reference. They are fully searchable and can be accessed from anywhere in the World through your EOSS Portal. We'll discuss this as well as the EOSS Security model at a later date.

We look forward to seeing you at our next post.

The EOSSOnline Team

Tuesday, January 3, 2012

New website

Check out our new website at www.eossonline.com and let us know what you think

Thursday, September 1, 2011

Content Management - Internationalising Alfrescos LIST Constraints


EOSSOnline incorporates an Enterprise Content Management System into its EOSS stack to manage the creation and retrieval of unstructured information, mostly in the form of documents, and the ECM of choice for the EOSS stack is the rather excellent Open Source Alfresco 3.4.d Community edition.

Alfresco is much more than just a CMS but that's all we're interested in in this particular post. If you install Alfresco directly from one of the pre-packaged zip bundles you can download from their site you will have a fairly competent CMS at you disposal that you can even expose to your users as if it were a standard shared network drive.

The EOSS platform mainly uses Alfresco internally to provide content as a service to other applications and internal business processes in the EOSS stack as well as to customer defined business processes in general.

The EOSS stack has been designed to be completely internationalisable and in general Alfresco meets this requirement with it's language pack concept. However, there are a couple of areas with regards it's UI that it doesn't handle this so well. One of those areas is the rendering of drop down lists in the Alfresco Explorer UI.

So in this post we will take a look at creating a new, reusable, internationalised, drop down list component that can handle the users locale, as well as a few other bonuses. This can usually be done in one of two ways, you can either create a custom Constraint object or you can create a custom Renderer that works at the UI level, you could also employ a mix of both principles if you wanted to. There are already some articles on creating custom constraints available on the internet, one of which deals with dynamic lists that you can find here . We are going to look at the other option, creating a Custom JSF renderer to do the job instead.
There are pros and cons to each of these approaches but I just happen to like the pure renderer approach because if done right it has all of the benefits and few if any of the problems. In-fact one of those other bonuses I mentioned earlier is that our new list renderer supports language collation as well, so we can define our lists to render in Ascending, Descending or LIST constraint order.

A word of caution here about using list constraints for properties in general, they should only be used to represent a known list of statuses and if you must insist on modifying this list after content has already been created in your repository, be very careful that you only append new options to the list and DO NOT remove existing options as you may well cause existing content with properties set to those now missing values to be invalid and may even cause issue when rendering the property in the UI.

With the previous words of caution fresh in our mind this is how we are going to advocate using our new renderer, to represent a selection of key values.
Using the standard Alfresco LIST constraint approach we would normally do something like the following:

Create a new model file and call it something like test-model.xml to include our new LIST constraint element and our test aspect. Place this file in the directory [tomcat-install]/shared/classes/alfresco/extension/eossonline/models.
<constraints>
  <constraint name="eoss:projectStatus" type="LIST">
            <parameter name="allowedValues">
                <list>
                    <value>Red</value>
                    <value>Yellow</value>
                    <value>Green</value>
                </list>
            </parameter>
       </constraint>
</constraints>
Actually, with our new way of thinking we will change these to be states represented as keys instead. So we would instead do something like the following.
<constraints>
  <constraint name="eoss:projectStatus" type="LIST">
            <parameter name="allowedValues">
                <list>
                    <value>status_red</value>
                    <value>status_yellow</value>
                    <value>status_green</value>
                </list>
            </parameter>
       </constraint>
</constraints>

Lets also create our new aspect with a couple of properties constrained by our LIST
<aspects>
  <aspect name="eoss:projectRelated">
   <title>Project Aspect</title>
   <properties>
    <property name="eoss:status">
     <type>d:text</type>
     <mandatory>true</mandatory>
     <default>status_green</default>
     <constraints>
      <constraint ref="eoss:projectStatus" />
     </constraints>
    </property>
    <property name="eoss:statusAsc">
     <type>d:text</type>
     <mandatory>true</mandatory>
     <default>status_green</default>
     <constraints>
      <constraint ref="eoss:projectStatus" />
     </constraints>
    </property>
    <property name="eoss:statusDesc">
     <type>d:text</type>
     <mandatory>true</mandatory>
     <default>status_green</default>
     <constraints>
      <constraint ref="eoss:projectStatus" />
     </constraints>
    </property>
   </properties>
  </aspect>
 </aspects>
Nothing special here and if left like this these would be the actual values our users would see in the drop down lists, no matter what locale they were logged in as.


As you can see here, we have created an aspect with three properties we will use to test out our new constraints renderer. Obviously nothing here will change the sort orders of the drop down lists or map these keys to values in any resource bundles but the properties have been named according to our intent.
We now need to tell Alfresco that we want to be able to add this aspect to existing content and that we would also like the properties to be displayed and editable. We do this by updating the web-client-config-custom.xml file located in the [tomcat-install]/shared/classes/alfresco/extension directory like so.
<alfresco-config>
	<config evaluator="string-compare" condition="Action Wizards"> 
		<aspects> 
			<aspect name="eoss:projectRelated"/> 
		</aspects> 
	</config>
   
	<config evaluator="aspect-name" condition="eoss:projectRelated">
      	<property-sheet>
         		<show-property name="eoss:statusAsc"/>
         		<show-property name="eoss:statusDesc"/>
         		<show-property name="eoss:status"/>
		</property-sheet>
	</config>
</alfresco-config>

Time for a little gripe me thinks..... Most things in Alfresco are fairly easy to customise in an isolated way. However, the rigid naming and location of this file makes customising Alfresco a pain. It stops me from being able to just unzip my extensions onto an exploded Alfresco instance. Basically, most extensions you come across will want to modify this file and if you unzip multiple extensions then this file will most likely only contain the details needed for the last one you unzipped. I'm not even sure that packaging customisations as AMP modules alleviate this issue either. Anyway, back to the implementation.

We also need to bootstrap our new model component when Alfresco starts up. As the boot strapping is handled by Spring configuration you can pretty much name this file anything you like as long as it end in -context.xml. In our case we will call it eossonline-model-context.xml and put it in the [tomcat-install]/shared/classes/alfresco/extension directory with the following contents.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
   <!--
      EOSSOnline Bootstrap Extension Sequence. This file specifies the
      initialisation (and order of initialisation) to perform during Repository
      startup for beans.
   -->
<beans>
 	<bean id="eossonline.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
		<property name="models">
      		<list>
        <value>alfresco/extension/eossonline/models/test-model.xml</value>
      		</list>
    		</property>
	</bean>
	
	<bean id="eossonline.resourceBundle" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
		<property name="resourceBundles">
			<list>
	<value>alfresco.extension.eossonline.eossonline-messages</value>
			</list>
		</property>
	</bean>

</beans>

Here we declare two beans to be boostrapped at startup time. The bean id's don't actually matter, we just want to make sure that they won't clash with any other bean id's that may be declared else where. The second of these beans allows us to add a resource bundle to the existing resources already loaded into Alfresco, we will use this in a while to define our property labels and more importantly out Internationalised List values.

If I now start up Alfresco we will be able to add our new aspect to existing content in the repository using the Run Action Wizard and once added we will be able to see and edit the properties just like normal.

Lets first take a look at the internationalisation problem. If I log in to Alfresco now using a Spanish locale I get presented with the same list of options as I would as when logging in using an English locale i.e status_red, status_green and status_yellow, I would prefer my Spanish users to be able to select from Roco, Amarillo and Verde and my English users to select from Red, Yellow and Green instead. What I don't want to do is save these internationalised words in the properties because first of all the constraint would fail and I want to use these values in business processes, workflows and rules defined elsewhere in my solution.

Alfresco Explorer uses JSF to define it's UI controls, actually JSF is a standard so technically Alfresco uses the IceFaces JSF implementation to create it's UI controls but lets forget the semantics here and get on with it shall we.
To configure a new Renderer you have to define your renderers and converters in one of two places. Either you can add them to the faces-config-custom.xml in the the exploded Alfresco WEB-INF directory or you can add a faces-config.xml file to the META-INF directory of a jar file. If you choose the first of these options you will be in the same situation as we are in with the web-client-config-custom.xml. Not all changes regarding the faces config can be bundled with your jar file in the META-INF directory but in our case they can. As we are also going to create a couple of java class files we will take the opportunity to package them up into a jar file along with our faces-config.xml file.

This is what our file looks like.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
                              "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
   <!-- ==================== COMPONENT GENERATOR BEANS ==================== -->
   <managed-bean>
      <managed-bean-name>EossAscendingListGenerator</managed-bean-name>
      <managed-bean-class>com.eossonline.alfresco.web.ui.generators.EOSSI18nListGenerator</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      <managed-property>
         <property-name>sortOrder</property-name>
         <value>ASCENDING</value>
      </managed-property>
   </managed-bean>
   
   <managed-bean>
      <managed-bean-name>EossDescendingListGenerator</managed-bean-name>
      <managed-bean-class>com.eossonline.alfresco.web.ui.generators.EOSSI18nListGenerator</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      <managed-property>
         <property-name>sortOrder</property-name>
         <value>DESCENDING</value>
      </managed-property>
   </managed-bean>
   
   <managed-bean>
      <managed-bean-name>EossListGenerator</managed-bean-name>
      <managed-bean-class>com.eossonline.alfresco.web.ui.generators.EOSSI18nListGenerator</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
   </managed-bean>
   
      <!-- ==================== CONVERTERS ==================== -->
   <converter>
      <converter-id>com.eossonline.faces.ResourceConverter</converter-id>
      <converter-class>com.eossonline.alfresco.web.ui.repo.converters.ResourceConverter</converter-class>
   </converter>
</faces-config>
Basically we have created three JSF managed beans with different names and sort orders as well as defined a converter class that will be used by our renderer class. We have also set the scope of these beans to be session scoped so that they only need to be instantiated once per session by the JSF framework. Once the two java classes are written and the class files are packed up into a jar along with this configuration file we we will be in a position where we can tell Alfresco to use these renderers. To do that we will have to modify the web-client-config-custom.xml file we updated earlier, like so.
...	
<config evaluator="aspect-name" condition="eoss:projectRelated">
      <property-sheet>
		<show-property name="eoss:statusAsc" component-generator= "EossAscendingListGenerator"/>
      	<show-property name="eoss:statusDesc" component-generator= "EossDescendingListGenerator"/>
      	<show-property name="eoss:status" component-generator= "EossListGenerator"/>
	</property-sheet>
</config>
...
Notice how we have added the component-generator property to each show-property element. These names match up with the names of the JSF managed beans in the faces-config.xml file we just create.

Were almost done as we just need to write the java code, create our resource files, package up our jar and drop it into our Alfresco WEB-INF\lib directory and restart Alfresco. I'm not going to explain the java code or the packaging of the class files and JSF config into a jar file in this post, you can take a look at the source code and work out what it does and how to create a jar for your self.

But before I list the java source there,s still one thing left to do. We need to create out resource bundle that will give us our internationalised drop down lists.

We already named it alfresco.extension.eossonline.eossonline-messages earlier in out -context.xml bootstrap file. But just to be clear this represents our base bundle which is named eossonline-messages and thus the property file names will be eossonline-messages.properties, for the default language bundle and any internationalised versions will be named eossonline-messages_[languageCode]_[countryCode].properties for example the Spanish version of the translations would live in a file named eossonline-messages_es_ES.properties and they would all live together in the [tomcat-install]/shared/classes/alfresco/extension/eossonline directory.

# Project Aspect properties
# This defines what Alfresco will display for the aspect in the Action Wizard drop down
eoss_filingModel.aspect.eoss_projectRelated.title=Project

# These values will be displayed as the labels of the properties in the UI
eoss_filingModel.property.eoss_status.title=Project Status
eoss_filingModel.property.eoss_statusAsc.title=Project Status Ascending
eoss_filingModel.property.eoss_statusDesc.title=Project Status Descending
# end of Project Aspect properties

# New statuses can be appended to the end of the list.
# The keys here match the entries defined in the model Constraint LIST
status_green=Green
status_yellow=Yellow
status_red=Red
# end of project statuses
OK here's the Java Code and were done.....

package com.eossonline.alfresco.web.ui.generators;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Vector;

import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItems;
import javax.faces.component.UISelectOne;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.generator.BaseComponentGenerator;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.repo.component.property.PropertySheetItem;
import org.alfresco.web.ui.repo.component.property.UIPropertySheet;
import org.springframework.extensions.surf.util.I18NUtil;

import com.eossonline.alfresco.web.ui.repo.converters.ResourceConverter;

public class EOSSI18nListGenerator extends BaseComponentGenerator {

	protected SelectItem[] items = null;

	// This is the default sort order for the list
	protected SortOrder sortOrder = SortOrder.NONE;

	protected Node node;
	
	public EOSSI18nListGenerator() {
	}

	@SuppressWarnings("unchecked")
	public UIComponent generate(FacesContext context, String id) {
	
		UIComponent component = context.getApplication().createComponent(
				UISelectOne.COMPONENT_TYPE);
		FacesHelper.setupComponentId(context, component, id);

		// create the list of choices
		UISelectItems itemsComponent = (UISelectItems) context.getApplication()
				.createComponent("javax.faces.SelectItems");

		itemsComponent.setValue(items);

		// add the items as a child component
		component.getChildren().add(itemsComponent);

		return component;
	}

	@Override
	protected UIComponent createComponent(FacesContext context,
			UIPropertySheet propertySheet, PropertySheetItem item) {
		this.node = propertySheet.getNode();

		return super.createComponent(context, propertySheet, item);
	}

	@Override
	protected void setupConverter(FacesContext context,
			UIPropertySheet propertySheet, PropertySheetItem property,
			PropertyDefinition propertyDef, UIComponent component) {
		
		items = getResourceItems(propertyDef);
		
		createAndSetConverter(context, ResourceConverter.CONVERTER_ID,
				component);
	}

	@Override
	protected void setupMandatoryValidation(FacesContext context,
			UIPropertySheet propertySheet, PropertySheetItem item,
			UIComponent component, boolean realTimeChecking, String idSuffix) {
	}

	protected SelectItem[] getResourceItems(PropertyDefinition propertyDef) {
		if(items != null) {
			return items;
		}
		// First time called, generate the list of options
		
		// Determine sort order
		switch(sortOrder) {
		case ASCENDING:
			getSortOrderAssending(propertyDef);
			break;
		
		case DESCENDING:
			getSortOrderDescending(propertyDef);
			break;
		
		case NONE:
		default:
			getSortOrderNone(propertyDef);
			
		}		
		return items; 
	}
	
	private void getSortOrderAssending(PropertyDefinition propertyDef) {
		List<String> allItems = getListOfValuesConstraint(propertyDef);
		
		// We now have all the possible values that will be used as keys to lookup resources
		SortedMap<String, String> itemsWithValues = new TreeMap<String, String>(new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.compareTo(o2);
			}
		});

		// The problem we now have is that Sorting is naturally done by key and what we want in our case is sorting by value 
		for(String item : allItems) {
			String value = I18NUtil.getMessage(item);
			// If there is no resource matching this key then use the key as the value
			// This will result in a very similar output as already displayed by the standard LIST constraint drop down
			itemsWithValues.put(value == null ? item : value, item);
		}
		// We now have a SortedMap where the values have been used as the keys for sorting reasons
		
		items = new SelectItem[itemsWithValues.size()];
		int i = 0;
		for(String item : itemsWithValues.keySet()) {			
			String value = itemsWithValues.get(item);
			
			// Were now going to create the SelectItem object by flipping the key and value again. 
			// This gives us the output we expected
			items[i++] = new SelectItem(value == null ? item : value, item);
		}
	}

	private void getSortOrderDescending(PropertyDefinition propertyDef) {
		List<String> allItems = getListOfValuesConstraint(propertyDef);
		
		// We now have all the possible values that will be used as keys to lookup resources
		SortedMap<String, String> itemsWithValues = new TreeMap<String, String>(new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o2.compareTo(o1);
			}
		});

		// The problem we now have is that Sorting is naturally done by key and what we want in our case is sorting by value 
		for(String item : allItems) {
			String value = I18NUtil.getMessage(item);
			// If there is no resource matching this key then use the key as the value
			// This will result in a very similar output as already displayed by the standard LIST constraint drop down
			itemsWithValues.put(value == null ? item : value, item);
		}
		// We now have a SortedMap where the values have been used as the keys for sorting reasons
		
		items = new SelectItem[itemsWithValues.size()];
		int i = 0;
		for(String item : itemsWithValues.keySet()) {			
			String value = itemsWithValues.get(item);
			
			// Were now going to create the SelectItem object by flipping the key and value again. 
			// This gives us the output we expected
			items[i++] = new SelectItem(value == null ? item : value, item);
		}
	}

	private void getSortOrderNone(PropertyDefinition propertyDef) {
		Collection<String> allItems = getListOfValuesConstraint(propertyDef);
		
		// As we don't intend to sort this list we are basically done... 
		// so just iterate over the list and create the SelectItem array
		items = new SelectItem[allItems.size()];
		int i = 0;
		for(String item : allItems) {			
			String value = I18NUtil.getMessage(item);
			
			// If there is no resource matching this key then use the key as the value
			// This will result in a very similar output as already displayed by the standard LIST constraint drop down
			items[i++] = new SelectItem(item, value == null ? item : value);
		}
	}
	
	// Let Spring property editors convert from injected String to Enum 
	public void setSortOrder(String sortOrder) {
		if("ascending".compareToIgnoreCase(sortOrder) == 0 ) {
			this.sortOrder = SortOrder.ASCENDING;
		} else if("descending".compareToIgnoreCase(sortOrder) == 0) {
			this.sortOrder = SortOrder.DESCENDING;
		}
	}

    public List<String> getListOfValuesConstraint(PropertyDefinition propertyDef) {

        List<String> lovConstraint = new Vector<String>();

        if (propertyDef != null) {
            // go through the constraints and see if it has any
            // list of values constraint
            List<ConstraintDefinition> constraints = propertyDef.getConstraints();

            for (ConstraintDefinition constraintDef : constraints) {
                Constraint constraint = constraintDef.getConstraint();

                if (constraint instanceof ListOfValuesConstraint) {
                    lovConstraint.addAll(((ListOfValuesConstraint) constraint).getAllowedValues());
                }
            }
        }

        return lovConstraint;
    }
    
	enum SortOrder {
	    NONE, ASCENDING,DESCENDING 
	}	
}

package com.eossonline.alfresco.web.ui.repo.converters;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

import org.springframework.extensions.surf.util.I18NUtil;

public class ResourceConverter implements Converter
{
   /**
    * <p>The standard converter id for this converter.</p>
    */
   public static final String CONVERTER_ID = "com.eossonline.faces.ResourceConverter";

   /**
    * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
    */
   public Object getAsObject(FacesContext context, UIComponent component, String value)
   {   
      if(value == null)
      {
         throw new IllegalArgumentException(I18NUtil.getMessage("error_locale_null"));
      } 
      else
      {
         return value;
      }
   }

   /**
    * @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
    */
   public String getAsString(FacesContext context, UIComponent component, Object value)
   {
      if(value == null)
      {
         throw new IllegalArgumentException(I18NUtil.getMessage("error_locale_null"));
      }
      
      //    if the component's renderer type is  javax.faces.Text, return 
      //    the language label corresponding to the received language code (as string) or the received locale
      else if(component.getRendererType().equalsIgnoreCase("javax.faces.Text"))
      {
    	  String ret = I18NUtil.getMessage((String)value);
    	  if(ret == null) {
    		  ret = (String)value;
    	  }
    	  return ret;
      }
      //    else don't modify 
      else
      {
         return value.toString();
      }                            
   }   
}

Thats all for today folks. We hope you get some millage out of this.

Steven McArdle CTO
On behalf of the eossonline team.

Wednesday, August 17, 2011

A quick update

It's been a while since I lasted posted to this blog but I thought I would just take this opportunity to let you all know that were still here, beavering away at the EOSS platform.

I hope to make posting here a regular part of my work week from now on, not just to keep interested parties informed of our progress but to also use this blog as a medium for storing some of our thoughts and achievements in the weeks and months to come, as well as to document some of the things we have already been working on.

This week were running a small survey and would ask anybody visiting this blog to spare 2 minutes of your precious time to fill it in.

The EOSS Small Business Stack is designed to caters to quite a range of business needs and these different needs will be of more or less interest to different organisations. What we hope to get out of this survey is a better understanding of our priorities driven by your needs.


Steven McArdle CTO
On behalf of the eossonline team.


Thursday, September 23, 2010

What is an Early Adopter?

Recently I blogged that eossonline was actively seeking five “Early Adopters”. As feedback to that blog post I have been asked a few times “What exactly is eossonline looking for in an Early Adopter?”. Well hopefully this blog entry will help explain what were looking for.

There are several sources on the internet that give some pretty good explanations of the term "Early Adopter" but the one I like most is the definition provided by Wikipedia:

Typically this will be a customer who, in addition to using the vendor's product or technology, will also provide considerable and candid feedback to help the vendor refine its future product releases, as well as the associated means of distribution, service, and support.
The relationship is synergistic, with the customer having early (and sometimes unique, or at least uniquely early) access to an advantageous new product or technology.
In exchange for being an early adopter, and thus being exposed to the problems, risks, and annoyances common to early-stage product testing and deployment, the lighthouse customer is given especially attentive vendor assistance and support, even to the point of having personnel at the customer's work site to assist with implementation. The customer is often given preferential pricing, terms, and conditions.” 
 
In our case “preferential pricing terms” means FREE for life, because we want you to be there and actively involved in defining every feature both now and in the future as part of a team. Businesses that are prepared to work with us through all of our teething problems on a day to day basis to help ensure that eossonline meets both of our needs through state-of-the-art application integration. We are not promising to resolve all of your integration and or automation needs, just the areas in which eossonline is being designed to address and you can be an active part of defining these areas.


Our perfect early adopter partners will be businesses employing between 5 and 100 people willing to replace or change their current business infrastructure and or business processes, where necessary, to simplify their day to day administrative tasks and improve their customer engagement through social technologies .
We don't want to change what your business does, we want to work with you to develop an integrated business eco system that will help businesses to work smarter and take full advantage of today's social media capabilities using only the tools and mobile devices you are already familiar with.

So, if you are interested in maximising the way your business engages with people for the better, saving time on mundane, repetitive, administrative tasks and you think you would be a good fit for us, then just send an email to earlyadopter@eossonline.com with a short description of what your business does, why you think we would be a good fit and who we need to contact.


Steven McArdle CTO
On behalf of the eossonline team.

Tuesday, September 14, 2010

Is your business ready for today's tech savvy customer?

The way we do business has changed immeasurably in the last few years and the way customers expect to engage with us is a real game changer.

Are you ready to deal with the world of today's social media? or more to the point, is your business ready to employ the tech savvy Generation Yers?

Web 2.0, iPhones, Blackberries, always connected people and facebook are here to stay. Customers no longer look up phone numbers in the Yellow pages for local tradesman or buy from newspaper advertisements and they don't believe what you say about your products and services any more, it's a fact of life and you need to grasp this with both hands to stay relevant. Today's consumer spends more time on the internet than they do watching TV and social networking sites mean they can get the low down on you and your business, from their trusted network, faster than you can order an espresso. More to the point, they can find out about your competitors as well.

This is how business is done today and this is how your customers expect to interact with you. Successful companies get it, and they have changed the way they engage their customers to fit this model. Generation Yers want it their way or not at all and they are used to getting what they want, when they want.

If your business is not prepared or preparing to deal with these new business models and fully embrace the world of social media you will soon find yourself loosing out to your competition, that is assuming your not already loosing out.

To successfully strike up long term relationships with today's consumers your business needs to work smarter, delivering a true 360 degree view of a customer and that means social CRM and Sales Force Automation need to be at the top of your “to have” business application list.

Monday, September 13, 2010

What is it that you’re looking for from your business applications?

eossonline is building the next generation in "online business applications" and were interested in what it is your business is really after, not what we think you need.

As business owners, there is often a need to wear many hats and use some pretty complicated applications to help you run and manage your business effectively day to day. This often means that you either learn new skills or if you can afford it, hire somebody else to do it for you.

Either way, there is always some associated pain in running your business, be it not enough time in the day to get everything done or the necessity to train up your staff to use that new ERP system you just installed, you know the one, the one that the supplier “guaranteed” would “turn your business around overnight”.

Whatever your particular pain, we are interested in hearing about it.

At eossonline we want to work closely with a few early adopters so that we can together develop the easiest, non-invasive, business application experience, today. Using the latest cutting edge technologies we are going to simplify the way businesses use these applications, so much so that for common use cases you won't even know you’re using them.

If your business is interested in working closely with us to develop this next generation technology please send an email to earlyadopter@eossonline.com giving a few details about your business along with the contact details of the person we need to speak too, and your business could be benefiting from reduced administration and training costs in no time. Best of all, as an early adopter, you’ll never have to pay for the service, ever.

We’re looking forward to working with you on this very exciting, cutting edge, next generation, online business stack so get in touch today.

The eossonline team.