<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>X-Squared On-Demand &#187; X-Squared On Demand</title>
	<atom:link href="http://www.x2od.com/cat/companies/x-squared-on-demand/feed" rel="self" type="application/rss+xml" />
	<link>http://www.x2od.com</link>
	<description>Salesforce Configuration, Administration, and Development</description>
	<lastBuildDate>Fri, 11 Jun 2010 16:30:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>A Mention in the Developers Challenge</title>
		<link>http://www.x2od.com/2009/10/02/a-mention-in-the-developers-challenge.html</link>
		<comments>http://www.x2od.com/2009/10/02/a-mention-in-the-developers-challenge.html#comments</comments>
		<pubDate>Fri, 02 Oct 2009 19:56:51 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[salesforce.com]]></category>
		<category><![CDATA[Apex]]></category>
		<category><![CDATA[Force.com Platform]]></category>
		<category><![CDATA[Sites]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=754</guid>
		<description><![CDATA[The salesforce.com Developer Force Challenge has concluded, and the team of Force Squared and The Enforcer won a mention! Our Daily Shinro site was listed &#8220;for sheer exuberance!&#8221; I&#8217;m really proud of the site, though the lion&#8217;s share of the kudos go to John for the concept and site design. I just coded whatever he [...]]]></description>
			<content:encoded><![CDATA[<p>The salesforce.com <a href="http://blog.sforce.com/sforce/2009/09/developer-force-challenge-results.html">Developer Force Challenge has concluded</a>, and the team of Force Squared and The Enforcer won a mention!</p>
<p>Our <a href="http://www.dailyshinro.com">Daily Shinro</a> site was listed &#8220;for sheer exuberance!&#8221;  </p>
<p>I&#8217;m really proud of the site, though the lion&#8217;s share of the kudos go to John for the concept and site design.  I just coded whatever he told me to code; he&#8217;s the creative one!</p>
<p>So if anyone is looking for a custom Force.com Site or website integration to Salesforce, <a href="/contact">contact us</a> and let&#8217;s discuss your needs!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2009/10/02/a-mention-in-the-developers-challenge.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Overload Apex Class to be Controller AND Extension</title>
		<link>http://www.x2od.com/2009/07/24/overload-apex-class-to-be-controller-and-extension.html</link>
		<comments>http://www.x2od.com/2009/07/24/overload-apex-class-to-be-controller-and-extension.html#comments</comments>
		<pubDate>Fri, 24 Jul 2009 20:01:00 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Visualforce]]></category>
		<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[Eclipse IDE]]></category>
		<category><![CDATA[Force.com Platform]]></category>
		<category><![CDATA[New Features]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=682</guid>
		<description><![CDATA[Coding the new premium version of Mass Update Contacts (details to come), I replaced the two parts of the page with Apex Components. This will allow the app to support custom address fields and international address formats.
I didn't want to write one ControllerExtension for the main page, a CustomController for the view section component, and another CustomController for the pageblocktable component. So here is the overloaded class constructor. Note that this works because an extension passes the StandardController to the constructor, and a CustomController passes nothing:]]></description>
			<content:encoded><![CDATA[<p>Wow - today brought an interesting discovery.  Here's the situation:</p>
<p>Coding the new premium version of Mass Update Contacts (details to come), I replaced the two parts of the page with Apex Components.  This will allow the app to support custom address fields and international address formats.</p>
<p>I didn't want to write one ControllerExtension for the main page, a CustomController for the view section component, and another CustomController for the pageblocktable component.  So here is the overloaded class constructor.  Note that this works because an extension passes the StandardController to the constructor, and a CustomController passes nothing:</p>

<pre class="brush: java;">
public with sharing class VersatileClass {

private Account account;

public VersatileClass(){
	system.debug('OPERATING AS CONTROLLER');
		if(System.currentPageReference().getParameters().get('id')==null){
			//Include error checking here
		} else{
			string AId = System.currentPageReference().getParameters().get('id');
			account = [select id, name from Account where id = :AId];
			//And whatever else you want to do
		}
}

public VersatileClass(ApexPages.StandardController controller) {
	system.debug('OPERATING AS EXTENSION');
		if(System.currentPageReference().getParameters().get('id')==null){
			//Include error checking here
		} else{
			this.account = (Account)controller.getRecord();
			//And whatever else you want to do
		}
	}
}
</pre>
<p>Enjoy!  This should save people a lot of time.</p>]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2009/07/24/overload-apex-class-to-be-controller-and-extension.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Visualforce Email Inbox</title>
		<link>http://www.x2od.com/2009/07/14/visualforce-email-inbox.html</link>
		<comments>http://www.x2od.com/2009/07/14/visualforce-email-inbox.html#comments</comments>
		<pubDate>Tue, 14 Jul 2009 18:00:26 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Visualforce]]></category>
		<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[salesforce.com]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=642</guid>
		<description><![CDATA[Sonny Cloward, SysAd at Rainforest Alliance, approached us about writing a Visualforce page to display all incoming emails for a given Case Queue. This led to quite a few interesting discoveries. Here's how we handled the project:]]></description>
			<content:encoded><![CDATA[<p>Sonny Cloward, SysAd at <a href="http://rainforestalliance.org/">Rainforest Alliance</a>, approached us about writing a Visualforce page to display all incoming emails for a given Case Queue.  This led a few interesting discoveries.  Here's how we handled the (donated time) project:</p>
<p>First, the page was built upon the <a href="http://salesforcesource.blogspot.com/2008/11/adding-sorting-capability-to.html">template Sam Arjimandi built</a> at <a href="http://salesforcesource.blogspot.com">Salesforce<Source></a>.  Instead of the Account object, we substituted the <a href="http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_emailmessage.htm">EmailMessage object</a>.  But something didn't work.  </p>
Fields have certain <a href="http://www.salesforce.com/us/developer/docs/api/Content/access_for_fields.htm">attributes</a>:<br />
            <table cellpadding="4" cellspacing="0" summary="" class="featureTable">
                <thead align="left">
                    <tr>
                        <th class="featureTableHeader" width="25%" id="d9607e40" colspan="1" rowspan="1">Property</th>
                        <th class="featureTableHeader" width="75%" id="d9607e43" colspan="1" rowspan="1">Description</th>
                    </tr>
                </thead>
                <tbody>

                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435186"><a name="i1435186" shape="rect"><!-- --></a>Autonumber</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">The <span>API</span> creates an autonumber.</td>
                    </tr>
                    <tr>

                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435191"><a name="i1435191" shape="rect"><!-- --></a>Create</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Value for the field can be specified during create using the <span>API</span>.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435199"><a name="i1435199" shape="rect"><!-- --></a>Defaulted on create</span>

                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">When created, a default value is supplied if no other value
is specified.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435204"><a name="i1435204" shape="rect"><!-- --></a>Delete</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Value for the field can be deleted using the <span>API</span>.</td>

                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435212"><a name="i1435212" shape="rect"><!-- --></a>Filter</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Can be used as filter criteria in a SOQL query FROM or WHERE
clause.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="access_lookup"><a name="access_lookup" shape="rect"><!-- --></a>idLookup</span>

                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Can be used to specify a record in an <span><a href="sforce_api_calls_upsert.htm" shape="rect"><span><samp class="codeph">upsert()</samp></span></a></span> call. The <span class="fieldName">Id</span> field of each
object has this property and some <span class="fieldName">Name</span> fields. <span>There are exceptions, so check for the property in
any object you wish to <a href="sforce_api_calls_upsert.htm" shape="rect"><span><samp class="codeph">upsert()</samp></span>.</a></span></td>

                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435217"><a name="i1435217" shape="rect"><!-- --></a>Nillable</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">The field can contain a null value.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435222"><a name="i1435222" shape="rect"><!-- --></a>Query</span>

                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">The field can be queried with SOQL using the <span>API</span>.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435230"><a name="i1435230" shape="rect"><!-- --></a>Replicate</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">The value of the field can be replicated using the <span>API</span>.</td>

                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435238"><a name="i1435238" shape="rect"><!-- --></a>Restricted picklist</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">  A picklist that depends on the value of another picklist
for the values it displays.</td>
                    </tr>
                    <tr>

                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435244"><a name="i1435244" shape="rect"><!-- --></a>Retrieve</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Value of the field can be retrieved using the <span>API</span>.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="field_access_search"><a name="field_access_search" shape="rect"><!-- --></a>Search</span>

                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Can be searched with SOSL using the <span>API</span>.</td>
                    </tr>
                    <tr>
                        <td width="25%" headers="d9607e40" colspan="1" rowspan="1"><span id="i1435259"><a name="i1435259" shape="rect"><!-- --></a>Update</span>
                        </td>
                        <td width="75%" headers="d9607e43" colspan="1" rowspan="1">Can be updated using the <span>API</span>.</td>

                    </tr>
                </tbody>
            </table>
<p>The important one here is "Filter" because (as the documentation states) this allows the field to be used in a WHERE clause.  Also, however, (as the documentation does not state) it allows the field to be used in an ORDER BY clause.  So all fields on the EmailMessage object that do not allow filtering/ordering had to be presented plainly, without Sam's cool PageBlockTable sorting features.
Once this was done, Sonny had some great ideas:</p>
<ol>
	<li>Show the email subject, but make that a hyperlink to the email message itself</li>
	<li>Link the Case Number (EmailMessage.ParentId) to the Case (EmailMessage.Parent)</li>
	<li>Show the Case Contact (EmailMessage.Parent.Contact.Name), linking to the Contact (EmailMessage.Parent.ContactId)</li>
	<li>Show the Case Account (EmailMessage.Parent.Account.Name), linking to the Account (EmailMessage.Parent.AccountId)</li>
	<li>Provide filters - Incoming only, Unread only, etc.</li>
</ol>
You'll see in the Apex Code where we added parent object fields to the SOQL query, and where we used a List<SelectOption> to populate the query's filter.  
<pre class="brush: java;">
public with sharing class EmailMessageController {
   public String EmailMessage { get; set; }
   private List&lt;EmailMessage&gt; messages;
   private String sortDirection = 'ASC';
   private String sortExp = 'MessageDate';
   public String wheretext;

   public EmailMessageController(){
   	wheretext = '';
   }

   public String sortExpression { get {
        return sortExp;
     }
     set {
       //if the column is clicked on then switch between Ascending and Descending modes
       if (value == sortExp)
         sortDirection = (sortDirection == 'ASC')? 'DESC' : 'ASC';
       else
         sortDirection = 'ASC';
       sortExp = value;
     }
   }
   
public void setWhereText(String value) {  
   whereText = value;
 }
public string getWhereText(){
	return wheretext;
}
   
public List&lt;SelectOption&gt; getViews(){
	List&lt;SelectOption&gt; options = new List&lt;SelectOption&gt;();
	options.add(new SelectOption('WHERE e.id != null','All'));
	options.add(new SelectOption('WHERE e.Incoming = true AND e.Status = \'0\' ','Incoming Unread'));
	options.add(new SelectOption('WHERE e.Incoming = true AND e.Status = \'1\' ','Incoming Read'));
        options.add(new SelectOption('WHERE e.Incoming = true','All Incoming'));
        options.add(new SelectOption('WHERE e.Incoming = false','All Outgoing'));
        options.add(new SelectOption('WHERE e.ToAddress = \'support@x2od.com\'','Support Queue'));
        options.add(new SelectOption('WHERE e.ToAddress = \'support2@x2od.com\'','Support Queue2')); //etc.
        return options;
}

 public String getSortDirection() {
    //if not column is selected 
    if (sortExpression == null || sortExpression == '')
      return 'ASC';
    else
     return sortDirection;
 }

 public void setSortDirection(String value) {  
   sortDirection = value;
 }
  
   public List&lt;EmailMessage&gt; getMessages() {
       return messages;
   }
   
   public PageReference ViewData() {
       //build the full sort expression
       string sortFullExp = sortExpression  + ' ' + sortDirection;
      
       //query the database based on the sort expression
       messages = Database.query('Select e.FromAddress, e.Parent.ContactId, e.Parent.Contact.Name, e.Parent.Account.Name, e.ToAddress, e.Parent.CaseNumber, e.Parent.AccountId, e.TextBody, e.SystemModstamp, e.Subject, e.Status, e.ParentId, e.MessageDate, e.LastModifiedDate, e.LastModifiedById, e.IsDeleted, e.Incoming, e.Id, e.HtmlBody, e.Headers, e.HasAttachment, e.FromName, e.CreatedDate, e.CreatedById, e.CcAddress, e.BccAddress, e.ActivityId From EmailMessage e ' + wheretext + ' order by ' + sortFullExp + ' limit 1000');
       return null;
   }
}
</pre>
<p>And here's the Visualforce Page:</p>
<pre class="brush: xml;">
&lt;apex:page controller=&quot;EmailMessageController&quot; action=&quot;{!ViewData}&quot;&gt;
	&lt;apex:sectionHeader title=&quot;Email Messages&quot; subtitle=&quot;&quot;&gt;&lt;/apex:sectionHeader&gt;
	&lt;apex:pageblock id=&quot;emailblock&quot;&gt;
		&lt;apex:facet name=&quot;header&quot;&gt;
			&lt;apex:form&gt;
				&lt;apex:panelGrid styleClass=&quot;list&quot;
					columnClasses=&quot;pbTitle,pbButton,pbHelp&quot; columns=&quot;3&quot; border=&quot;0&quot;
					cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;
					&lt;apex:outputLabel&gt;&lt;h3&gt;Messages&lt;/h3&gt;&lt;/apex:outputLabel&gt;
					&lt;apex:commandButton value=&quot; Refresh &quot; styleClass=&quot;btn&quot;
						action=&quot;{!ViewData}&quot; rerender=&quot;emailblock&quot;&gt;&lt;/apex:commandButton&gt;
					&lt;apex:SelectList value=&quot;{!wheretext}&quot; size=&quot;1&quot;	id=&quot;controllerselectlist&quot;&gt;
						&lt;apex:actionSupport event=&quot;onchange&quot; action=&quot;{!ViewData}&quot;
							reRender=&quot;emailblock&quot;&gt;&lt;/apex:actionSupport&gt;
						&lt;apex:selectOptions value=&quot;{!views}&quot; /&gt;
					&lt;/apex:SelectList&gt;
				&lt;/apex:panelGrid&gt;
			&lt;/apex:form&gt;
		&lt;/apex:facet&gt;
		&lt;apex:form&gt;
			&lt;apex:pageblocktable value=&quot;{!Messages}&quot; var=&quot;e&quot; id=&quot;emailtable&quot;
				bgcolor=&quot;#F3F3EC&quot; styleClass=&quot;list&quot; rowClasses=&quot;dataRow&quot;
				onRowMouseOver=&quot;hiOn(this);&quot; onRowMouseOut=&quot;hiOff(this);&quot;&gt;
				&lt;apex:column&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.Subject.label}{!IF(sortExpression=='Subject', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;Subject&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
					&lt;apex:outputLink value=&quot;/{!e.Id}&quot; target=&quot;_blank&quot;&gt;{!e.Subject}&lt;/apex:outputLink&gt;
				&lt;/apex:column&gt;
				&lt;apex:column&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
					{!$ObjectType.Contact.fields.Name.label}
					&lt;/apex:facet&gt;
					&lt;apex:outputLink value=&quot;/{!e.Parent.ContactId}&quot; target=&quot;_blank&quot;
						rendered=&quot;{!IF(e.Parent.ContactId != '',true,false)}&quot;&gt;{!e.FromName}&lt;/apex:outputLink&gt;
					&lt;apex:outputtext value=&quot;{!e.FromName}&quot;
						rendered=&quot;{!IF(e.Parent.ContactId != '',false,true)}&quot; /&gt;
				&lt;/apex:column&gt;
				&lt;apex:column&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
					{!$ObjectType.Account.fields.Name.label}
					&lt;/apex:facet&gt;
					&lt;apex:outputLink value=&quot;/{!e.Parent.AccountId}&quot; target=&quot;_blank&quot;&gt;{!e.Parent.Account.Name}&lt;/apex:outputLink&gt;
				&lt;/apex:column&gt;
				&lt;apex:column value=&quot;{!e.FromAddress}&quot;&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.FromAddress.label}{!IF(sortExpression=='FromAddress', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;FromAddress&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
				&lt;/apex:column&gt;
				&lt;apex:column value=&quot;{!e.Status}&quot;&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.Status.label}{!IF(sortExpression=='Status', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;Status&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
				&lt;/apex:column&gt;
				&lt;apex:column value=&quot;{!e.MessageDate}&quot;&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.MessageDate.label}{!IF(sortExpression=='MessageDate', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;MessageDate&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
				&lt;/apex:column&gt;
				&lt;apex:column value=&quot;{!e.Incoming}&quot;&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.Incoming.label}{!IF(sortExpression=='Incoming', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;Incoming&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
				&lt;/apex:column&gt;
				&lt;apex:column value=&quot;{!e.HasAttachment}&quot;&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.HasAttachment.label}{!IF(sortExpression=='HasAttachment', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;HasAttachment&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
				&lt;/apex:column&gt;
				&lt;apex:column&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.Case.fields.CaseNumber.label}{!IF(sortExpression=='ParentId', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;ParentId&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
					&lt;apex:outputLink value=&quot;/{!e.ParentId}&quot;&gt;{!e.Parent.CaseNumber}&lt;/apex:outputLink&gt;

				&lt;/apex:column&gt;
				&lt;apex:column value=&quot;{!e.ToAddress}&quot;&gt;
					&lt;apex:facet name=&quot;header&quot;&gt;
						&lt;apex:commandLink action=&quot;{!ViewData}&quot;
							value=&quot;{!$ObjectType.EmailMessage.fields.ToAddress.label}{!IF(sortExpression=='ToAddress', 
							IF(sortDirection='ASC','▼','▲'),'')}&quot;&gt;
							&lt;apex:param value=&quot;ToAddress&quot; name=&quot;column&quot;
								assignTo=&quot;{!sortExpression}&quot;&gt;&lt;/apex:param&gt;
						&lt;/apex:commandLink&gt;
					&lt;/apex:facet&gt;
				&lt;/apex:column&gt;
			&lt;/apex:pageblocktable&gt;
		&lt;/apex:form&gt;
	&lt;/apex:pageblock&gt;
&lt;/apex:page&gt;
</pre>
<p>There are some other cool bits: </p>
<p>If there is no Case.Contact, the table will display the FromName, pulled from the email message.</p>
<p>An interesting point: You may notice that EmailStatus is presented in numerical form.  For instance, Incoming Unread is 0, Incoming Read is 1, etc.  The documentation, however, says, "Read only. The status of the email. For example, “New,” “Unread,” “Replied,” “Sent.”"  So we're not sure of the exact mapping.  3 seems to be Sent, so 2 is probably Replied... but we're not sure.</p>
<p>Don't forget: EmailMessage has two lookups (foreign key): Case, and Activity.  This Activity is the task created when Salesforce receives the email, and is - according to the documentation - assigned to the Case Owner.  We're not sure what happens when the Case is owned by a Queue.  Feel free to comment and share your experiences.</p>
<p>
That's it!  Enjoy.</p>]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2009/07/14/visualforce-email-inbox.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>X-Squared featured in Inc.com article on drop.io</title>
		<link>http://www.x2od.com/2009/03/19/inccom-dropio-article.html</link>
		<comments>http://www.x2od.com/2009/03/19/inccom-dropio-article.html#comments</comments>
		<pubDate>Thu, 19 Mar 2009 19:51:22 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=406</guid>
		<description><![CDATA[Howard Greenstein of Inc.com published a story today(”Stop, Collaborate, and Listen“) on drop.io and asked us to comment on how drop.io can help SMBs in service delivery.]]></description>
			<content:encoded><![CDATA[<p>Those who follow us on <a href="http://www.twitter.com">Twitter</a> know that <a href="http://drop.io">drop.io</a> is one of our favorite tools.  We use it to collaborate with clients, to send files without taking up valuable inbox space (companies have been known to enforce miniscule Exchange inbox sizes), and even to share music playlists.<br />
<a href="http://blog.inc.com/start-up/howard_greenstein/">Howard Greenstein</a> of <a href="http://www.inc.com/">Inc.com</a> published a story today(&#8220;<strong><a href="http://blog.inc.com/start-up/2009/03/stop_collaborate_and_listen_1.html">Stop, Collaborate, and Listen</a></strong>&#8220;) on drop.io and asked David to comment on how drop.io can help SMBs in service delivery.<br />
It&#8217;s a good story that outlines the more basic features that drop.io offers.  There is so much more available, both through the front-end and via drop.io&#8217;s <a href="http://api.drop.io">RESTful API</a>.  In fact, David has been working on a Salesforce-drop.io integration that will allow inexpensive file storage and selective file-sharing with clients.<br />
Please read <strong><a href="http://blog.inc.com/start-up/2009/03/stop_collaborate_and_listen_1.html">Howard&#8217;s story</a></strong> and give <a href="http://drop.io">drop.io</a> a shot &#8211; you&#8217;ll enjoy it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2009/03/19/inccom-dropio-article.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>X-Squared Featured in ITA Newsletter</title>
		<link>http://www.x2od.com/2008/12/08/x-squared-featured-in-ita-newsletter.html</link>
		<comments>http://www.x2od.com/2008/12/08/x-squared-featured-in-ita-newsletter.html#comments</comments>
		<pubDate>Mon, 08 Dec 2008 22:15:00 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[X-Squared On Demand]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=288</guid>
		<description><![CDATA[This week, X-Squared On Demand was featured in the Illinois Technology Association&#8216;s Industry Weekly newsletter ITA Member Q&#038;A. Thank you to the ITA for featuring us!]]></description>
			<content:encoded><![CDATA[<p>This week, <a href="https://www.illinoistech.org/technologynews.aspx/1735">X-Squared On Demand</a> was featured in the <a href="http://www.illinoistech.org">Illinois Technology Association</a>&#8216;s Industry Weekly newsletter ITA Member Q&#038;A.  </p>
<p>Thank you to the ITA for featuring us!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2008/12/08/x-squared-featured-in-ita-newsletter.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Project: Change Owner Button in Visualforce</title>
		<link>http://www.x2od.com/2008/11/13/project-change-owner-button-in-visualforce.html</link>
		<comments>http://www.x2od.com/2008/11/13/project-change-owner-button-in-visualforce.html#comments</comments>
		<pubDate>Thu, 13 Nov 2008 06:13:15 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Visualforce]]></category>
		<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[salesforce.com]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=244</guid>
		<description><![CDATA[Drawing upon some code I found in the Developers Guide, I have written a Visualforce page to mass-change the owner of all selected records to any active User in Salesforce.  Yes, it only works with Contacts for now, but my next step will be to use Dynamic Apex to pass the sObject name to the page and its extension/controller, allowing me to reuse one bit of code for multiple objects.  We'll see how it goes.  But in the meantime, enjoy this page that lets you perform a search, check which records you want to transfer, and then input a User.  I've tested it with 50 records at once, so that should suffice for most uses.]]></description>
			<content:encoded><![CDATA[<p>Salesforce Labs has put out a series of Mass Action packages on the AppExchange.  There is <a href="https://www.salesforce.com/appexchange/detail_overview.jsp?NavCode__c=&#038;id=a0330000000iAkcAAE">Mass Transfer Opportunity Owner</a> (uses AJAX), <a href="http://www.salesforce.com/appexchange/detail_overview.jsp?NavCode__c=&#038;id=a0330000000iIEtAAM">Mass Update Contact Addresses</a> (AJAX), <a href="http://www.salesforce.com/appexchange/detail_overview.jsp?NavCode__c=&#038;id=a0330000000iAkcAAE">Mass Update Opportunity Owner</a>, <a href="https://www.salesforce.com/appexchange/detail_overview.jsp?NavCode__c=&#038;id=a0330000000iIAxAAM">Mass Update Opportunity Close Dates</a>, etc.  All of these are &#8220;thick client&#8221; tools, meaning that data must be loaded onto your computer, altered, and then uploaded back to Salesforce.  </p>
<p><a href="http://community.salesforce.com/sforce/tracker?user.id=198">Ron Hess</a> released a super bit of code, found in the Visualforce documentation and elsewhere, to <a href="http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_sosc_custom_button.htm">Mass Update Opportunity Stage and Close Date</a>.  It could, theoretically, be expanded to other fields as well.  This got me thinking about doing so with other objects.  </p>
<p>A while ago, I took the code for the <a href="http://www.salesforce.com/appexchange/detail_overview.jsp?NavCode__c=&#038;id=a03300000033CsnAAE">Mass Delete</a> button and altered it to change the owner of the selected records to the User clicking the button.  It was like an Accept button, but I could use it for any object.  Actually, it wasn&#8217;t as easy as that.  I had to make one button for each object, and maintenance was a pain&#8211;whenever I created a new object, I needed to clone my code.</p>
<p>Drawing upon some code I found in the <a href="http://wiki.apexdevnet.com/index.php/force_library">Developers Guide</a>, I have written a Visualforce page to mass-change the owner of all selected records to any active User in Salesforce.  Yes, it only works with Contacts for now, but my next step will be to use Dynamic Apex to pass the sObject name to the page and its extension/controller, allowing me to reuse one bit of code for multiple objects.  We&#8217;ll see how it goes.  But in the meantime, enjoy this page that lets you perform a search, check which records you want to transfer, and then input a User.  I&#8217;ve tested it with 50 records at once, so that should suffice for most uses.</p>
<p><strong>VF Page:</strong><br />
<pre class="brush: xml;">&lt;br /&gt;
&lt;apex:page standardController=&quot;Contact&quot; recordSetVar=&quot;Contacts&quot; id=&quot;updateOwnerPage&quot;&gt;&lt;br /&gt;
&lt;apex:form&gt;&lt;br /&gt;
&lt;apex:sectionHeader title=&quot;Change Owner for Contacts&quot;/&gt;&lt;br /&gt;
&lt;apex:pageBlock mode=&quot;edit&quot;&gt;&lt;br /&gt;
&lt;apex:pageMessages /&gt;&lt;br /&gt;
&lt;apex:pageblockSection title=&quot;Change&quot; columns=&quot;1&quot;&gt;&lt;br /&gt;
&lt;apex:pageblockSectionItem &gt;&lt;br /&gt;
&lt;apex:outputLabel for=&quot;owner&quot;&gt;New Owner&lt;/apex:outputLabel&gt;&lt;br /&gt;
&lt;apex:inputField id=&quot;owner&quot; value=&quot;{!Contact.OwnerId}&quot;/&gt;&lt;br /&gt;
&lt;/apex:pageblockSectionItem&gt;&lt;br /&gt;
&lt;/apex:pageBlockSection&gt;&lt;br /&gt;
&lt;apex:pageBlockSection title=&quot;Selected Contacts&quot; columns=&quot;1&quot;&gt;&lt;br /&gt;
&lt;apex:pageBlockTable value=&quot;{!selected}&quot; var=&quot;j&quot; bgcolor=&quot;#F3F3EC&quot; width=&quot;100%&quot;&lt;br /&gt;
styleClass=&amp;#8221;list&amp;#8221; rowClasses=&amp;#8221;dataRow&amp;#8221; onRowMouseOver=&amp;#8221;hiOn(this);&amp;#8221; onRowMouseOut=&amp;#8221;hiOff(this);&amp;#8221;&gt;&lt;br /&gt;
&lt;apex:column &gt;&lt;br /&gt;
&lt;apex:facet name=&quot;header&quot;&gt;Contact Name&lt;/apex:facet&gt;&lt;br /&gt;
&lt;apex:outputLink value=&quot;{!URLFOR($Action.Contact.View, j.id)}&quot;&gt;&lt;br /&gt;
{!j.FirstName} {!j.LastName}&lt;/apex:outputLink&gt;&lt;br /&gt;
&lt;/apex:column&gt;&lt;br /&gt;
&lt;apex:column &gt;&lt;br /&gt;
&lt;apex:facet name=&quot;header&quot;&gt;Account Name&lt;/apex:facet&gt;&lt;br /&gt;
&lt;apex:outputLink value=&quot;{!URLFOR($Action.Account.View, j.Account.id)}&quot;&gt;&lt;br /&gt;
{!j.Account.Name}&lt;/apex:outputLink&gt;&lt;br /&gt;
&lt;/apex:column&gt;&lt;br /&gt;
&lt;apex:column&gt;&lt;br /&gt;
&lt;apex:facet name=&quot;header&quot;&gt;Current Owner&lt;/apex:facet&gt;&lt;br /&gt;
{!j.Owner.Name}&lt;br /&gt;
&lt;/apex:column&gt;&lt;br /&gt;
&lt;/apex:pageBlockTable&gt;&lt;br /&gt;
&lt;/apex:pageblockSection&gt;&lt;br /&gt;
&lt;apex:pageBlockButtons location=&quot;bottom&quot;&gt;&lt;br /&gt;
&lt;apex:commandButton value=&quot;Save&quot; action=&quot;{!save}&quot;/&gt;&lt;br /&gt;
&lt;apex:commandButton value=&quot;Cancel&quot; action=&quot;{!cancel}&quot;/&gt;&lt;br /&gt;
&lt;/apex:pageBlockButtons&gt;&lt;br /&gt;
&lt;/apex:pageBlock&gt;&lt;br /&gt;
&lt;/apex:form&gt;&lt;br /&gt;
&lt;/apex:page&gt;&lt;br /&gt;
</pre></p>
<p><strong>Button:</strong><br />
Go to Setup -> Contact -> Buttons and Links<br />
Create a new button, set it to execute in the current window with sidebar and header, and set it to call a Visualforce page.  Select the page you just created.  Then add the button to Contact Search Layout and to any Contact related lists you like.</p>
<p>Voila!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2008/11/13/project-change-owner-button-in-visualforce.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upcoming Plans</title>
		<link>http://www.x2od.com/2008/11/09/upcoming-plans.html</link>
		<comments>http://www.x2od.com/2008/11/09/upcoming-plans.html#comments</comments>
		<pubDate>Sun, 09 Nov 2008 08:03:50 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[Force.com Platform]]></category>
		<category><![CDATA[New Developments]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=227</guid>
		<description><![CDATA[This blog post is partly an announcement of X-Squared’s upcoming plans and projects, and partly a way to hold myself to my list. It is said that while managing the Yankees, Joe Torre tried to quit many times, until someone bet him $1000 that he couldn’t quit… and told everyone he knew about the bet. Clearly, $1000 is small change to Torre, but the pressure of the whole world knowing his plan to quit helped him quite a bit. So here is X-Squared On Demand’s list of projects and plans (outside of the standard billing work for our amazing clients):]]></description>
			<content:encoded><![CDATA[<p>This is my first blog post since Dreamforce 2008, and I had an amazing time.  Hello to everyone I met, and hello to all the people that I said I&#8217;d meet &#8211; but couldn&#8217;t.  I left Dreamforce and came to Sydney to visit my family, and am writing this blog post sitting on a deck chair under a setting sun, listening to my niece and nephew play nicely.</p>
<p>This blog post is partly an announcement of X-Squared&#8217;s upcoming plans and projects, and partly a way to hold myself to my word.  It is said that while managing the Yankees, Joe Torre tried to quit many times, until someone bet him $1000 that he couldn&#8217;t quit&#8230; and told everyone he knew about the bet.  Clearly, $1000 is small change to Torre, but the pressure of the whole world knowing his plan to quit helped him quite a bit.  So here is X-Squared On Demand&#8217;s list of projects and plans (outside of the standard billing work for our amazing clients):</p>
<p><a href="http://twitter.com/jonmountjoy">Jon Mountjoy</a> suggested that I pick one Salesforce development feature and learn it completely instead of making the mistake of trying to learn everything and doing it all poorly.  I chose <a href="http://wiki.apexdevnet.com/index.php/Visualforce">Visualforce</a>.  All my side projects from now on will involve Visualforce to some degree.</p>
<ul>
<li><strong>Lookup to Picklist</strong>: I&#8217;ve always been interested in lookup fields and have written some interesting implementations that use error messages and custom buttons to simplify and focus allowed values for lookups.  Here, I plan to present the user with a list of all the target records available and to present them in a picklist.  (Of course, if there are more than 50 records, I will leave the field as a lookup.)</li>
<li><strong>Filtered Lookup</strong>: I have the code for a filtered lookup that utilizes a three-page wizard to choose the proper record for a lookup, but I want to simplify this to allow an administrator to limit a lookup to one Record Type or any other hard-coded filter.  Then I&#8217;ll use a simplified wizard to enhance that feature, which would basically be like using the lookup filters in Enhanced Lookups currently available in the standard UI.</li>
<li><strong>NonProfit EventForce using Google Sites</strong>: We started this project at Dreamforce 2008, and I have a non-profit client who would like a tool to allow registration for various kinds of events.  This is a super opportunity to expand upon this hackathon project.  <a href="http://colinloretz.com/">Colin Loretz</a> has agreed to help on this, and Steve Wright of Salesforce.com Foundation has offered to provide a salesforce.com technical resource if we make the code open-source.  I told Steve that in my mind I was writing the code for the Foundation, and that the Foundation could do whatever it wanted with the code.  So keep an eye out for this in the next month or two.</li>
<li><strong>Airport Codes to Full Name</strong> of the airport when entered into a field, using Visualforce.</li>
<li><strong>SIC to NAICS</strong>: I have NO idea why Salesforce CRM is so attached to SIC codes&#8211;after all, the government has completed its changeover to NAICS codes.  I plan to use the existing conversion charts provided by the government to allow orgs to convert their data from SIC to NAICS.</li>
<li><strong>Google Maps as a Data Enrichment Tool</strong>: Input the ZIP Code, and Google Maps will return a city/state.  Or input the Street and City/State, and Google Maps will return the ZIP Code.  Sorry, DemandTools and Postcode Anywhere, this might cut into your profit margin.</li>
<li><strong>Drop.io for AppExchange</strong>: I love <a href="http://drop.io">drop.io</a> as a file sharing and storage tool, and with the release of their API&#8211;and Ron Hess&#8217;s explanation of his XMLDom Apex Class, it may be time to create a nice app allowing 100MB of storage per record in Salesforce CRM.  It might require a couple of hacks before it can be used for more than standard objects, but this will likely be my ongoing work in progress.</li>
<li>Use <strong>Amazon EC2 Windows</strong> to put the <a href="http://wiki.apexdevnet.com/index.php/Workbench">Workbench</a> in the Cloud.</li>
<li>And finally, I will spend the next year making a list of everyone I want to meet at Dreamforce 2009, and will find a way to see everyone there!</li>
</ul>
<p>There are probably many more ideas sketched on napkins and pads of paper around my office, but this is a beginning list of projects I&#8217;m most passionate about.  If anyone would like to help with any, please let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2008/11/09/upcoming-plans.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>X-Squared at Dreamforce 2008</title>
		<link>http://www.x2od.com/2008/10/28/x-squared-at-dreamforce-2008.html</link>
		<comments>http://www.x2od.com/2008/10/28/x-squared-at-dreamforce-2008.html#comments</comments>
		<pubDate>Wed, 29 Oct 2008 01:38:10 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[salesforce.com]]></category>
		<category><![CDATA[Dreamforce]]></category>
		<category><![CDATA[New Developments]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=224</guid>
		<description><![CDATA[Please be sure to register for sessions at Dreamforce. And DEFINITELY don&#8217;t miss my session! Wrangle Data &#038; Pump up the Configuration “I’m administering Salesforce. I’ve learned the ropes. Now I want to get great!” In this session, we’ll review the latest insights and subtlties that top Salesforce consultants have learned on the front lines. [...]]]></description>
			<content:encoded><![CDATA[<p>Please be sure to <a href="https://dreamforcereg.force.com/">register</a> for sessions at <a href="http://www.dreamforce.com">Dreamforce</a>.  </p>
<p>And DEFINITELY don&#8217;t miss my session!</p>
<p><strong>Wrangle Data &#038; Pump up the Configuration</strong><br />
“I’m administering Salesforce. I’ve learned the ropes. Now I want to get great!” In this session, we’ll review the latest insights and subtlties that top Salesforce consultants have learned on the front lines. We’ll focus on data and configuration to help cut the time you spend massaging data. You&#8217;ll also learn how to implement tricky config quirks you never thought possible.<br />
Speaker: Ezra Kenigsberg, SALESFORCE.COM<br />
Speaker: David Schach, X-Squared On Demand LLC<br />
Date: Monday, November 3<br />
Time: 11:45 a.m. &#8211; 12:45 p.m.</p>
<p>I&#8217;m on the Administrator track &#8211; we&#8217;ll be providing tips for configuring your org implementation and optimizations, and for ensuring that things remain smooth as you move forward as a Super Administrator.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2008/10/28/x-squared-at-dreamforce-2008.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zipcar: CaaS (Car as a Service)</title>
		<link>http://www.x2od.com/2008/08/13/zipcar-caas-car-as-a-service.html</link>
		<comments>http://www.x2od.com/2008/08/13/zipcar-caas-car-as-a-service.html#comments</comments>
		<pubDate>Wed, 13 Aug 2008 17:00:53 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[Companies]]></category>
		<category><![CDATA[X-Squared On Demand]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=94</guid>
		<description><![CDATA[A few weeks ago, I went on a Low Car Diet.  No, I didn’t come up with the name; it’s the invention of Zipcar, a growing company with a product that, in these times of rising gas prices, is not only filling a growing demand, but is creating a market for its service.
After speaking to some people at <a href="http://www.zipcar.com">Zipcar</a>, and having rented cars a few times, I have come to realize the following:
In this age of Web 2.0 (and, <a href="http://www.techcrunchit.com/2008/08/01/welcome-to-web-30-now-your-other-computer-is-a-data-center/">according to some</a>, Web 3.0), when Software as a Service is growing faster than ever, the on-demand model can be applied to other sectors, creating, for instance, Car as a Service.
<strong>OWN NOTHING</strong>
Ask anyone who drank the Software-as-a-Service Kool-Aid about in-house servers and you’ll be greeted with a face that looks like someone just took a bite out of a lemon, peel and all.  In today’s quickly-evolving Information Technology world, ownership is nothing; rental is everything.  How much does it cost to own a file server (including hardware, electricity, air conditioning, salaries for the in-house geeks, space that can’t be used for an office refrigerator, and more) per year?  Compare that to the cost of storing files on Amazon Web Services!  Compare purchasing a VPN appliance to the monthly cost of certificate-based Single Sign-On products like MyOneLogin by TriCipher.  Pooling capital costs and being charged only for what we use is the new model.  I don’t want to have to buy a 1TB NAS drive, and then to worry about if it is filling up; I’d rather pay per GB for shared storage, where my information is just as private, and arguably more accessible while being more secure (since nobody can walk into my office and steal my drives).  
Cloud Computing is where it’s at.  This is the solution to problems caused by using in-house systems and desktop applications inaccessible from any computer outside the office.  And Cloud Driving seems to be just as viable a solution to the headache of owning a car and paying for gas, insurance, parking, and maintenance.
Let’s compare Salesforce, the top on-demand software application created by <a href="http://www.salesforce.com">salesforce.com</a> to Zipcar, a leading on-demand driving service created by, well, Zipcar.  ]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago, I went on a Low Car Diet.  No, I didn’t come up with the name; it’s the invention of Zipcar, a growing company with a product that, in these times of rising gas prices, is not only filling a growing demand, but is creating a market for its service.<br />
After speaking to some people at <a href="http://www.zipcar.com">Zipcar</a>, and having rented cars a few times, I have come to realize the following:<br />
In this age of Web 2.0 (and, <a href="http://www.techcrunchit.com/2008/08/01/welcome-to-web-30-now-your-other-computer-is-a-data-center/">according to some</a>, Web 3.0), when Software as a Service is growing faster than ever, the on-demand model can be applied to other sectors, creating, for instance, Car as a Service.<br />
<strong>OWN NOTHING</strong><br />
Ask anyone who drank the Software-as-a-Service Kool-Aid about in-house servers and you’ll be greeted with a face that looks like someone just took a bite out of a lemon, peel and all.  In today’s quickly-evolving Information Technology world, ownership is nothing; rental is everything.  How much does it cost to own a file server (including hardware, electricity, air conditioning, salaries for the in-house geeks, space that can’t be used for an office refrigerator, and more) per year?  Compare that to the cost of storing files on Amazon Web Services!  Compare purchasing a VPN appliance to the monthly cost of certificate-based Single Sign-On products like MyOneLogin by TriCipher.  Pooling capital costs and being charged only for what we use is the new model.  I don’t want to have to buy a 1TB NAS drive, and then to worry about if it is filling up; I’d rather pay per GB for shared storage, where my information is just as private, and arguably more accessible while being more secure (since nobody can walk into my office and steal my drives).<br />
Cloud Computing is where it’s at.  This is the solution to problems caused by using in-house systems and desktop applications inaccessible from any computer outside the office.  And Cloud Driving seems to be just as viable a solution to the headache of owning a car and paying for gas, insurance, parking, and maintenance.<br />
Let’s compare Salesforce, the top on-demand software application created by <a href="http://www.salesforce.com">salesforce.com</a> to Zipcar, a leading on-demand driving service created by, well, Zipcar.<span id="more-94"></span><br />
<strong>MULTI-TENANCY</strong><br />
Any time multiple users are sharing the same system without actually interacting with each other, and especially when they all have access to pooled services but can exist without knowing who their neighbors are, that fits the model of multi-tenancy.  I liken it to living in an apartment building with a gym.  My assessments pay for elevators, lighting, carpeting, and a doorman.  People can pay extra for upgrades such as the gym or the pool.  I may never meet most of my neighbors, but they’re there.  We may never work out at the same time, but we’re all using the gym.  We may all know that the doorman’s name is Jim (mornings) or Calvin (afternoons), but we may never pass before him at the same time.<br />
The same concept applies to Zipcar.  I can rent a Volvo, Mini, Volkswagen, Mazda, Ford, Subaru, BMW, and more.  There’s even a Mustang Convertible 1.5 miles away, easy accessible by bus.  I will likely never run into anyone else renting the car next to mine, though I might because they have as many as eight cars in a single lot near me, and one is a BMW that I’m dying to take out.  Every car (not model… every CAR) has a name, which makes renting “Shannon” a bit awkward, but that’s just part of the shtick.<br />
So we’re all sharing amenities, each existing in our own world, paying for basic services in our yearly and hourly fees.  What I do in the car when I’m driving it is my business, as long as I follow the six rules: Report damage, Clean up after myself, Leave at least 1/4 tank, Don’t smoke, Return the car on time, and Keep pets in a carrier.  Sounds pretty easy.<br />
As long as I follow the rules, I can do whatever I want.  Salesforce or a company’s System Administrator can set rules as well, including storage limits, IP address restrictions, security permissions, and more.<br />
<strong>ON-DEMAND</strong><br />
Zipcar is on-demand.  When you want to rent a car, just go to the website and reserve a car.  You can also call their hotline to make a reservation in a snap!  Sure, it’s possible that every car under a mile away is unavailable, but as the provider makes system upgrades, system capacity will increase.  Sounds just like upgrading a server (or allowing more API calls like, ahem, Twitter should).<br />
With reservations available from any web browser or telephone, Zipcar’s availability actually exceeds that of Salesforce (which requires a web browser or a Blackberry, Treo, or iPhone)!  As for timing, a car can be rented on the spot – if I want a car immediately at 3:45pm, the system will let me rent from 3:30pm.  Sure, I eat the 15 minutes, but that’s a small price to pay for the convenience.<br />
<strong>PAYMENT MODEL</strong><br />
With Salesforce, I pay a subscription fee, plus a fee for any add-ons such as Mobile, a Full Sandbox, etc.  Zipcar is similar: I pay a recurring membership fee, and then each car rental is booked hourly.  I don’t pay for gas!  The car comes with a special debit card that I can use at any gas station; Zipcar tells us to leave the tank at least a quarter full.<br />
Zipcar has two pricing models: One for heavy users, and one for occasional users.  (Sounds like Salesforce’s portal pricing model, right?)  Everyone pays a $50 yearly fee.  Heavy users pay $50 to $125 per month up front, but dollars can roll-over.  Higher plans include hourly discounts.  Occasional drivers just pay the yearly fee and standard hourly rates, which vary per car model, but range from $9.25 to $11 near me.<br />
Heavy users pay $50 per year and commit to $50 per month in driving fees.  Basically, it’s a cell phone plan in that on average, I’m paying $55 per month for car usage annually.  I can go over my $50 per month, and that (unlike my cell phone plan!) is billed at the standard rate.  The overage charges come in if I return a car late; then I get hit with some serious penalties.  This plan also gives 10% off standard hourly rates.  Heavy user (and I mean in terms of weight, as this turns out to be a great weight-loss tool, as I’ll describe in a bit) plans are also available at higher monthly commitments and come with rollover miles (hello, Cingular) and deeper hourly discounts.<br />
For occasional users, just pay the same yearly fee and standard hourly rates.  No commitment at all.  It’s not identical to pay-per-login, as the duration of time spent using the system is part of the pricing, but it’s a standard pay-as-you-go setup.<br />
That all sounds like an on-demand product to me so far.<br />
<strong>INTEROPERABILITY</strong><br />
Salesforce has a robust API that enables it to interface seamlessly with other systems.  Zipcar has a nice Google Maps mashup of available cars on its website, but it also interfaces with gas pump machines: When I fill up, I use the Zipcar-provided debit card, and I input my membership number.  The system knows if I am currently renting a car, and allows me to pump my gas.  Otherwise, I assume that it will prevent me from doing so.<br />
<strong>SECURITY</strong><br />
This is where Zipcar comes through in a major way: There is an RFID reader in each car, and it is keyed to my membership card only for the hours that I’m scheduled to rent the car.  I merely wave my card in front of the reader and the car unlocks.  You may wonder what I do for car keys:  The keys are always locked in the car!  Because the reader will unlock only for me, whenever I make a stop, I just lock the keys in the car and swipe my card to lock all the doors.  Zipcar says that this also activates an engine kill switch, so even if someone breaks in and tries to start the car, it won’t work.  Does this all sound like two-factor authorization?<br />
Salesforce has a password-protected system, accessible only from a https page.  Using the system from an unrecognized computer results in a prompt to send an activation URL to the user’s email address.  Additionally, Salesforce uses an API token system, appended after the user’s password, to allow direct API access to data.  No token, no access.  A nice kill switch!<br />
Clearly, any security system must also be interoperable.  Salesforce has SAML single sign-on, and though I don’t think it would be prudent for Zipcar to allow its cars to be opened with anything other than Zipcards, their system clearly must interface with the car’s security, gas pumps/payment computers, a membership list, and probably GPS trackers that I’m sure they have installed in the cars in case anyone tries some funny business.<br />
And that’s just the security we can see.  When one of my consulting clients fired a Salesforce user and forgot to deactivate his login, he got into the system (indicated by the Last Login Date on his user record) but they didn’t know what he had done.  Salesforce.com could reconstruct his login, including the string he typed into the search box and which record he viewed before logging off.  Some of the best security tracking features are ones we don’t know exist until we have a problem and need historical information.  Something tells me that Zipcar can tell me where I drove my last few rentals, along with the exact times I locked and unlocked the cars.  And that’s fine with me.  The as a Service model requires us to trust our providers.  I know that salesforce.com is tracking what I do in each org and I know they won’t use that information for malicious purposes.  Similarly, when I signed on to the Zipcar program, I knew that they would have some information about me, but I trade that lack of anonymity for the convenience that the Zipcar program gives me.  If I were that paranoid, I’d never go to London for fear of being caught on their myriad video cameras.  But that’s another article for another day.<br />
<strong>ANYONE CAN INNOVATE</strong><br />
Salesforce has the AppExchange, where I can go to download plug-ins that other people have created.  But I can also create custom modules of my own within my org.  Zipcar doesn’t tell me where to drive or where to park when the car is on my time, so I am free to innovate (hello Web 3.0) as I wish.<br />
No, I’m not going to innovate to the point of installing any upgrades on the Zipcar just down my street, so the metaphor does fall apart at some point.<br />
<strong>CHANNEL SELLING</strong><br />
Salesforce provides its referral partners with code to place logos on our websites.  If someone uses our logo to create a trial, and eventually signs up as a customer, we get a share of salesforce.com’s revenue.  Similarly, Zipcar provides $50 for every person I refer.  I can allocate that money between the two of us in any way I want; I can keep it all, can give it away, or we can split it.  Not bad!<br />
<strong>USER LIMITS FOR THE GREATER GOOD</strong><br />
Nobody likes limitations, but sometimes they have to exist.  Salesforce has a governor on Apex calls, on API calls per 24 hours, and sometimes on logins per month.  Salesforce also has strict specifications on how Apex code is written and executed.  It would be terrible if one person wrote bad code that crashed the system or corrupted someone else’s data.<br />
Zipcar will charge me for any damage I may cause to the vehicle. For that reason, I do a walkaround before every rental, and if there is any damage, all I have to do is report it to a slick automated hotline and I won’t be liable if anything happens.<br />
<strong>MAINTENANCE IS INCLUDED</strong><br />
The best part about Salesforce has got to be the included upgrades.  And I mean hardware and software.  I never pay extra to upgrade anything—when a new version comes out (about three times a year), I get plenty of emails with cool descriptions, and even get tutorials.  But I never pay for that.  (Compare that to Microsoft Office, which was expensive in 2003 and even more expensive in 2007.)  And have I ever had to wonder about the servers?  Nope.  I don’t care if a given drive or rack needs to be replaced because salesforce.com has a team of people dedicated to hardware maintenance AND another team responsible for maintaining mirrored servers so that if something should happen at one site, everything is still accessible seamlessly to the user.<br />
Zipcar handles all the oil changes and maintenance on its cars.  They even have a fleet of bike messengers and trained auto mechanics (super combination) who can zip across town to any car quickly (bringing their own tools) and make on the spot repairs.  I guess the included fuel falls into this category as well.  Zipcar also bought all the cars itself.  If a car needs to be retired, they will buy a replacement, ensuring that the customer has at least a constant (and lately increasing) list of cars from which to choose.<br />
<strong>CONVENIENT ACCESSIBILITY</strong><br />
Okay, so it’s hard to compete with Salesforce in the convenience department: I can get into my system from any web-enabled computer using Internet Explorer, Firefox, or (in beta) Safari.  Both services make me buy my own internet access, but that goes without saying.  Here’s where Zipcar has made some super strides in the convenience arena:<br />
If I’m running late and want to extend my rental, I just call an automated line and it will allow me to do so.  Of course, that assumes that the car is available for that time.  If not, they’ll tell me how much longer I can keep it.  When I reported damage to a car (at my initial walkaround), I got a confirmation email.  This is similar to the confirmation emails I get from Salesforce whenever I change my password.<br />
Also along the lines of convenience, it bears reiterating that I can drive anywhere.  Some have tried to make the case that a commuter rail system is Transportation as a Service, and that may be true to some, but for me the key is independence.  The train goes along its track, on its timetable.  My Zipcar goes where I want.  Sure, I have to park in front of my building, run upstairs to put away the groceries, and go back to the lot, then walk home, but it’s worth it.<br />
<strong>LOCATIONS</strong><br />
Go ahead and remind me that Salesforce is a non-tangible product, so it is accessible from anywhere in its entirety.  I fully agree.  Zipcars are in specific parking spaces, and in specific cities.  They don’t have a strong presence in Los Angeles, but are in Santa Barbara, Santa Cruz, Claremont, Irvine, and more.  There are also Zipcars in San Francisco, Nashville (my hometown), Boston, Columbus, Toronto, and more.  They even have cars in London!  If someone lives near a Zipcar, then it’s perfect.  If not, then not so much.  They don’t put cars at airports, as that’s the standard rental companies’ bread and butter, but they put cars all over town.<br />
<strong>BRANDING</strong><br />
Marketing is huge.  Salesforce has its logo in its applications, which makes perfect sense.  Zipcar brands its cars as well.  I’m using their cars, so they should get some advertising out of the deal.<br />
The last car I rented, a Mini Cooper, had a Zipcar logo on the passenger door and www.zipcar.com on the back.  That was it.  Not terribly obtrusive, but nobody’s going to believe that I own a BMW when I pull up in a Zipcar.  Keep in mind, though, that I’m not in this to impress anyone—I’m in it for the Car as a Service.<br />
As with most things these days, some benefits were likely not predicted: A guy on the street saw me swiping my Zipcard and asked me what I was doing.  We talked about it and he said he’d sign up.  Not bad!  (Then there was the guy who saw me doing it and proclaimed to his friend (with a brown-bagged bottle in his hand) that this was something new and he was getting it on his car, which was in the shop that day.  Yeah.)</p>
<p><strong>THE DIET PARTICULARS</strong><br />
Zipcar had a great idea with the low car diet: I committed not to use my car for a month, and in return they gave me a year’s subscription, $150 in rental credit, a 7-day bus/el pass, and a tour of Wrigley Field.  (That last bit was clutch—there’s little cooler than going into the Cubs’ clubhouse, which is also one of two batting cages at the Friendly Confines, and pretending to sing “Take Me Out to the Ballgame” from Harry Caray’s broadcast booth.<br />
Six weeks ago, I decided to try the Wii Fit weight-loss plan.  I don’t need to lose a ton of weight, but I wouldn’t mind trimming a bit off the bottom.  Part of the Wii Fit product lets me record my other exercising as well, including walking.  And that has dovetailed perfectly with the Zipcar program:<br />
Not being able to use my car, and having to schedule car usage in advance (though sometimes only 45 minutes in advance) forces me to consolidate my errands.  I used to drive to Best Buy, though it’s (gasp) 0.6 miles away by car.  They have a parking lot!  There have been times that the weather’s been so hot that I’ve wanted to drive to the local Argo Tea to do configurations outside my home office, but I’ve had to walk.  I saved money on gas and parking, AND got good exercise.  It’s also nice to keep track of that and to enter it in my Wii Fit log so I can unlock cooler exercises on that as well.<br />
My car is in a valet garage, so whenever I want to use it, I have to call down and ask the guys to bring it around for me.  I’ve always felt guilty about that, so it’s always been important to consolidate my errands and to get as much done as possible.  How much more so with Zipcar!  I’ve become great at writing down a list of things to do, and then assembling everything I’ll need at my front door.  If it’s too much to carry, I’ll go get the car (there are 15 within 0.56 miles of my apartment) and bring it back, take my stuff downstairs, and run my many errands.  If I need a bigger car, I know I can rent a Honda Element or a Subaru Outback.  If I want a smaller one, there’s the Mini Cooper, and many others in between.<br />
I no longer take my car just to pick up the dry cleaning or to buy groceries.  No way.  Now it’s a huge process of deciding what to do first, second, third, etc.  My car doesn’t get the best mileage, so it’s also nice to shift the burden onto someone else’s car for all those other expenses.<br />
Am I getting rid of my car? Probably not.  Will I drive it?  Probably about once a month, if that.  Zipcar is simply too good to give up.  But I’m lucky to have low insurance rates, cheap parking (for Chicago), and a car that needs little maintenance.  I do, however, have clients in other cities and in neighboring states, and sometimes I go onsite for longer than the three-day maximum allowed by Zipcar.  Believe me: If I could get a super deal on a four- or five-day rental, I might change my mind (and at $68 to $80 per day, gas included, my mind might change sooner than I expect).  National Car Rental is $41 for a midsize, so I’d have to look at gas prices.  Maybe I’d use Zipcar for intracity driving, and National for intercity.  We’ll see. </p>
<p>This has turned out to be a combination of a Saas vs CaaS comparison and my personal Zipcar impressions, but I hope that through reading it you not only become as excited about Zipcar as I am, but that you start to see other as-a-Service providers around you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2008/08/13/zipcar-caas-car-as-a-service.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Listing in Alltop!</title>
		<link>http://www.x2od.com/2008/07/22/a-listing-in-alltop.html</link>
		<comments>http://www.x2od.com/2008/07/22/a-listing-in-alltop.html#comments</comments>
		<pubDate>Tue, 22 Jul 2008 05:47:54 +0000</pubDate>
		<dc:creator>David Schach</dc:creator>
				<category><![CDATA[X-Squared On Demand]]></category>
		<category><![CDATA[New Developments]]></category>

		<guid isPermaLink="false">http://www.x2od.com/?p=88</guid>
		<description><![CDATA[You know you’ve arrived when Guy Kawasaki give you his blessing and you find your blog in Alltop. Well, that’s exactly what has happened: Find this blog at Customerservice.alltop.com!]]></description>
			<content:encoded><![CDATA[<p>You know you&#8217;ve arrived when <a href="http://twitter.com/guykawasaki" target="_blank">Guy Kawasaki</a> give you his blessing and you find your blog in <a href="http://www.alltop.com" target="_blank">Alltop</a>.  Well, that&#8217;s exactly what has happened: Find this blog at <a href="http://customerservice.alltop.com/" target="_blank">Customerservice.alltop.com</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.x2od.com/2008/07/22/a-listing-in-alltop.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
