From: <mb...@re...> - 2004-11-04 20:45:40
|
Author: mbooth Date: 2004-11-04 21:38:35 +0100 (Thu, 04 Nov 2004) New Revision: 80 Modified: ccm-core/trunk/src/com/arsdigita/formbuilder/actions/XMLEmailListener.java ccm-core/trunk/src/com/arsdigita/formbuilder/util/Placeholders.java Log: Fix/Enhance XMLEmailListener in a few ways: 1. No longer throws an error when user isn't logged in. 2. Produces much cleaner (but the same) XML. 3. Email title can contain any placeholder text and this will be interpolated. eg set title to "Email about ::form.subject::" "subject" will be interpolated from a fields in the form. Modified: ccm-core/trunk/src/com/arsdigita/formbuilder/actions/XMLEmailListener.java =================================================================== --- ccm-core/trunk/src/com/arsdigita/formbuilder/actions/XMLEmailListener.java 2004-11-04 20:28:37 UTC (rev 79) +++ ccm-core/trunk/src/com/arsdigita/formbuilder/actions/XMLEmailListener.java 2004-11-04 20:38:35 UTC (rev 80) @@ -18,29 +18,44 @@ */ package com.arsdigita.formbuilder.actions; +import com.arsdigita.formbuilder.PersistentProcessListener; import com.arsdigita.formbuilder.util.Placeholders; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.PersonName; +import com.arsdigita.kernel.User; import com.arsdigita.persistence.OID; import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.metadata.ObjectType; import com.arsdigita.domain.DataObjectNotFoundException; - -import com.arsdigita.bebop.FormData; -import com.arsdigita.bebop.FormProcessException; -import com.arsdigita.bebop.event.FormSectionEvent; - import com.arsdigita.mail.Mail; +import com.arsdigita.util.UncheckedWrapperException; +import com.arsdigita.web.Web; +import com.arsdigita.xml.XML; -import com.arsdigita.formbuilder.PersistentProcessListener; -import com.arsdigita.formbuilder.util.Placeholders; - +import java.io.StringWriter; import java.math.BigDecimal; import java.util.Iterator; import javax.mail.MessagingException; -import com.arsdigita.util.UncheckedWrapperException; -import com.arsdigita.bebop.event.FormProcessListener; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + public class XMLEmailListener extends PersistentProcessListener { public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.formbuilder.actions.XMLEmailListener"; @@ -48,6 +63,17 @@ public static final String TO = "recipient"; public static final String SUBJECT = "subject"; + private ThreadLocal s_dbFactory = new ThreadLocal() { + protected Object initialValue() { + DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); + f.setCoalescing( true ); + f.setNamespaceAware( false ); + f.setValidating( false ); + + return f; + } + }; + public XMLEmailListener() { this(BASE_DATA_OBJECT_TYPE); } @@ -136,27 +162,112 @@ public void process(FormSectionEvent e) throws FormProcessException { - - Placeholders p = new Placeholders(e.getPageState()); + Placeholders p = new Placeholders(e.getPageState(), e.getFormData()); String to = p.interpolate(m_to); String subject = p.interpolate(m_subject); - //String from = p.interpolate("::user.givenname:: ::user.familyname:: <::user.email::>"); - String from = p.interpolate("::user.email::"); - StringBuffer body = new StringBuffer(p.interpolate("<form-data>\n <from email=\"::user.email::\">\n <givenname>::user.givenname::</givename> <familyname>::user.familyname::</familyname>\n </from>\n <field-list>\n")); + String from; + User user = (User)Kernel.getContext().getParty(); + if( null == user ) { + from = "notloggedinuser@" + + Web.getConfig().getServer().getName(); + } else { + from = user.getPrimaryEmail().getEmailAddress(); + } + DocumentBuilder db; + try { + db = ((DocumentBuilderFactory) (s_dbFactory.get())).newDocumentBuilder(); + } catch( ParserConfigurationException ex ) { + throw new UncheckedWrapperException( ex ); + } + + Document doc = db.newDocument(); + Element formDataE = doc.createElement( "form-data" ); + doc.appendChild( formDataE ); + + if( null != user ) { + Element fromE = doc.createElement( "from" ); + fromE.setAttribute( "email", from ); + formDataE.appendChild( fromE ); + + PersonName name = user.getPersonName(); + + String givenName = name.getGivenName(); + Element givenNameE = doc.createElement( "givenname" ); + givenNameE.appendChild( doc.createTextNode( givenName ) ); + fromE.appendChild( givenNameE ); + + String familyName = name.getFamilyName(); + Element familyNameE = doc.createElement( "familyname" ); + familyNameE.appendChild( doc.createTextNode( familyName ) ); + fromE.appendChild( familyNameE ); + } + + Element fieldListE = doc.createElement( "field-list" ); + formDataE.appendChild( fieldListE ); + FormData data = e.getFormData(); Iterator keys = data.keySet().iterator(); while (keys.hasNext()) { String key = (String)keys.next(); Object value = data.get(key); - body.append(" <field" + (value == null ? "" : (" type=\"" + value.getClass().getName() + "\"")) + "><key>" + key + "</key>" + (value == null ? "" : "<value>" + value.toString() + "</value>") + "</field>\n"); + Element fieldE = doc.createElement( "field" ); + fieldListE.appendChild( fieldE ); + + Element keyE = doc.createElement( "key" ); + keyE.appendChild( doc.createTextNode( key ) ); + fieldE.appendChild( keyE ); + + if( null == value ) continue; + + Class valueClass = value.getClass(); + + String type; + if( valueClass.isArray() ) { + type = valueClass.getComponentType().getName(); + } else { + type = valueClass.getName(); + } + fieldE.setAttribute( "type", type ); + + if( valueClass.isArray() ) { + Object[] values = (Object[]) value; + + for( int i = 0; i < values.length; i++ ) { + Element valueE = doc.createElement( "value" ); + valueE.appendChild( doc.createTextNode( values[i].toString() ) ); + fieldE.appendChild( valueE ); + } + } else { + Element valueE = doc.createElement( "value" ); + valueE.appendChild( doc.createTextNode( value.toString() ) ); + fieldE.appendChild( valueE ); + } } - body.append("</field-list>\n</form-data>\n"); + StringWriter body = new StringWriter(); + DOMSource source = new DOMSource( doc ); + + Transformer tr; try { + tr = TransformerFactory.newInstance().newTransformer(); + } catch( TransformerConfigurationException ex ) { + throw new UncheckedWrapperException( ex ); + } + + tr.setOutputProperty( OutputKeys.ENCODING, "UTF-8" ); + tr.setOutputProperty( OutputKeys.INDENT, "yes" ); + + try { + tr.transform( source, new StreamResult( body ) ); + } catch( TransformerException ex ) { + throw new UncheckedWrapperException( ex ); + } + + try { Mail message = new Mail(to, from, subject, body.toString()); message.send(); } catch (MessagingException ex) { Modified: ccm-core/trunk/src/com/arsdigita/formbuilder/util/Placeholders.java =================================================================== --- ccm-core/trunk/src/com/arsdigita/formbuilder/util/Placeholders.java 2004-11-04 20:28:37 UTC (rev 79) +++ ccm-core/trunk/src/com/arsdigita/formbuilder/util/Placeholders.java 2004-11-04 20:38:35 UTC (rev 80) @@ -31,15 +31,19 @@ import java.util.HashMap; import java.util.Iterator; +import java.util.Map; - import com.arsdigita.db.Sequences; import java.sql.SQLException; import com.arsdigita.util.UncheckedWrapperException; import java.math.BigDecimal; +import org.apache.log4j.Logger; + public class Placeholders { + private static final Logger s_log = Logger.getLogger( Placeholders.class ); + private HashMap m_vars; // FIXME: why do we need to pass state into this constructor? I don't see it @@ -71,6 +75,21 @@ public String interpolate(String text) { + if( s_log.isDebugEnabled() ) { + StringBuffer buf = new StringBuffer(); + + buf.append( "Interpolating: " ).append( text ).append( '\n' ); + + Iterator vars = m_vars.entrySet().iterator(); + while( vars.hasNext() ) { + Map.Entry var = (Map.Entry) vars.next(); + + buf.append( var.getKey() ).append( ": " ); + buf.append( var.getValue() ).append( '\n' ); + } + + s_log.debug( buf.toString() ); + } return StringUtils.interpolate(text, m_vars); } |