安装Tuscany的Eclipse插件
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
英文原文版权归原作者所有, 本译文转载请注明出处!
译者:abigfrog 联系:QQ:800736, MSN:J2EE@HOTMAIL.COM
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
首先,启动Eclipse,并依次点击菜单:Help -> Software Updates -> Find and Install,选择“Search for new features to install”,点击下一步:
< composite xmlns ="http://www.osoa.org/xmlns/sca/1.0"
xmlns:t ="http://tuscany.apache.org/xmlns/sca/1.0"
xmlns:s ="http://store"
name ="store" >
<! —原文如此,错误
<component name="store" >
< t:implementation .widget location ="ufservices/store.html" />
< service name ="Widget" >
< t:binding .http />
</ service >
< reference name ="catalog" target ="Catalog" >
< t:binding .jsonrpc />
</ reference >
< reference name ="shoppingCart" target ="ShoppingCart" >
< t:binding .atom />
</ reference >
</ component >
-->
<! —正确的应该这样 -- >
< component name ="store" >
< t:implementation .resource location ="ufservices" />
< service name ="Resource" >
< t:binding .http />
</ service >
</ component >
<! —正确的应该这样 -- >
< component name ="Catalog" >
< implementation .java class ="services.CatalogImpl" />
< property name ="currencyCode" > USD </ property >
< service name ="Catalog" >
< t:binding .jsonrpc />
</ service >
< reference name ="currencyConverter" target ="CurrencyConverter" />
</ component >
< component name ="ShoppingCart" >
< implementation .java class ="services.ShoppingCartImpl" />
< service name ="Collection" >
< t:binding .atom />
</ service >
</ component >
< component name ="CurrencyConverter" >
< implementation .java class ="services.CurrencyConverterImpl" />
</ component >
</ composite >
this .uri = uri;
this .get = function (id, responseFunction) {
var xhr = this .createXMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 ) {
if (xhr.status == 200 ) {
if (responseFunction !== null ) {
responseFunction(xhr.responseXML);
}
} else {
alert( " get - Error getting data from the server " );
}
}
};
xhr.open( " GET " , uri + id, true );
xhr.send( null );
};
this .post = function (entry, responseFunction) {
var xhr = this .createXMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 ) {
if (xhr.status == 201 ) {
if (responseFunction !== null ) {
responseFunction(xhr.responseXML);
}
} else {
alert( " post - Error getting data from the server " );
}
}
};
xhr.open( " POST " , uri, true );
xhr.setRequestHeader( " Content-Type " , " application/atom+xml " );
xhr.send(entry);
};
this .put = function (id, entry, responseFunction) {
var xhr = this .createXMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 ) {
if (xhr.status == 200 ) {
if (responseFunction !== null ) {
responseFunction(xhr.responseXML);
}
} else {
alert( " put - Error getting data from the server " );
}
}
};
xhr.open( " PUT " , uri + id, true );
xhr.setRequestHeader( " Content-Type " , " application/atom+xml " );
xhr.send(entry);
};
this .del = function (id, responseFunction) {
var xhr = this .createXMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 ) {
if (xhr.status == 200 ) {
if (responseFunction !== null ) {
responseFunction();
}
} else {
alert( " delete - Error getting data from the server " );
}
}
};
xhr.open( " DELETE " , uri + id, true );
xhr.send( null );
};
this .createXMLHttpRequest = function () {
try { return new XMLHttpRequest();} catch (e) {}
try { return new ActiveXObject( " Msxml2.XMLHTTP " );} catch (e) {}
try { return new ActiveXObject( " Microsoft.XMLHTTP " );} catch (e) {}
alert( " XML http request not supported " );
return null ;
};
}
bindingatom = " loaded " ;
function escapeJSONChar(c)
{
if (c == " " " || c == " / " ) return " / " + c;
else if (c == " " ) return " /b " ;
else if (c == " " ) return " /f " ;
else if (c == " " ) return " /n " ;
else if (c == " " ) return " /r " ;
else if (c == " " ) return " /t " ;
var hex = c.charCodeAt( 0 ).toString( 16 );
if (hex.length == 1 ) return " /u000 " + hex;
else if (hex.length == 2 ) return " /u00 " + hex;
else if (hex.length == 3 ) return " /u0 " + hex;
else return " /u " + hex;
};
/* encode a string into JSON format */
escapeJSONString =
function escapeJSONString(s)
{
/* The following should suffice but Safari's regex is b0rken
(doesn't support callback substitutions)
return """ + s.replace(/([^ -]|[/"])/g,
escapeJSONChar) + """;
*/
/* Rather inefficient way to do it */
var parts = s.split( "" );
for ( var i = 0 ; i < parts.length; i ++ ) {
var c = parts[i];
if (c == ' " ' ||
c == ' / ' ||
c.charCodeAt( 0 ) < 32 ||
c.charCodeAt( 0 ) >= 128 )
parts[i] = escapeJSONChar(parts[i]);
}
return " " " + parts.join( "" ) + " " " ;
};
/* Marshall objects to JSON format */
toJSON = function toJSON(o)
{
if (o == null ) {
return " null " ;
} else if (o.constructor == String) {
return escapeJSONString(o);
} else if (o.constructor == Number) {
return o.toString();
} else if (o.constructor == Boolean) {
return o.toString();
} else if (o.constructor == Date) {
return ' {javaClass: "java.util.Date", time: ' + o.valueOf() + ' } ' ;
} else if (o.constructor == Array) {
var v = [];
for ( var i = 0 ; i < o.length; i ++ ) v.push(toJSON(o[i]));
return " [ " + v.join( " , " ) + " ] " ;
} else {
var v = [];
for (attr in o) {
if (o[attr] == null ) v.push( " " " + attr + " ": null " );
else if ( typeof o[attr] == " function " ); /* skip */
else v.push(escapeJSONString(attr) + " : " + toJSON(o[attr]));
}
return " { " + v.join( " , " ) + " } " ;
}
};
/* JSONRpcClient constructor */
JSONRpcClient =
function JSONRpcClient_ctor(serverURL, user, pass, objectID)
{
this .serverURL = serverURL;
this .user = user;
this .pass = pass;
this .objectID = objectID;
/* Add standard methods */
if ( this .objectID) {
this ._addMethods([ " listMethods " ]);
var req = this ._makeRequest( " listMethods " , []);
} else {
this ._addMethods([ " system.listMethods " ]);
var req = this ._makeRequest( " system.listMethods " , []);
}
var m = this ._sendRequest(req);
this ._addMethods(m);
};
/* JSONRpcCLient.Exception */
JSONRpcClient.Exception =
function JSONRpcClient_Exception_ctor(code, message, javaStack)
{
this .code = code;
var name;
if (javaStack) {
this .javaStack = javaStack;
var m = javaStack.match( /^ ([ ^ :] * ) / );
if (m) name = m[ 0 ];
}
if (name) this .name = name;
else this .name = " JSONRpcClientException " ;
this .message = message;
};
JSONRpcClient.Exception.CODE_REMOTE_EXCEPTION = 490 ;
JSONRpcClient.Exception.CODE_ERR_CLIENT = 550 ;
JSONRpcClient.Exception.CODE_ERR_PARSE = 590 ;
JSONRpcClient.Exception.CODE_ERR_NOMETHOD = 591 ;
JSONRpcClient.Exception.CODE_ERR_UNMARSHALL = 592 ;
JSONRpcClient.Exception.CODE_ERR_MARSHALL = 593 ;
JSONRpcClient.Exception.prototype = new Error();
JSONRpcClient.Exception.prototype.toString =
function JSONRpcClient_Exception_toString(code, msg)
{
return this .name + " : " + this .message;
};
/* Default top level exception handler */
JSONRpcClient.default_ex_handler =
function JSONRpcClient_default_ex_handler(e) { alert(e); };
/* Client settable variables */
JSONRpcClient.toplevel_ex_handler = JSONRpcClient.default_ex_handler;
JSONRpcClient.profile_async = false ;
JSONRpcClient.max_req_active = 1 ;
JSONRpcClient.requestId = 1 ;
/* JSONRpcClient implementation */
JSONRpcClient.prototype._createMethod =
function JSONRpcClient_createMethod(methodName)
{
var fn = function ()
{
var args = [];
var callback = null ;
for ( var i = 0 ;i < arguments.length;i ++ ) args.push(arguments[i]);
/* TUSCANY change callback to be last arg instead of first to match binding.ajax
if(typeof args[0] == "function") callback = args.shift();
*/
if ( typeof args[arguments.length - 1 ] == " function " ) callback = args.pop();
var req = fn.client._makeRequest.call(fn.client, fn.methodName,
args, callback);
if (callback == null ) {
return fn.client._sendRequest.call(fn.client, req);
} else {
JSONRpcClient.async_requests.push(req);
JSONRpcClient.kick_async();
return req.requestId;
}
};
fn.client = this ;
fn.methodName = methodName;
return fn;
};
JSONRpcClient.prototype._addMethods =
function JSONRpcClient_addMethods(methodNames)
{
for ( var i = 0 ; i < methodNames.length; i ++ ) {
var obj = this ;
var names = methodNames[i].split( " . " );
for ( var n = 0 ; n < names.length - 1 ; n ++ ) {
var name = names[n];
if (obj[name]) {
obj = obj[name];
} else {
obj[name] = new Object();
obj = obj[name];
}
}
var name = names[names.length - 1 ];
if ( ! obj[name]) {
var method = this ._createMethod(methodNames[i]);
obj[name] = method;
}
}
};
JSONRpcClient._getCharsetFromHeaders =
function JSONRpcClient_getCharsetFromHeaders(http)
{
try {
var contentType = http.getResponseHeader( " Content-type " );
var parts = contentType.split( / s * ;s */ );
for ( var i = 0 ; i < parts.length; i ++ ) {
if (parts[i].substring( 0 , 8 ) == " charset= " )
return parts[i].substring( 8 , parts[i].length);
}
} catch (e) {}
return " UTF-8 " ; /* default */
};
/* Async queue globals */
JSONRpcClient.async_requests = [];
JSONRpcClient.async_inflight = {};
JSONRpcClient.async_responses = [];
JSONRpcClient.async_timeout = null ;
JSONRpcClient.num_req_active = 0 ;
JSONRpcClient._async_handler =
function JSONRpcClient_async_handler()
{
JSONRpcClient.async_timeout = null ;
while (JSONRpcClient.async_responses.length > 0 ) {
var res = JSONRpcClient.async_responses.shift();
if (res.canceled) continue ;
if (res.profile) res.profile.dispatch = new Date();
try {
res.cb(res.result, res.ex, res.profile);
} catch (e) {
JSONRpcClient.toplevel_ex_handler(e);
}
}
while (JSONRpcClient.async_requests.length > 0 &&
JSONRpcClient.num_req_active < JSONRpcClient.max_req_active) {
var req = JSONRpcClient.async_requests.shift();
if (req.canceled) continue ;
req.client._sendRequest.call(req.client, req);
}
};
JSONRpcClient.kick_async =
function JSONRpcClient_kick_async()
{
if (JSONRpcClient.async_timeout == null )
JSONRpcClient.async_timeout =
setTimeout(JSONRpcClient._async_handler, 0 );
};
JSONRpcClient.cancelRequest =
function JSONRpcClient_cancelRequest(requestId)
{
/* If it is in flight then mark it as canceled in the inflight map
and the XMLHttpRequest callback will discard the reply. */
if (JSONRpcClient.async_inflight[requestId]) {
JSONRpcClient.async_inflight[requestId].canceled = true ;
return true ;
}
/* If its not in flight yet then we can just mark it as canceled in
the the request queue and it will get discarded before being sent. */
for ( var i in JSONRpcClient.async_requests) {
if (JSONRpcClient.async_requests[i].requestId == requestId) {
JSONRpcClient.async_requests[i].canceled = true ;
return true ;
}
}
/* It may have returned from the network and be waiting for its callback
to be dispatched, so mark it as canceled in the response queue
and the response will get discarded before calling the callback. */
for ( var i in JSONRpcClient.async_responses) {
if (JSONRpcClient.async_responses[i].requestId == requestId) {
JSONRpcClient.async_responses[i].canceled = true ;
return true ;
}
}
return false ;
};
JSONRpcClient.prototype._makeRequest =
function JSONRpcClient_makeRequest(methodName, args, cb)
{
var req = {};
req.client = this ;
req.requestId = JSONRpcClient.requestId ++ ;
var obj = {};
obj.id = req.requestId;
if ( this .objectID)
obj.method = " .obj# " + this .objectID + " . " + methodName;
else
obj.method = methodName;
obj.params = args;
if (cb) req.cb = cb;
if (JSONRpcClient.profile_async)
req.profile = { " submit " : new Date() };
req.data = toJSON(obj);
return req;
};
JSONRpcClient.prototype._sendRequest =
function JSONRpcClient_sendRequest(req)
{
if (req.profile) req.profile.start = new Date();
/* Get free http object from the pool */
var http = JSONRpcClient.poolGetHTTPRequest();
JSONRpcClient.num_req_active ++ ;
/* Send the request */
if ( typeof ( this .user) == " undefined " ) {
http.open( " POST " , this .serverURL, (req.cb != null ));
} else {
http.open( " POST " , this .serverURL, (req.cb != null ), this .user, this .pass);
}
/* setRequestHeader is missing in Opera 8 Beta */
try { http.setRequestHeader( " Content-type " , " text/plain " ); } catch (e) {}
/* Construct call back if we have one */
if (req.cb) {
var self = this ;
http.onreadystatechange = function () {
if (http.readyState == 4 ) {
http.onreadystatechange = function () {};
var res = { " cb " : req.cb, " result " : null , " ex " : null };
if (req.profile) {
res.profile = req.profile;
res.profile.end = new Date();
}
try { res.result = self._handleResponse(http); }
catch (e) { res.ex = e; }
if ( ! JSONRpcClient.async_inflight[req.requestId].canceled)
JSONRpcClient.async_responses.push(res);
delete JSONRpcClient.async_inflight[req.requestId];
JSONRpcClient.kick_async();
}
};
} else {
http.onreadystatechange = function () {};
}
JSONRpcClient.async_inflight[req.requestId] = req;
try {
http.send(req.data);
} catch (e) {
JSONRpcClient.poolReturnHTTPRequest(http);
JSONRpcClient.num_req_active -- ;
throw new JSONRpcClient.Exception
(JSONRpcClient.Exception.CODE_ERR_CLIENT, " Connection failed " );
}
if ( ! req.cb) return this ._handleResponse(http);
};
JSONRpcClient.prototype._handleResponse =
function JSONRpcClient_handleResponse(http)
{
/* Get the charset */
if ( ! this .charset) {
this .charset = JSONRpcClient._getCharsetFromHeaders(http);
}
/* Get request results */
var status, statusText, data;
try {
status = http.status;
statusText = http.statusText;
data = http.responseText;
} catch (e) {
JSONRpcClient.poolReturnHTTPRequest(http);
JSONRpcClient.num_req_active -- ;
JSONRpcClient.kick_async();
throw new JSONRpcClient.Exception
(JSONRpcClient.Exception.CODE_ERR_CLIENT, " Connection failed " );
}
/* Return http object to the pool; */
JSONRpcClient.poolReturnHTTPRequest(http);
JSONRpcClient.num_req_active -- ;
/* Unmarshall the response */
if (status != 200 ) {
throw new JSONRpcClient.Exception(status, statusText);
}
var obj;
try {
eval( " obj = " + data);
} catch (e) {
throw new JSONRpcClient.Exception( 550 , " error parsing result " );
}
if (obj.error)
throw new JSONRpcClient.Exception(obj.error.code, obj.error.msg,
obj.error.trace);
var res = obj.result;
/* Handle CallableProxy */
if (res && res.objectID && res.JSONRPCType == " CallableReference " )
return new JSONRpcClient( this .serverURL, this .user,
this .pass, res.objectID);
return res;
};
/* XMLHttpRequest wrapper code */
/* XMLHttpRequest pool globals */
JSONRpcClient.http_spare = [];
JSONRpcClient.http_max_spare = 8 ;
JSONRpcClient.poolGetHTTPRequest =
function JSONRpcClient_pool_getHTTPRequest()
{
if (JSONRpcClient.http_spare.length > 0 ) {
return JSONRpcClient.http_spare.pop();
}
return JSONRpcClient.getHTTPRequest();
};
JSONRpcClient.poolReturnHTTPRequest =
function JSONRpcClient_poolReturnHTTPRequest(http)
{
if (JSONRpcClient.http_spare.length >= JSONRpcClient.http_max_spare)
delete http;
else
JSONRpcClient.http_spare.push(http);
};
JSONRpcClient.msxmlNames = [ " MSXML2.XMLHTTP.5.0 " ,
" MSXML2.XMLHTTP.4.0 " ,
" MSXML2.XMLHTTP.3.0 " ,
" MSXML2.XMLHTTP " ,
" Microsoft.XMLHTTP " ];
JSONRpcClient.getHTTPRequest =
function JSONRpcClient_getHTTPRequest()
{
/* Mozilla XMLHttpRequest */
try {
JSONRpcClient.httpObjectName = " XMLHttpRequest " ;
return new XMLHttpRequest();
} catch (e) {}
/* Microsoft MSXML ActiveX */
for ( var i = 0 ;i < JSONRpcClient.msxmlNames.length; i ++ ) {
try {
JSONRpcClient.httpObjectName = JSONRpcClient.msxmlNames[i];
return new ActiveXObject(JSONRpcClient.msxmlNames[i]);
} catch (e) {}
}
/* None found */
JSONRpcClient.httpObjectName = null ;
throw new JSONRpcClient.Exception( 0 , " Can't create XMLHttpRequest object " );
};
bindingjsonrpc = " loaded " ;
< project name ="store" default ="compile" >
< property name ="test.class" value ="launch.Launch" />
< property name ="test.jar" value ="sample-store.jar" />
< target name ="init" >
< mkdir dir ="target/classes" />
</ target >
< target name ="compile" depends ="init" >
< javac srcdir ="src"
destdir ="target/classes"
debug ="on"
source ="1.6"
target ="1.6"
encoding ="UTF-8" >
< classpath >
< pathelement location ="lib/tuscany-sca-manifest.jar" />
</ classpath >
</ javac >
< copy todir ="target/classes" >
< fileset dir ="resources" />
</ copy >
< jar destfile ="target/${test.jar}" basedir ="target/classes" >
< manifest >
< attribute name ="Main-Class" value ="${test.class}" />
</ manifest >
</ jar >
</ target >
< target name ="run-classes" >
< java classname ="${test.class}"
fork ="true" >
< classpath >
< pathelement path ="target/classes" />
< pathelement location ="lib/tuscany-sca-manifest.jar" />
</ classpath >
</ java >
</ target >
< target name ="run" >
< java classname ="${test.class}"
fork ="true" >
< classpath >
< pathelement path ="target/${test.jar}" />
< pathelement location ="lib/tuscany-sca-manifest.jar" />
</ classpath >
</ java >
</ target >
< target name ="clean" >
< delete quiet ="true" includeemptydirs ="true" >
< fileset dir ="target" />
</ delete >
</ target >
</ project >
import org.apache.tuscany.sca.host.embedded.SCADomain;
public class Launch {
public static void main(String[] args) throws Exception {
System.out.println( " Starting ... " );
SCADomain scaDomain = SCADomain.newInstance( " store.composite " );
System.out.println( " store.composite ready for big business !!! " );
System.out.println();
System.in.read();
scaDomain.close();
}
}
if (feed != null ) {
var entries = feed.getElementsByTagName( " entry " );
var list = "" ;
alert(entries.length);
for ( var i = 0 ; i < entries.length; i ++ ) {
var item = entries[i].getElementsByTagName( " content " )[ 0 ].firstChild.nodeValue;
list += item + ' <br> ' ;
}
document.getElementById( " shoppingCart " ).innerHTML = list;
document.getElementById( ' total ' ).innerHTML = feed.getElementsByTagName( " subtitle " )[ 0 ].firstChild.nodeValue;
}
}
该应用是由四个服务组成的,这个应用是一个在线商店,这里有一个目录服务,你可以通过它取得项目名单,依靠currencyCode属性来判断是以美元还是欧元提供项目价格,目录服务本身不去做货币换算的工作,相反它引用了一个CurrencyConverter服务去完成这个工作。接下来,这里还有一个ShoppingCart服务,从目录选择了的项目可以被加进去(购物车),它是使用REST实现的;Catalog使用的是一个JSONRPC绑定,ShoppingCart呢则是通过ATOM进行绑定,最后,就是提供给用户的、基于浏览器的界面服务的Store组件了,Store服务组件分别通过JSONRPC和ATOM绑定使用Catalog和ShoppingCart服务。
创建一个Java工程
这一步你要在Eclipse中建立一个Java工程,点击工具栏上的New Java Project按钮 来打开新建工程的对话框,接下来输入store作为工程名称,并选择Create separate
folders for sources and class files:
点击下一步按钮,在接下来的窗口打开Libraries选项卡,点击Add Library...按钮以添加Tuscany Libraray到工程中:
最后,点击Finish按钮结束工程创建。
构建服务
首先,创建两个包目录,以便在接下来的步骤中存放服务的实现。选择“store”工程,点击工具栏上的新建Java包按钮 启动创建包对话框。接下来,输入services作为包名,点击Finish按钮关闭对话框。
记下来,会在services包内放入普通的服务,ufservices内是界面相关服务。
Catalog
现在,准备创建Catalog服务的接口和实现。
选择“services”包,接下来在工具栏的下拉菜单中点击“New Java Class” 按钮 和“New Java Interface”按钮 ,在弹出的对话框中以“Catalog”作为接口名,并点击Finish关闭对话框,这时在Java编辑器中就会打开新增的Java接口,将下面这段Java接口代码Copy-Paste到编辑器内:
import org.osoa.sca.annotations.Remotable;
@Remotable
public interface Catalog {
String[] get();
}
再次选中“services”包,点击“New Java Class”按钮 ,在弹出的对话框中以“CatalogImpl”作为类的名字,将“Catalog”作为该类的实现接口,点击Finish完成。
在Java编辑器中会打开我们新增的类,将下面的代码复制过去:
import java.util.ArrayList;
import java.util.List;
import org.osoa.sca.annotations.Init;
import org.osoa.sca.annotations.Property;
import org.osoa.sca.annotations.Reference;
public class CatalogImpl implements Catalog {
@Property
public String currencyCode = " USD " ;
@Reference
public CurrencyConverter currencyConverter;
private List < String > catalog = new ArrayList < String > ();
@Init
public void init() {
String currencySymbol = currencyConverter.getCurrencySymbol(currencyCode);
catalog.add( " Apple - " + currencySymbol +
currencyConverter.getConversion( " USD " , currencyCode, 2.99f ));
catalog.add( " Orange - " + currencySymbol +
currencyConverter.getConversion( " USD " , currencyCode, 3.55f ));
catalog.add( " Pear - " + currencySymbol +
currencyConverter.getConversion( " USD " , currencyCode, 1.55f ));
}
public String[] get() {
String[] catalogArray = new String[catalog.size()];
catalog.toArray(catalogArray);
return catalogArray;
}
}
在这一步,我们将创建CurrencyConverter的接口和实现,首先,按照之前的方式建立接口和类文件,并将下面的代码复制过去:
import org.osoa.sca.annotations.Remotable;
@Remotable
public interface CurrencyConverter {
public float getConversion(String fromCurrenycCode,
String toCurrencyCode, float amount);
public String getCurrencySymbol(String currencyCode);
}
public class CurrencyConverterImpl implements CurrencyConverter {
public float getConversion(String fromCurrencyCode,
String toCurrencyCode, float amount) {
if (toCurrencyCode.equals( " USD " ))
return amount;
else if (toCurrencyCode.equals( " EUR " ))
return amount * 0.7256f ;
return 0 ;
}
public String getCurrencySymbol(String currencyCode) {
if (currencyCode.equals( " USD " ))
return " $ " ;
else
if (currencyCode.equals( " EUR " ))
return " € " ;
return " ? " ;
}
}
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.tuscany.sca.binding.feed.collection.Collection;
import org.apache.tuscany.sca.binding.feed.collection.NotFoundException;
import com.sun.syndication.feed.atom.Content;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.feed.atom.Link;
public class ShoppingCartImpl implements Collection {
// needs to change to instance var once conversation scope works
private static Map < String, Entry > cart = new HashMap < String, Entry > ();
public Feed getFeed() {
Feed feed = new Feed();
feed.setTitle( " shopping cart " );
Content subtitle = new Content();
subtitle.setValue( " Total : " + getTotal());
feed.setSubtitle(subtitle);
feed.getEntries().addAll(cart.values());
return feed;
}
public Entry get(String id) throws NotFoundException {
return cart.get(id);
}
public Entry post(Entry entry) {
String id = " cart- " + UUID.randomUUID().toString();
entry.setId(id);
Link link = new Link();
link.setRel( " edit " );
link.setHref( "" + id);
entry.getOtherLinks().add(link);
link = new Link();
link.setRel( " alternate " );
link.setHref( "" + id);
entry.getAlternateLinks().add(link);
entry.setCreated( new Date());
cart.put(id, entry);
return entry;
}
public void put(String id, Entry entry) throws NotFoundException {
entry.setUpdated( new Date());
cart.put(id, entry);
}
public void delete(String id) throws NotFoundException {
if (id.equals( "" ))
cart.clear();
else
cart.remove(id);
} private String getTotal() {
float total = 0 ;
String symbol = "" ;
if ( ! cart.isEmpty()) {
Entry entry = cart.values().iterator().next();
String item = ((Content)entry.getContents().get( 0 )).getValue();
symbol = item.substring(item.indexOf( " - " ) + 2 , item.indexOf( " - " ) + 3 );
}
for (Entry entry : cart.values()) {
String item = ((Content)entry.getContents().get( 0 )).getValue();
total += Float.valueOf(item.substring(item.indexOf( " - " ) + 3 ));
}
return symbol + String.valueOf(total);
}
}
< head >
< title > Store </ TITLE >
< script type ="text/javascript" src ="store.js" ></ script >
< script language ="JavaScript" >
// Reference
catalog = ( new JSONRpcClient( " ../Catalog " )).Catalog;
// Reference
shoppingCart = new AtomClient( " ../ShoppingCart " );
function catalog_getResponse(items) {
var catalog = "" ;
for ( var i = 0 ; i < items.length; i ++ )
catalog += ' <input name="items" type="checkbox" value=" ' +
items[i] + ' "> ' + items[i] + ' <br> ' ;
document.getElementById( ' catalog ' ).innerHTML = catalog;
}
function shoppingCart_getResponse(feed) {
if (feed != null ) {
var entries = feed.getElementsByTagName( " entry " );
var list = "" ;
for ( var i = 0 ; i < entries.length; i ++ ) {
var item = entries[i].getElementsByTagName( " content " )[ 0 ].firstChild.nodeValue;
list += item + ' <br> ' ;
}
document.getElementById( " shoppingCart " ).innerHTML = list;
document.getElementById( ' total ' ).innerHTML = feed.getElementsByTagName( " subtitle " )[ 0 ].firstChild.nodeValue;
}
}
function shoppingCart_postResponse(entry) {
shoppingCart.get( "" , shoppingCart_getResponse);
}
function addToCart() {
var items = document.catalogForm.items;
var j = 0 ;
for ( var i = 0 ; i < items.length; i ++ )
if (items[i].checked) {
var entry = ' <entry xmlns="http://www.w3.org/2005/Atom"><title>cart-item</title><content type="text"> ' + items[i].value + ' </content></entry> '
shoppingCart.post(entry, shoppingCart_postResponse);
items[i].checked = false ;
}
}
function checkoutCart() {
document.getElementById( ' store ' ).innerHTML = ' <h2> ' +
' Thanks for Shopping With Us!</h2> ' +
' <h2>Your Order</h2> ' +
' <form name="orderForm" action="store.html"> ' +
document.getElementById( ' shoppingCart ' ).innerHTML +
' <br> ' +
document.getElementById( ' total ' ).innerHTML +
' <br> ' +
' <br> ' +
' <input type="submit" value="Continue Shopping"> ' +
' </form> ' ;
shoppingCart.del( "" , null );
}
function deleteCart() {
shoppingCart.del( "" , null );
document.getElementById( ' shoppingCart ' ).innerHTML = "" ;
document.getElementById( ' total ' ).innerHTML = "" ;
}
catalog.get(catalog_getResponse);
shoppingCart.get( "" , shoppingCart_getResponse);
</ script >
</ head >
< body >
< h1 > Store </ h1 >
< div id ="store" >
< h2 > Catalog </ h2 >
< form name ="catalogForm" >
< div id ="catalog" ></ div >
< br >
< input type ="button" onClick ="addToCart()" value ="Add to Cart" >
</ form >
< br >
< h2 > Your Shopping Cart </ h2 >
< form name ="shoppingCartForm" >
< div id ="shoppingCart" ></ div >
< br >
< div id ="total" ></ div >
< br >
< input type ="button" onClick ="checkoutCart()" value ="Checkout" >
< input type ="button" onClick ="deleteCart()" value ="Empty" >
< a href ="../ShoppingCart/" > (feed) </ a >
</ form >
</ div >
</ body >
</ html >