diff options
23 files changed, 1047 insertions, 42 deletions
diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index fd06b83678..e44bc181ec 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -900,6 +900,7 @@ AC_CONFIG_FILES([Makefile modules/openid/Makefile modules/oauth/Makefile modules/wsgi/Makefile + modules/edit/Makefile components/Makefile components/cache/Makefile components/log/Makefile diff --git a/sca-cpp/trunk/modules/Makefile.am b/sca-cpp/trunk/modules/Makefile.am index a0fa000791..278d8b40cc 100644 --- a/sca-cpp/trunk/modules/Makefile.am +++ b/sca-cpp/trunk/modules/Makefile.am @@ -15,5 +15,5 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = scheme atom rss js json scdl http server python java openid oauth wsgi +SUBDIRS = scheme atom rss js json scdl http server python java openid oauth wsgi edit diff --git a/sca-cpp/trunk/modules/edit/Makefile.am b/sca-cpp/trunk/modules/edit/Makefile.am new file mode 100644 index 0000000000..0bc94880eb --- /dev/null +++ b/sca-cpp/trunk/modules/edit/Makefile.am @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +moddir = $(prefix)/modules/js +nobase_dist_mod_DATA = htdocs/*.js htdocs/*.html +EXTRA_DIST = htdocs/*.js htdocs/*.html + diff --git a/sca-cpp/trunk/modules/edit/apps.py b/sca-cpp/trunk/modules/edit/apps.py new file mode 100644 index 0000000000..920bb635e6 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/apps.py @@ -0,0 +1,48 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Workspace collection implementation +import uuid +import sys +from util import * + +# Convert an id to an app id +def appid(id): + return ("'" + car(id), "'app.composite") + +# Post a new app to the domains db +def post(collection, app, cache): + id = appid((str(uuid.uuid1()),)) + cache.put((id,), app) + return id + +# Put an app into the domains db +def put(id, app, cache): + cache.put(appid(id), app) + return True + +# Get an app from the domains db +def get(id, cache): + if isNil(id): + return ("Apps", "apps") + return (car(id), car(id), cache.get(appid(id))) + +# Delete an app from the domains db +def delete(id, cache): + cache.delete(appid(id)) + return True + diff --git a/sca-cpp/trunk/modules/edit/dashboard.py b/sca-cpp/trunk/modules/edit/dashboard.py new file mode 100644 index 0000000000..c93924b68e --- /dev/null +++ b/sca-cpp/trunk/modules/edit/dashboard.py @@ -0,0 +1,82 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Workspace collection implementation +import uuid +import sys +from util import * + +# Convert a particular user email to a workspace id +def workspaceid(user): + return ("'" + user.id(),) + +# Get a workspace from the cache +def getworkspace(id, cache): + workspace = cache.get(id) + if isNil(workspace): + return () + return workspace + +# Post a new app to the user's workspace +def post(collection, app, user, cache): + id = (str(uuid.uuid1()),) + workspace = cons((car(app), id, caddr(app)), getworkspace(workspaceid(user), cache)) + cache.put(workspaceid(user), workspace) + return id + +# Put an app into the user's workspace +def put(id, app, user, cache): + def putapp(app, workspace): + if isNil(workspace): + return (app,) + if cadr(app) == cadr(car(workspace)): + return cons(app, cdr(workspace)) + return cons(car(workspace), putapp(app, cdr(workspace))) + + workspace = putapp(app, getworkspace(workspaceid(user), cache)) + cache.put(workspaceid(user), workspace) + return True + +# Get apps from the user's workspace +def get(id, user, cache): + def findapp(id, workspace): + if isNil(workspace): + return None + if id == cadr(car(workspace)): + return car(workspace) + return findapp(id, cdr(workspace)) + + if isNil(id): + return ("Your Apps", user.id()) + getworkspace(workspaceid(user), cache) + return findapp(car(id), getworkspace(workspaceid(user), cache)) + +# Delete apps from the user's workspace +def delete(id, user, cache): + if isNil(id): + return cache.delete(workspaceid(user)) + + def deleteapp(id, workspace): + if isNil(workspace): + return () + if id == cadr(car(workspace)): + return cdr(workspace) + return cons(car(workspace), deleteapp(id, cdr(workspace))) + + workspace = deleteapp(id, getworkspace(workspaceid(user), cache)) + cache.put(workspaceid(user), workspace) + return True + diff --git a/sca-cpp/trunk/modules/edit/domains/relay/app.composite b/sca-cpp/trunk/modules/edit/domains/relay/app.composite new file mode 100644 index 0000000000..7f7302955e --- /dev/null +++ b/sca-cpp/trunk/modules/edit/domains/relay/app.composite @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://relay" + name="relay"> + + <component name="JSONTwit"> + <t:implementation.python script="relay.py"/> + <service name="Relay"> + <t:binding.http uri="jsontwit"/> + </service> + <reference name="target"> + <t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.json?screen_name=jsdelfino"/> + </reference> + </component> + + <component name="XMLTwit"> + <t:implementation.python script="relay.py"/> + <service name="Relay"> + <t:binding.http uri="xmltwit"/> + </service> + <reference name="target"> + <t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=jsdelfino"/> + </reference> + </component> + + <component name="RSSTwit"> + <t:implementation.python script="relay.py"/> + <service name="Relay"> + <t:binding.http uri="rsstwit"/> + </service> + <reference name="target"> + <t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=jsdelfino"/> + </reference> + </component> + + <component name="HTML"> + <t:implementation.python script="relay.py"/> + <service name="Relay"> + <t:binding.http uri="html"/> + </service> + <reference name="target"> + <t:binding.http uri="http://people.apache.org/~jsdelfino/"/> + </reference> + </component> + + <component name="JSONFB"> + <t:implementation.python script="relay.py"/> + <service name="Relay"> + <t:binding.http uri="jsonfb"/> + </service> + <reference name="target"> + <t:binding.http uri="https://graph.facebook.com/100001053301307"/> + </reference> + </component> + +</composite> diff --git a/sca-cpp/trunk/modules/edit/domains/store/app.composite b/sca-cpp/trunk/modules/edit/domains/store/app.composite new file mode 100644 index 0000000000..912898123b --- /dev/null +++ b/sca-cpp/trunk/modules/edit/domains/store/app.composite @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://store" + name="store"> + + <component name="Store"> + <t:implementation.python script="store.py"/> + <service name="Widget"> + <t:binding.http uri="store"/> + </service> + <reference name="catalog" target="Catalog"/> + <reference name="shoppingCart" target="ShoppingCart/Cart"/> + <reference name="shoppingTotal" target="ShoppingCart/Total"/> + </component> + + <component name="Catalog"> + <t:implementation.python script="fruits-catalog.py"/> + <property name="currencyCode">USD</property> + <service name="Catalog"> + <t:binding.jsonrpc uri="catalog"/> + </service> + <reference name="currencyConverter" target="CurrencyConverter"/> + </component> + + <component name="ShoppingCart"> + <t:implementation.python script="shopping-cart.py"/> + <service name="ShoppingCart"> + <t:binding.atom uri="shoppingCart"/> + </service> + <service name="Total"> + <t:binding.jsonrpc uri="total"/> + </service> + <reference name="cache" target="Cache"/> + </component> + + <component name="CurrencyConverter"> + <t:implementation.python script="currency-converter.py"/> + <service name="CurrencyConverter"> + <t:binding.jsonrpc uri="currencyConverter"/> + </service> + </component> + + <component name="Cache"> + <implementation.cpp path="../../components/cache" library="libmemcache"/> + <service name="Cache"> + <t:binding.atom uri="cache"/> + </service> + <property name="servers">localhost:11211</property> + </component> + +</composite> diff --git a/sca-cpp/trunk/modules/edit/edit-conf b/sca-cpp/trunk/modules/edit/edit-conf new file mode 100755 index 0000000000..042dd9e139 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/edit-conf @@ -0,0 +1,37 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Generate a server conf +here=`readlink -f $0`; here=`dirname $here` +mkdir -p $1 +root=`readlink -f $1` + +cat >>$root/conf/httpd.conf <<EOF +# Generated by: edit-conf $* + +# Serve JavaScript client scripts +Alias /graph.js $here/htdocs/graph.js + +<Location /graph.js> +AuthType None +Require all granted +</Location> + +EOF + diff --git a/sca-cpp/trunk/modules/edit/edit.composite b/sca-cpp/trunk/modules/edit/edit.composite new file mode 100644 index 0000000000..c73ac82037 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/edit.composite @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://edit" + name="edit"> + + <component name="User"> + <t:implementation.python script="user.py"/> + <property name="user">?</property> + <property name="email">joe@localhost</property> + <property name="nickname">?</property> + <property name="fullname">?</property> + <property name="firstname">?</property> + <property name="lastname">?</property> + <property name="realm">?</property> + <service name="User"> + <t:binding.http uri="user"/> + </service> + </component> + + <component name="EditWidget"> + <t:implementation.widget location="/index.html"/> + <reference name="dashboard" target="Dashboard"/> + <reference name="apps" target="Apps"/> + </component> + + <component name="Dashboard"> + <t:implementation.python script="dashboard.py"/> + <service name="Dashboard"> + <t:binding.http uri="dashboard"/> + </service> + <reference name="user" target="User"/> + <reference name="cache" target="WorkspaceCache"/> + </component> + + <component name="Apps"> + <t:implementation.python script="apps.py"/> + <service name="Apps"> + <t:binding.http uri="apps"/> + </service> + <reference name="cache" target="DomainCache"/> + </component> + + <component name="WorkspaceCache"> + <implementation.cpp path="../../components/cache" library="libdatacache"/> + <service name="WorkspaceCache"> + <t:binding.http uri="workspacecache"/> + </service> + <reference name="l1reader" target="Memcache"/> + <reference name="l1writer" target="Memcache"/> + <reference name="l2reader" target="WorkspaceDB"/> + <reference name="l2writer" target="WorkspaceDB"/> + </component> + + <component name="WorkspaceDB"> + <implementation.cpp path="../../components/filedb" library="libfiledb"/> + <property name="dbname">workspaces</property> + <property name="format">scheme</property> + <service name="WorkspaceDB"> + <t:binding.http uri="workspaces"/> + </service> + </component> + + <component name="DomainCache"> + <implementation.cpp path="../../components/cache" library="libdatacache"/> + <service name="DomainCache"> + <t:binding.http uri="domaincache"/> + </service> + <reference name="l1reader" target="Memcache"/> + <reference name="l1writer" target="Memcache"/> + <reference name="l2reader" target="DomainDB"/> + <reference name="l2writer" target="DomainDB"/> + </component> + + <component name="DomainDB"> + <implementation.cpp path="../../components/filedb" library="libfiledb"/> + <property name="dbname">domains</property> + <property name="format">xml</property> + <service name="DomainDB"> + <t:binding.http uri="domains"/> + </service> + </component> + + <component name="Memcache"> + <implementation.cpp path="../../components/cache" library="libmemcache"/> + <service name="Memcache"> + <t:binding.http uri="memcache"/> + </service> + <property name="servers">localhost:11211</property> + </component> + +</composite> diff --git a/sca-cpp/trunk/modules/edit/htdocs/edit/edit.html b/sca-cpp/trunk/modules/edit/htdocs/edit/edit.html new file mode 100644 index 0000000000..5e1e41bf5c --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/edit/edit.html @@ -0,0 +1,69 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<html> +<head> +<link rel="stylesheet" type="text/css" href="/ui.css"> +<script type="text/javascript" src="/util.js"></script> +<script type="text/javascript" src="/elemutil.js"></script> +<script type="text/javascript" src="/xmlutil.js"></script> +<script type="text/javascript" src="/atomutil.js"></script> +<script type="text/javascript" src="/scdl.js"></script> +<script type="text/javascript" src="/ui.js"></script> +<script type="text/javascript" src="/component.js"></script> +<script type="text/javascript" src="/graph.js"></script> +</head> +<body> + +<script type="text/javascript"> +var editWidget = sca.component("EditWidget"); +var dashboard = sca.reference(editWidget, "dashboard"); +var apps = sca.reference(editWidget, "apps"); + +if (false) { +dashboard.get('', function(doc) { + var entries = cddr(atom.readATOMFeedDocument(doc)); + var entry = car(entries); + var item = caddr(entry); + var composite = cddr(item); + var comps = scdl.components(composite); + + var g = graph.mkgraph(); + var shapes = graph.composite(composite); + log(shapes); + for (var s in shapes) + g.appendChild(shapes[s]); +}); +} + +apps.get('store', function(doc) { + var entry = atom.readATOMEntryDocument(doc); + var item = caddr(entry); + var composite = cddr(item); + var comps = scdl.components(composite); + + var g = graph.mkgraph(); + var shapes = graph.composite(composite); + log(shapes); + for (var s in shapes) + g.appendChild(shapes[s]); +}); + +</script> +</body> +</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/edit/index.html b/sca-cpp/trunk/modules/edit/htdocs/edit/index.html new file mode 100644 index 0000000000..7cdfcd81a4 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/edit/index.html @@ -0,0 +1,33 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<html> +<head> +<title>App Editor</title> +<link rel="stylesheet" type="text/css" href="/ui.css"> +<script type="text/javascript" src="/util.js"></script> +<script type="text/javascript" src="/ui.js"></script> +</head> +<body> +<iframe id="editFrame" src="edit.html" style="visibility: visible; height: 100%; width: 100%; border: 0px;" scrolling="no" frameborder="0"></iframe> + +<script type="text/javascript"> +</script> +</body> +</html> + diff --git a/sca-cpp/trunk/modules/js/htdocs/graph.js b/sca-cpp/trunk/modules/edit/htdocs/graph.js index 883b3aa801..20f71a5dd4 100644 --- a/sca-cpp/trunk/modules/js/htdocs/graph.js +++ b/sca-cpp/trunk/modules/edit/htdocs/graph.js @@ -46,12 +46,19 @@ graph.supportsSVG = function() { /** * Basic colors */ -graph.red = 'red'; -graph.green = 'green'; -graph.blue = 'blue'; -graph.yellow = 'yellow'; -graph.orange = '#ffa500'; -graph.gray = 'gray' +graph.colors = new Object(); +graph.colors.black = '#000000'; +graph.colors.blue = '#0000ff'; +graph.colors.cyan = '#00ffff'; +graph.colors.gray = '#808080' +graph.colors.green = '#008000'; +graph.colors.magenta = '#008000'; +graph.colors.orange = '#ffa500'; +graph.colors.pink = '#ffc0cb'; +graph.colors.purple = '#800080'; +graph.colors.red = '#ff0000'; +graph.colors.white = '#ffffff'; +graph.colors.yellow = '#ffff00'; /** * Base path class. @@ -204,10 +211,13 @@ if (graph.supportsVML()) { /** * Make a title element. */ - graph.mktitle = function(t) { + graph.mktitle = function(comp) { + var t = scdl.name(comp); + var tsvcs = graph.tsvcs(comp); + var lsvcs = graph.lsvcs(comp); var title = document.createElement('v:textbox'); - title.style.left = '25'; - title.style.top = '5'; + title.style.left = '' + (isNil(lsvcs)? 7 : 27); + title.style.top = '' + (isNil(tsvcs)? 5 : 25); title.style.position = 'absolute'; var tnode = document.createTextNode(t); title.appendChild(tnode); @@ -217,7 +227,8 @@ if (graph.supportsVML()) { /** * Return the width of a title. */ - graph.titlewidth = function(t) { + graph.titlewidth = function(comp) { + var t = scdl.name(comp); graph.textWidthDiv.innerHTML = t; var twidth = graph.textWidthDiv.offsetWidth; graph.textWidthDiv.innerHTML = ''; @@ -228,8 +239,7 @@ if (graph.supportsVML()) { * Make a component shape. */ graph.mkcompshape = function(comp, cassoc) { - var name = scdl.name(comp); - var title = graph.mktitle(name); + var title = graph.mktitle(comp); var d = graph.mkcomppath(comp, cassoc).str(); @@ -247,8 +257,8 @@ if (graph.supportsVML()) { contour.coordsize = '500,500'; contour.setAttribute('path', d); contour.filled = 'false'; - contour.strokecolor = graph.gray; - contour.strokeweight = '3'; + contour.strokecolor = graph.colors.gray; + contour.strokeweight = '2'; contour.style.top = 1; contour.style.left = 1; var stroke = document.createElement('v:stroke'); @@ -381,7 +391,8 @@ if (graph.supportsSVG()) { /** * Make a title element. */ - graph.mktitle = function(t) { + graph.mktitle = function(comp) { + var t = scdl.name(comp); var title = document.createElementNS(graph.svgns, 'text'); title.setAttribute('text-anchor', 'start'); title.setAttribute('x', 5); @@ -394,8 +405,8 @@ if (graph.supportsSVG()) { /** * Return a width of a title. */ - graph.titlewidth = function(t) { - var title = graph.mktitle(t); + graph.titlewidth = function(comp) { + var title = graph.mktitle(comp); var width = title.getBBox().width; graph.textWidthSvg.removeChild(title); return width; @@ -405,8 +416,7 @@ if (graph.supportsSVG()) { * Make a component shape. */ graph.mkcompshape = function(comp, cassoc) { - var name = scdl.name(comp); - var title = graph.mktitle(name); + var title = graph.mktitle(comp); var d = graph.mkcomppath(comp, cassoc).str(); @@ -417,7 +427,7 @@ if (graph.supportsSVG()) { var contour = document.createElementNS(graph.svgns, 'path'); contour.setAttribute('d', d); contour.setAttribute('fill', 'none'); - contour.setAttribute('stroke', graph.gray); + contour.setAttribute('stroke', graph.colors.gray); contour.setAttribute('stroke-width', '4'); contour.setAttribute('stroke-opacity', '0.20'); contour.setAttribute('transform', 'translate(1,1)'); @@ -491,7 +501,7 @@ graph.rrefs = function(comp) { */ graph.color = function(comp) { var c = scdl.color(comp); - return c == null? graph.blue : c; + return c == null? graph.colors.blue : graph.colors[c]; } /** @@ -548,7 +558,7 @@ graph.refswidth = function(refs, cassoc) { * Return the width of a component. */ graph.compwidth = function(comp, cassoc) { - var twidth = graph.titlewidth(scdl.name(comp)) + 20; + var twidth = graph.titlewidth(comp) + 20; var tsvcs = graph.tsvcs(comp); var tsvcsw = Math.max(1, length(tsvcs)) * 60 + 20; var brefs = graph.brefs(comp); diff --git a/sca-cpp/trunk/modules/edit/htdocs/index.html b/sca-cpp/trunk/modules/edit/htdocs/index.html new file mode 100644 index 0000000000..3c18fdbd47 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/index.html @@ -0,0 +1,38 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<html> +<head> +<title>App Edit Tools</title> +<link rel="stylesheet" type="text/css" href="/ui.css"> +<script type="text/javascript" src="/util.js"></script> +<script type="text/javascript" src="/ui.js"></script> +</head> +<body> +<h1>App Edit Tools</h1> +<p>This module implements simple tools to help you create Tuscany apps.</p> + +<h2>App Dashboard</h1> +<p>Try the <a href="main">App Dashboard</a> to manage your collection of apps.</p> + +<h2>App Editor</h1> +<p>Try the <a href="edit">App Editor</a> to edit an app.</p> + +</body> +</html> + diff --git a/sca-cpp/trunk/modules/edit/htdocs/main/dashboard.html b/sca-cpp/trunk/modules/edit/htdocs/main/dashboard.html new file mode 100644 index 0000000000..a5e5b12aef --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/main/dashboard.html @@ -0,0 +1,104 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<html> +<head> +<link rel="stylesheet" type="text/css" href="/ui.css"> +<script type="text/javascript" src="/util.js"></script> +<script type="text/javascript" src="/elemutil.js"></script> +<script type="text/javascript" src="/xmlutil.js"></script> +<script type="text/javascript" src="/atomutil.js"></script> +<script type="text/javascript" src="/scdl.js"></script> +<script type="text/javascript" src="/ui.js"></script> +<script type="text/javascript" src="/component.js"></script> +</head> +<body> +<div id="dashboard"> + +<form id="appsForm"> +<div id="apps"></div> +<br/> +><a href="" id="addAppLink">Add</a> <a href="" id="deleteAppLink">Delete</a> +</form> + +<div id="newApp" style="visibility: hidden;"> +<form id="newAppForm"> +<table width="100%"> +<tr><th>Add a New App</th></tr> +<tr><td>Add a new App to your dashboard.</td></tr> +</table> +<br> + +<table> +<tr><td>App name:</td><td><input type="text" name="appName" size="50"/></td></td><td>e.g. mycoolapp</td></tr> +<tr><td>Title:</td><td><input type="text" name="appTitle" size="50"/></td></td><td>e.g. My really cool app</td></tr> +</table> +<input id="addAppButton" type="button" value="Add"/> +</form> +</div> + +</div> + +<script type="text/javascript"> +ui.installwidget(); + +var editWidget = sca.component("EditWidget"); +var dashboard = sca.reference(editWidget, "dashboard"); + +// Get and display list of apps +dashboard.get('', function(doc) { + var apps = ''; + apps += '<table width="100%">'; + apps += '<tr><th>App</th><th>Title</th></tr>'; + + var entries = cddr(atom.readATOMFeedDocument(doc)); + for (var i = 0; i < length(entries); i++) { + var entry = entries[i]; + var item = caddr(entry); + var composite = cddr(item); + var comps = scdl.components(composite); + + name = cadr(entry); + title = car(entry); + + apps += '<tr>'; + apps += '<td><input name="apps" type="checkbox" value="' + name + '">' + '<a href=\"' + '/edit/?app=' + name + '\">' + name + '</a></td>'; + apps += '<td class="tdw">' + title + '</td>'; + apps += '</tr>'; + } + apps += '</table>'; + $('apps').innerHTML = apps; + +}); + +// Toggle new app form +$('addAppLink').onclick = function() { + var div = $('newApp'); + div.style.visibility = div.style.visibility == 'hidden'? 'visible' : 'hidden'; + return false; +}; + +// Add a new app +$('addAppButton').onclick = function() { + alert('Add new app'); + return false; +}; + +</script> +</body> +</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/main/index.html b/sca-cpp/trunk/modules/edit/htdocs/main/index.html new file mode 100644 index 0000000000..13b2662645 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/main/index.html @@ -0,0 +1,36 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<html> +<head> +<title>App Dashboard</title> +<link rel="stylesheet" type="text/css" href="/ui.css"> +<script type="text/javascript" src="/util.js"></script> +<script type="text/javascript" src="/ui.js"></script> +</head> +<body> +<h1>Welcome to your App Dashboard!</h1> +<div id="dashboard"></div> +<iframe id="dashboardFrame" src="dashboard.html"></iframe> + +<script type="text/javascript"> +ui.bindwidget('dashboardFrame', 'dashboard'); +</script> +</body> +</html> + diff --git a/sca-cpp/trunk/modules/edit/start-test b/sca-cpp/trunk/modules/edit/start-test new file mode 100755 index 0000000000..f541ffba9b --- /dev/null +++ b/sca-cpp/trunk/modules/edit/start-test @@ -0,0 +1,35 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Setup +../../components/cache/memcached-start 11211 + +../http/httpd-conf tmp localhost 8090 htdocs +../server/server-conf tmp +../python/python-conf tmp +./edit-conf tmp +cat >>tmp/conf/httpd.conf <<EOF +# Configure SCA Composite +SCAContribution `pwd`/ +SCAComposite edit.composite + +EOF + +../http/httpd-start tmp + diff --git a/sca-cpp/trunk/modules/edit/stop-test b/sca-cpp/trunk/modules/edit/stop-test new file mode 100755 index 0000000000..bc831c18a6 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/stop-test @@ -0,0 +1,22 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +../http/httpd-stop tmp +../../components/cache/memcached-stop 11211 + diff --git a/sca-cpp/trunk/modules/edit/user.py b/sca-cpp/trunk/modules/edit/user.py new file mode 100644 index 0000000000..2eb65a8ea4 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/user.py @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# User info service component + +# Return the user id +def id(user, email, nick, full, first, last, realm): + if email.eval() != '?': + return email.eval() + if nick.eval() != '?': + return nick.eval() + '@' + realm.eval() + return user.eval() + '@' + realm.eval() + diff --git a/sca-cpp/trunk/modules/edit/util.py b/sca-cpp/trunk/modules/edit/util.py new file mode 100644 index 0000000000..80bc7db101 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/util.py @@ -0,0 +1,158 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Simple utility functions +from sys import maxint + +# Scheme-like lists +def cons(a, b): + return (a,) + b + +def car(l): + return l[0] + +def first(l): + return car(l) + +def cdr(l): + return l[1:] + +def rest(l): + return cdr(l) + +def cadr(l): + return car(cdr(l)) + +def cddr(l): + return cdr(cdr(l)) + +def caddr(l): + return car(cddr(l)) + +def append(a, b): + return a + b + +def reverse(l): + r = list(l) + r.reverse() + return tuple(r) + +def isNil(l): + if isinstance(l, streampair): + return l.isNil() + return l == () + +def isSymbol(v): + return isinstance(v, basestring) and v[0:1] == "'" + +def isString(v): + return isinstance(v, basestring) and v[0:1] != "'" + +def isList(v): + if getattr(v, '__iter__', False) == False: + return False + if isinstance(v, basestring) or isinstance(v, dict): + return False + return True + +def isTaggedList(v, t): + return isList(v) and not isNil(v) and car(v) == t + + +# Scheme-like streams +class streampair(object): + def __init__(self, car, cdr): + self.car = car + self.cdr = cdr + + def __repr__(self): + return repr(self[0:len(self)]) + + def isNil(self): + return self.cdr == () + + def __len__(self): + if self.cdr == (): + return 0 + return 1 + len(self.cdr()) + + def __getitem__(self, i): + if i == 0: + return self.car + return self.cdr()[i - 1] + + def __getslice__(self, i, j): + if isNil(self): + return () + if i > 0: + if j == maxint: + return self.cdr()[i - 1: j] + return self.cdr()[i - 1: j - 1] + if j == maxint: + return self + if j == 0: + return (self.car,) + return (self.car,) + self.cdr()[: j - 1] + + def __eq__(self, other): + sl = len(self) + ol = len(other) + if sl != ol: + return False + return self[0: sl] == other[0: ol] + + def __ne__(self, other): + return not self.__eq__(other) + +def cons_stream(car, cdr): + return streampair(car, cdr) + + +# Scheme-like associations +def assoc(k, l): + if l == (): + return None + + if k == car(car(l)): + return car(l) + return assoc(k, cdr(l)) + +# Currying / partial function application +def curry(f, *args): + return lambda *a: f(*(args + a)) + +# Convert a path represented as a list of values to a string +def path(p): + if isNil(p): + return "" + return "/" + car(p) + path(cdr(p)) + +# Split a path into a list of segments +def tokens(path): + return tuple(filter(lambda s: len(s) != 0, path.split("/"))) + +# Return true if s1 contains s2 +def contains(s1, s2): + return s1.find(s2) != -1 + +# Write a list of strings to a stream +def writeStrings(l, os): + if l == (): + return os + os.write(car(l)) + return writeStrings(cdr(l), os) + diff --git a/sca-cpp/trunk/modules/edit/workspaces/joe@localhost b/sca-cpp/trunk/modules/edit/workspaces/joe@localhost new file mode 100644 index 0000000000..d735651e40 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/workspaces/joe@localhost @@ -0,0 +1 @@ +(("Sample Store App" "store" ((composite (@xmlns "http://docs.oasis-open.org/ns/opencsa/sca/200912") (@xmlns:t "http://tuscany.apache.org/xmlns/sca/1.1") (@targetNamespace "http://store") (@name "store") (component (((@name "Store") (@color "yellow") (t:implementation.python (@script "store.py")) (service (@name "Widget") (t:binding.http (@uri "store"))) (reference (((@name "catalog") (@target "Catalog")) ((@name "shoppingCart") (@target "ShoppingCart/Cart")) ((@name "shoppingTotal") (@target "ShoppingCart/Total"))))) ((@name "Catalog") (@color "green") (t:implementation.python (@script "fruits-catalog.py")) (property "USD") (service (@name "Catalog") (t:binding.jsonrpc (@uri "catalog"))) (reference (@name "currencyConverter") (@target "CurrencyConverter"))) ((@name "ShoppingCart") (@color "pink") (t:implementation.python (@script "shopping-cart.py")) (service (((@name "ShoppingCart") (t:binding.atom (@uri "shoppingCart"))) ((@name "Total") (t:binding.jsonrpc (@uri "total"))))) (reference (@name "cache") (@target "Cache") (@align "bottom"))) ((@name "CurrencyConverter") (@color "red") (t:implementation.python (@script "currency-converter.py")) (service (@name "CurrencyConverter") (t:binding.jsonrpc (@uri "currencyConverter")))) ((@name "Cache") (@color "blue") (implementation.cpp (@path "../../components/cache") (@library "libmemcache")) (service (@name "Cache") (@align "top") (t:binding.atom (@uri "cache"))) (property "localhost:11211")))))))("Another Store App" "store2" ((composite (@xmlns "http://docs.oasis-open.org/ns/opencsa/sca/200912") (@xmlns:t "http://tuscany.apache.org/xmlns/sca/1.1") (@targetNamespace "http://store") (@name "store") (component (((@name "Store") (@color "yellow") (t:implementation.python (@script "store.py")) (service (@name "Widget") (t:binding.http (@uri "store"))) (reference (((@name "catalog") (@target "Catalog")) ((@name "shoppingCart") (@target "ShoppingCart/Cart")) ((@name "shoppingTotal") (@target "ShoppingCart/Total"))))) ((@name "Catalog") (@color "green") (t:implementation.python (@script "fruits-catalog.py")) (property "USD") (service (@name "Catalog") (t:binding.jsonrpc (@uri "catalog"))) (reference (@name "currencyConverter") (@target "CurrencyConverter"))) ((@name "ShoppingCart") (@color "pink") (t:implementation.python (@script "shopping-cart.py")) (service (((@name "ShoppingCart") (t:binding.atom (@uri "shoppingCart"))) ((@name "Total") (t:binding.jsonrpc (@uri "total"))))) (reference (@name "cache") (@target "Cache") (@align "bottom"))) ((@name "CurrencyConverter") (@color "red") (t:implementation.python (@script "currency-converter.py")) (service (@name "CurrencyConverter") (t:binding.jsonrpc (@uri "currencyConverter")))) ((@name "Cache") (@color "blue") (implementation.cpp (@path "../../components/cache") (@library "libmemcache")) (service (@name "Cache") (@align "top") (t:binding.atom (@uri "cache"))) (property "localhost:11211")))))))) diff --git a/sca-cpp/trunk/modules/js/htdocs/atomutil.js b/sca-cpp/trunk/modules/js/htdocs/atomutil.js index 6b998dceda..24a47980f7 100644 --- a/sca-cpp/trunk/modules/js/htdocs/atomutil.js +++ b/sca-cpp/trunk/modules/js/htdocs/atomutil.js @@ -44,16 +44,32 @@ atom.entriesElementsToValues = function(e) { }; /** - * Convert a list of strings to a list of values representing an ATOM entry. + * Return true if a list of strings represents an ATOM entry. */ -atom.readATOMEntry = function(l) { - var e = readXML(l); +atom.isATOMEntry = function(l) { + if (!isXML(l)) + return false; + return car(l).match('<entry') != null && car(l).match('<feed') == null && car(l).match('="http://www.w3.org/2005/Atom"') != null; +}; + +/** + * Convert a DOM Document to a list of values representing an ATOM entry. + */ +atom.readATOMEntryDocument = function(doc) { + var e = readXMLDocument(doc); if (isNil(e)) return mklist(); return atom.entryElementsToValues(car(e)); }; /** + * Convert a list of strings to a list of values representing an ATOM entry. + */ +atom.readATOMEntry = function(l) { + return atom.readATOMEntryDocument(parseXML(l)); +}; + +/** * Convert a list of values representy an ATOM entry to a value. */ atom.entryValue = function(e) { diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js index fcd61571d1..2f5c6d3ae9 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.js +++ b/sca-cpp/trunk/modules/js/htdocs/ui.js @@ -197,16 +197,26 @@ ui.elementByID = function(node, id) { function $(id) { if (id == document) { if (!isNil(document.widget)) - return widget; + return document.widget; return document; } return ui.elementByID($(document), id); }; /** - * Initialize a widget. + * Bind a widget iframe to an element. */ -ui.onloadwidget = function() { +ui.widgets = new Array(); + +ui.bindwidget = function(f, el) { + window.ui.widgets[f] = el; + return f; +}; + +/** + * Install a widget into the element bound to its iframe. + */ +ui.installwidget = function() { if (isNil(window.parent) || isNil(window.parent.ui) || isNil(window.parent.ui.widgets)) return true; var pdoc = ui.content(window.parent); @@ -221,13 +231,3 @@ ui.onloadwidget = function() { return true; }; -/** - * Load a widget into an element. - */ -ui.widgets = new Array(); - -ui.bindwidget = function(f, el) { - window.ui.widgets[f] = el; - return f; -}; - diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf index 742d48d614..992627596b 100755 --- a/sca-cpp/trunk/modules/server/server-conf +++ b/sca-cpp/trunk/modules/server/server-conf @@ -64,17 +64,24 @@ Alias /atomutil.js $jsprefix/htdocs/atomutil.js Alias /ui.js $jsprefix/htdocs/ui.js Alias /ui.css $jsprefix/htdocs/ui.css Alias /scdl.js $jsprefix/htdocs/scdl.js -Alias /graph.js $jsprefix/htdocs/graph.js <Location /component.js> AuthType None Require all granted </Location> -<Location /scdl.js> +<Location /util.js> AuthType None Require all granted </Location> -<Location /util.js> +<Location /elemutil.js> +AuthType None +Require all granted +</Location> +<Location /xmlutil.js> +AuthType None +Require all granted +</Location> +<Location /atomutil.js> AuthType None Require all granted </Location> @@ -86,6 +93,10 @@ Require all granted AuthType None Require all granted </Location> +<Location /scdl.js> +AuthType None +Require all granted +</Location> EOF |