I'd like creare a simple parser in Java that analize a string containing html and replace custom tags and if else/elseif statements, similar to Mailchimp.
Actually I simply replace my custom tags for example: *|NAME|*
with the name of the recipient, *|AGE|* whith the age of the recipient and so on.
I'd like to add conditional statements to permit expressions like:
<html>
<head>....</head>
<body>
*|IF:GENDER=M|*
Hello Mr.<b>*|NAME|*</b>
*|ELSEIF:GENDER=F|*
Hello Mrs.<i>*|NAME|*</i>
*|ELSE:|*
Dear customer
*|END:IF|*
<p>Bla bla bla</p>
....
....
</body>
</html>
In short, a very similar sintax to Mailchimp one.
The user can write his own html and add a custom syntax to customize the content based on data.
I think I'm able to create a code that works but I'm searching for the best practice to implement it. I looking for a good way to follow to implements a good code.
Would be nice if the parser can manage nested if/elseif/else statements.
Related
I'm working on a project using play framework 1.2.5
I have two custom tags files, one that does 'set' a value
#{set foo:'bar' /}
and another file that 'get' this value to make a decision to show some markup or not.
%{ if(foo) { %}
#{doBody /}
%{ } }%
This used to work in a previous play version (don't recall which) and now is not working, I'm not sure if it was the upgrade itself or something else got broken.
As per play documentations for template engine tags, set should work between different files:
Define a value which can be retrieved in the same template or any layout with the get tag.
http://www.playframework.com/documentation/1.2.3/tags#set
Any clue on what might be wrong?
thanks in advance
set only works with child template passing data to extended template, e.g
parent template:
<html>
<title>${get 'title'}</titl>
...
</html>
child template:
$extends('parent.html')
${set title: 'My Title'/}
To pass data from one template to another template, you have to define the callee template as a tag. See play's document on more detail. Note I am not sure if tag could extend another tag, most probably it is not possible
If you are using PlayRythm plugin, then it is much easier. E.g. calling from template foo to bar could be as easy as
bar template:
Hello #who
foo template:
#bar("World")
#// or
#bar(who: "world")
#// or
#bar({who: "world"})
Note Rythm doesnot have a separate tag concept, literally every template is tag and you can call any template from another one or even do recursive call. You can try rythm's live interactive demo on http://fiddle.rythmengine.org/.
Disclaim: I am the creator and maintainer of Rythm template engine and Play-Rythm module
I know I can use expression in play framework template like this.
<h1>Client ${client.name}</h1>
What to do if I need to include ${client.name} in html tag?
For example,
<h1 id=${client.name}>Client ${client.name}</h1>
However, this way doesn't works.
First replace that example because the id need a "" to use like this
<h1 id="${client.name}">Client ${client.name}</h1>
then to use java code in your template use the %{ java code here }% tags you can create variables and use it like %{ string mystring = "hello";}% then in the template<h2>${mystring}</h2>.
here are one example from my real code:
%{String selected = ""; if (permisoseleccionado?.Permiso?.id == tp?.id){selected = "selected";}}%
this post is old but I thing that this will be usefull to other people.
see ya!
I am sending emails using amazon java sdk. I have to send html template as mail. I have written a program for this and it is working fine. But now I am storing the whole html code in a single String. But whenever i need to edit the template, I have to edit the program (I mean the String variable). And also I have to take care the special characters like " \ ...etc in that html code. Please suggest me an elegant way to solve this issue.
Use a template engine for that and store your template externally either in class path or on a file system. Here is a question that may help you selecting one: https://stackoverflow.com/questions/2381619/best-template-engine-in-java
Use Apache Common Lang api's StringEscapeUtils#escapeHtml, It escapes the characters in a String using HTML entities and return a new escaped String, null if null string input.
For example:
"US" & "UK"
becomes:
"US" & "UK".
Check the Apache Velocity Project. You can create template for several things. From it's user-guide page
Velocity can be used to generate web pages, SQL, PostScript and other output from templates. It
can be used either as a standalone utility for generating source code and reports, or as an
integrated component of other systems.
You can use a VTL(Velocity Template Language) . A example from above link
<HTML>
<BODY>
Hello $customer.Name!
<table>
#foreach( $mud in $mudsOnSpecial )
#if ( $customer.hasPurchased($mud) )
<tr>
<td>
$flogger.getPromo( $mud )
</td>
</tr>
#end
#end
</table>
Better and easiest way is reading the html file line by line using simple file reading operation and append this each line to a single String. And also I found this solution (also a better one, if you are ready to add one more library file to your project) from SO.
is there a way to use groovy builders to build JSP files in a Grails application keeping things enough integrated?
To explain better: by default Grails uses gsp files that are nice but quite verbose..
<div class="clear">
<ul id="nav">
<li><g:link controller="snippets" action="list">Snippets</g:link></li>
<li><g:link controller="users" action="list">Users</g:link></li>
<li><g:link controller="problems" action="list">Problems</g:link></li>
<li><g:link controller="messages" action="list">Messages</g:link></li>
</div>
<div id="content">
is there a way to use groovy.xml.MarkupBuilder tha would turn the previous piece into
div(class:'clear') {
ul(id:'nav') {
li { g_link(controller:'snippets', action:'list', 'Snippets') }
// and so on
Of course g_link is invented just to give the idea..
Do a search for builder under the web layer section of the grails user guide. There is an example in there that shows you exactly how to do this using the xml builder.
I don't have a complete answer for you, but I suspect the key will be gaining access to the "view resolvers". In a normal SpringMVC app, these are configured in views.properties (or views.xml) as follows:
csv=com.example.MyCSVResolver
xml=com.example.MyXMLResolver
audio=com.example.MySpeechResolver
In a regular SpringMVC app, you return something like new ModelAndView(myModel, 'csv') from a controller action.
This would cause the CSVResolver class to be invoked passing it the data in myModel. In addition to containing the data to be rendered, myModel would likely also contain some formatting options (e.g. column widths).
Spring searches the views file for a key matching the view name. If it doesn't find a match, by default it just renders a JSP with the view name and passes it the model data.
Now back to Grails....remember that Grails is really just a Groovy API over SpringMVC and most of the features of SpringMVC can be accessed from Grails. So if you can figure out how to modify the views file, just change your controller actions to return an appropriate ModelAndView instance, and it should work as described above.
GSP allows you to run arbitrary Groovy code inside <% %> brackets. So you can have something like this (borrowing example from page linked to by BlackTiger):
<% StringWriter w = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(w)
builder.html{
head{
title 'Log in'
}
body{
h1 'Hello'
builder.form{ }
}
}
out << w.toString()
%>
Note that the above calls g:form tag, and you can pass additional stuff to it.
So what you are asking for is certainly possible, though I am not sure if it will end up being a win. I'd suggest you perhaps look more at TagLibs in combination with Templates and SiteMesh Layouts - can definitely simplify things tremendously.
I was thinking about the idea of using Ajax instead of TagLib. The most elegant way would be: Using Java Annotation.
The idea is, designers or anybody can make the HTML without any taglib ,just using the "standard" HTML tags with id or name, and call the Javascript. That way any WYSIWYG can be used, developer don't have to care about HTML format or the way it's designed.
In many (at least open-source) WYSIWYG don't show the taglibs in that final result (or have a template of it), so it's hard to "preview". Other reason is, developer should know Java and HTML/TagLibs should not be a must-have, since we got CSS and AJAX.
It should work just like that:
MyClass.java:
import ...
// Use the ResourceBundle resource[.{Locale}].properties
#Jay2JI18n(resourceBundle="org.format.resource",name="MyClassForm")
public class MyClass {
private Integer age;
private String name
private Date dob;
private salary;
#Jay2JLabel(resource="label.name")
#Jay2JMaxLength(value=50,required=true,)
#Jay2JException(resource="exception.message")
public String getName() {
...
}
public void setName(String name) {
if ( name.trim().equal("") ) {
throw new Exception("Name is required");
}
}
/* Getter and setter for age */
...
#Jay2JLabel(message="Salary")
#Jay2JFormat(format="##,###.00",language="en")
#Jay2JFormat(format="##.###,00",language="pt_BR")
// or you could use that to access a property of the ResourceBundle
//#Jay2I18nResource(resource="money.format")
public Date getSalary() {
...
}
/* Setter for salary and getter/setter for the rest */
...
}
Page.html:
<html>
<head>
<SCRIPT>
</SCRIPT>
</head>
<body>
<form onload="Jay2J.formalize(this)">
</form>
</body>
</html>
of it can be a HTML with the fields filled;
PageWithFields.html:
<html>
<head>
<SCRIPT>
</SCRIPT>
</head>
<body>
<form action="myfavoritewaytopostthis" onsubmit="return Jay2J.validate(this)" onload="Jay2J.formalizeExistField(this)">
<label>Name</label><input type="text" name="name" id="name" />
<label>DOB</label><input type="text" name="dateOfBirth" id="dob" />
<label>Salary</label><input type="text" name="salary" id="salary" />
<input type="submit" />
</form>
</body>
</html>
That way the Annotation (no XML, it's like HTML in the way that it's only another file modify and XML is not Java) will define how the HTML will be treated. That way developer can stop developing in HTML and use just JAVA (or JavaScript), do you think that's a valid idea?
When i see your topic title i thought:
You cant use Ajax in stead of a taglib. AJAX is javascript on the client and the taglib is java code on the server.
After reading your post i thought, ah he whats to do what [link text][1] does
But then not entrily the same.
[1]: http://code.google.com/webtoolkit/ GWT
First impression is ... yuck, someone who picks this up will have no idea what they're looking at without learning your (new, different, non-standard) way of doing things. You could do something similar by implementing a tag that takes a bean (value object) and maybe does some minor reflection/annotation inspection to emit the proper html, and you'll save yourself a lot of heartache down the line.
Make your value objects implement a simple interface that your tag will use to extract and format the html, and you can probably get 80-90% of where you're trying to go with 1/2 the work or less.
First impression was, WTF. After reading further, I get a impression that you are trying to address the 'separation of concerns'problem in a different way. Some observations on your approach.
Requires client side scripting to be enabled and hence fails accessibility guide lines.
Reinventing the wheel: Many web frameworks like Tapestry, Wicket try to address these issues and have done a commendable work.
On your comment on binding Java to HTML, the code example doesn't convey the idea very clearly. formalize() seems to create the UI, that implies you have UI (HTML) coded into java (Bad Idea? probably not NakedObjects attempts to you domain models for UI, probably yes if one were to write a page specific code)
validate() is invoked on onSubmit(), Why would I want it to be processed asynchronously!! That aside, using obstrusive java script is way out of fashion (seperation of concerns again)
Your argument on taglibs preventing WYSIWIG, though justifiable, is not entirely valid. Tags cannot be used to compose other tags, each tag is a unique entity that either deals with behaviour or emits some html code. Your argument is valid for the second case. However, if I understand your formalize() correctly, you are doing the same!
Nice to hear some new ideas and Welcome to SO. Also, please use the edit question option until you earn enough reputation to add comments. Adding answers is not the right way!
This idea has some merit, if I understand it correctly.
You could use AOP to modify a servlet that would actually be called for the page. The servlet would then return the html, using the annotations.
This way the programmers don't see the html generation, and if you have a standard javascript library for it, then it may work.
But, just because it works doesn't mean that you should do it.
As was mentioned, there are many frameworks out there that can hide the javascript from programmers, such as JSF, which is basically taglibs and a different navigation scheme.
I remember using the beehive project to do something similar, it was annotation driven so I could basically do everything in java and it generated the javascript, years ago. :)