You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/12/22 08:58:06 UTC
svn commit: r728626 - in
/incubator/sling/trunk/extensions/dojo-sling/src/main/resources:
SLING-INF/content/dojox/data/demo/demo4.html dojox/data/SlingNodeStore.js
dojox/data/SlingPropertyStore.js
Author: fmeschbe
Date: Sun Dec 21 23:58:06 2008
New Revision: 728626
URL: http://svn.apache.org/viewvc?rev=728626&view=rev
Log:
SLING-792 Apply patch by Rory Douglas (thanks for providing)
Added:
incubator/sling/trunk/extensions/dojo-sling/src/main/resources/SLING-INF/content/dojox/data/demo/demo4.html
Modified:
incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingNodeStore.js
incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingPropertyStore.js
Added: incubator/sling/trunk/extensions/dojo-sling/src/main/resources/SLING-INF/content/dojox/data/demo/demo4.html
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/dojo-sling/src/main/resources/SLING-INF/content/dojox/data/demo/demo4.html?rev=728626&view=auto
==============================================================================
--- incubator/sling/trunk/extensions/dojo-sling/src/main/resources/SLING-INF/content/dojox/data/demo/demo4.html (added)
+++ incubator/sling/trunk/extensions/dojo-sling/src/main/resources/SLING-INF/content/dojox/data/demo/demo4.html Sun Dec 21 23:58:06 2008
@@ -0,0 +1,145 @@
+<!--
+ 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>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ @import "../../../dojox/grid/resources/tundraGrid.css";
+ @import "../../../dojox/grid/resources/Grid.css";
+
+ .dojoxGrid table {
+ margin: 0;
+ }
+
+ </style>
+
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true, usePlainJson: true"></script>
+ <script type="text/javascript">
+ dojo.require("dijit.form.Form");
+ dojo.require("dijit.form.Button");
+ dojo.require("dijit.form.ComboBox");
+ dojo.require("dijit.form.TextBox");
+ dojo.require("dijit.form.FilteringSelect");
+ dojo.require("dijit.Tree");
+ dojo.require("dojox.data.SlingPropertyStore");
+ dojo.require("dojox.data.SlingNodeStore");
+ dojo.require("dojox.grid.DataGrid");
+ dojo.require("dijit.layout.StackContainer");
+ dojo.require("dijit.layout.TabContainer");
+ dojo.require("dijit.layout.ContentPane");
+ dojo.require("dijit.layout.BorderContainer");
+
+ var nodeLayout = [
+ [
+ { field: "name", name: "Name", width: 20 },
+ { field: "value", name: "Value", width: 40, editable: true}
+ ]
+ ];
+
+ </script>
+</head>
+<body class="tundra">
+ <!-- the data stores -->
+ <div dojoType="dojox.data.SlingPropertyStore" url="/samplenodes" jsId="propertyStore"></div>
+ <div dojoType="dojox.data.SlingNodeStore" url="/samplenodes" jsId="nodeStore"></div>
+ <div dojoType="dojox.data.SlingNodeStore" url="/samplenodes" jsId="nodeStoreLevel2" overrideDepth="{depth: 2}"></div>
+ <div dojoType="dojox.data.SlingNodeStore" url="/samplenodes" jsId="nodeStoreLevel2NotDeep" overrideDepth="{depth: 2}" overrideDeep="{deep: false}"></div>
+ <div dojoType="dojox.data.SlingNodeStore" url="/samplenodes" jsId="nodeStoreAll3" overrideDeep="{deep: true}" overrideDepth="{depth: 3}"></div>
+ <div dojoType="dojox.data.SlingNodeStore" url="/" statement="//*[sling:resourceType='sample/node']" searchprops="['title','jcr:created']" jsId="nodeStoreSearch"></div>
+ <div dojoType="dojox.data.SlingNodeStore" url="/samplenodes" jsId="nodeStoreTreeLimit" overrideDepth="{treeDepth: 3}"></div>
+
+ <!-- Models for the Trees -->
+ <div dojoType="dijit.tree.TreeStoreModel" jsId="treeModel" store="nodeStore"></div>
+ <div dojoType="dijit.tree.ForestStoreModel" jsId="forestModel" store="nodeStoreLevel2" rootId="fakeRoot" rootLabel="Fake Root"></div>
+ <div dojoType="dijit.tree.TreeStoreModel" jsId="treeModelLimit" store="nodeStoreTreeLimit"></div>
+
+ <!--<div dojoType="dijit.layout.StackController" containerId="demoStack"></div>-->
+ <div dojoType="dijit.layout.TabContainer" id="demoStack" style="height: 100%">
+ <div title="Tree 1" dojoType="dijit.layout.ContentPane">
+ <h4>Tree of /samplenodes, all defaults</h4>
+ <div dojoType="dijit.Tree" model="treeModel" persist="false"></div>
+ </div>
+ <div title="Tree 2" dojoType="dijit.layout.ContentPane">
+ <h4>Tree of /samplenodes, depth=2, using forest model</h4>
+ <div dojoType="dijit.Tree" model="forestModel" persist="false"></div>
+ </div>
+ <div title="Tree 3" dojoType="dijit.layout.ContentPane">
+ <h4>Tree of /samplenodes, treedepth=3</h4>
+ <div dojoType="dijit.Tree" model="treeModelLimit" persist="false"></div>
+ </div>
+ <div title="ComboBox 1" dojoType="dijit.layout.ContentPane">
+ <h4>ComboBox of /samplenodes, all defaults</h4>
+ <div dojoType="dijit.form.ComboBox" store="nodeStore" searchAttr="title"></div>
+ </div>
+ <div title="ComboBox 2" dojoType="dijit.layout.ContentPane">
+ <h4>ComboBox of /samplenodes, depth=2</h4>
+ <div dojoType="dijit.form.ComboBox" store="nodeStoreLevel2" searchAttr="title"></div>
+ </div>
+ <div title="ComboBox 3" dojoType="dijit.layout.ContentPane">
+ <h4>ComboBox of /samplenodes, depth=2, deep=false</h4>
+ <div dojoType="dijit.form.ComboBox" store="nodeStoreLevel2NotDeep" searchAttr="title"></div>
+ </div>
+ <div title="FilteringSelect 1" dojoType="dijit.layout.ContentPane">
+ <h4>FilteringSelect of /samplenodes, using search statement: //*[sling:resourceType='sample/node']</h4>
+ <div dojoType="dijit.form.FilteringSelect" store="nodeStoreSearch" searchAttr="title"></div>
+ </div>
+ <div title="Complete" dojoType="dijit.layout.ContentPane">
+ <div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="true" liveSplitters="true" id="borderContainer">
+ <div dojoType="dijit.layout.ContentPane" splitter="true" region="leading" style="width: 20%;">
+ <div dojoType="dijit.Tree" model="treeModel" persist="false">
+ <script type="dojo/connect" event="onClick" args="nodeItem,nodeWidget">
+ propertyStore.setUrl(nodeItem.uri);
+ dijit.byId("nodePropGrid").setStore(propertyStore);
+ </script>
+ </div>
+ </div>
+ <div id="propGrid" dojoType="dijit.layout.ContentPane" region="center">
+ <div dojoType="dijit.layout.BorderContainer" gutters="true" liveSplitters="true" id="propContainer">
+ <div dojoType="dijit.layout.ContentPane" region="top">
+ <input id="newPropertyName" dojoType="dijit.form.TextBox" value=""/>
+ <input id="newPropertyValue" dojoType="dijit.form.TextBox" value=""/>
+ <div dojoType="dijit.form.Button" label="Add Property">
+ <script type="dojo/connect" event="onClick">
+ var newItem= {name: dijit.byId('newPropertyName').getValue(),value: dijit.byId('newPropertyValue').getValue()};
+ propertyStore.newItem(newItem);
+ dijit.byId("nodePropGrid").setStore(propertyStore);
+ </script>
+ </div>
+ </div>
+ <div dojoType="dijit.layout.ContentPane" region="center">
+ <div id="nodePropGrid"
+ dojoType="dojox.grid.DataGrid"
+ store="propertyStore"
+ structure="nodeLayout"
+ rowsPerPage="40">
+ <script type="dojo/connect" event="onApplyCellEdit">
+ // necessary because v1.2.3 grid keeps internal item cache & fetchItemByIdentity returns new item not ref to existing
+ dijit.byId("nodePropGrid").setStore(propertyStore);
+ </script>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
+
+
Modified: incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingNodeStore.js
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingNodeStore.js?rev=728626&r1=728625&r2=728626&view=diff
==============================================================================
--- incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingNodeStore.js (original)
+++ incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingNodeStore.js Sun Dec 21 23:58:06 2008
@@ -18,23 +18,72 @@
dojo._hasResource["dojox.data.SlingNodeStore"] = true;
dojo.require("dojo.data.util.simpleFetch");
+dojo.require("dojo.data.util.filter");
dojo.provide("dojox.data.SlingNodeStore");
dojo.declare("dojox.data.SlingNodeStore", null, {
url:"",
+ statement:"",
query:null,
-
+ searchprops:null,
+ overrideDeep:null,
+ overrideDepth:null,
/* summary:
* The SlingNodeStore implements the dojo.data.api.Read API.
*/
constructor: function(/* Object */ keywordParameters){
- this.uri = keywordParameters.url;
+ this.uri = keywordParameters.url;
+ this.statement = keywordParameters.statement;
+
+ if(keywordParameters.query) {
+ this.query = keywordParameters.query;
+ }
+
+ if (dojo.isArray(keywordParameters.searchprops)) {
+ this.searchprops = keywordParameters.searchprops;
+ }else{
+ if (dojo.isString(keywordParameters.searchprops)) {
+ this.searchprops = keywordParameters.searchprops.split(",");
+ }
+ }
+
+ if(keywordParameters.overrideDeep) {
+ this.overrideDeep = keywordParameters.overrideDeep;
+ }
+
+ if(keywordParameters.overrideDepth) {
+ this.overrideDepth = keywordParameters.overrideDepth;
+ }
},
+ setUrl: function(/* String */ url) {
+ this.uri = url;
+ },
+ setStatement: function(/* String */ statement) {
+ this.statement = statement;
+ },
+ setSearchProps: function(/* Array|String */ props) {
+ if (dojo.isArray(props)) {
+ this.searchprops = props;
+ }else{
+ if (dojo.isString(props)) {
+ this.searchprops = props.split(",");
+ }
+ }
+ },
+ setOverrideDeep: function(/* Object */ overrideDeep) {
+ this.overrideDeep = overrideDeep;
+ },
+ setOverrideDepth: function(/* Object */ overrideDepth) {
+ this.overrideDepth = overrideDepth;
+ },
+ setQuery: function(/* Object */ query) {
+ this.query = query;
+ },
getValue: function( /* item */ item,
/* attribute-name-string */ attribute,
/* value? */ defaultValue){
- console.log("getValue " + attribute);
+ //console.log("getValue " + attribute);
if (!this.isItem(item)) {
throw new Error(item + " is not an item");
}
@@ -62,6 +111,9 @@
if (!dojo.isString(attribute)) {
throw new Error(attribute + " is not a string");
}
+ if (attribute=="sling:uri") {
+ return [item.uri];
+ }
if (attribute=="children"&&this._hasChildren(item)) {
return this._getChildren(item);
}
@@ -82,10 +134,14 @@
for (var property in item.node) {
if (dojo.isObject(item.node[property])) {
- if (item.node[property]["jcr:primaryType"]&&this.accept(item.node[property], item.query)) {
- var childuri = item.uri=="/" ? "/" + property : item.uri + "/" + property;
- var child = {uri: childuri, query: item.query }
- children.push(child);
+ if (item.node[property]["jcr:primaryType"]) {
+ var childuri = item.uri=="/" ? "/" + property : item.uri + "/" + property;
+ var checkChild = {uri: childuri, node: item.node[property], depth: item.depth+1};
+
+ if(this.accept(checkChild, item.query)) {
+ var child = {uri: childuri, query: item.query, depth: item.depth+1 };
+ children.push(child);
+ }
}
}
}
@@ -95,7 +151,7 @@
},
getAttributes: function(/* item */ item){
- console.log("getAttributes");
+ //console.log("getAttributes");
if (!this.isItem(item)) {
return [];
}
@@ -129,6 +185,9 @@
if (attribute=="children") {
return this._hasChildren(item);
}
+ if (attribute=="sling:uri") {
+ return true;
+ }
if (item.node[attribute]) {
return true;
}
@@ -137,11 +196,19 @@
_hasChildren: function(/* item */ item) {
//children are all properties of a node that are objects
+ if(this.overrideDepth && this.overrideDepth.treeDepth && item.depth && item.depth >= this.overrideDepth.treeDepth ) {
+ return false;
+ }
for (var property in item.node) {
if (dojo.isObject(item.node[property])) {
- if (item.node[property]["jcr:primaryType"]&&this.accept(item.node[property], item.query)) {
- //console.log("there are children");
- return true;
+ if (item.node[property]["jcr:primaryType"]) {
+ var childuri = item.uri=="/" ? "/" + property : item.uri + "/" + property;
+ var checkChild = {uri: childuri, node: item.node[property], depth: item.depth+1};
+
+ if(this.accept(checkChild, item.query)) {
+ //console.log("there are children");
+ return true;
+ }
}
}
}
@@ -251,29 +318,100 @@
xhr.abort();
}
};
- var query = keywordArgs.query;
- var depth = 1;
- if (query&&query.level) {
- depth = depth + query.level;
+ var query = keywordArgs.query;
+ var queryOptions = keywordArgs.queryOptions;
+ //var startVal = keywordArgs.start;
+ //var countVal = keywordArgs.count;
+
+ var depth = 0;
+ var isDeep = false;
+ var isSearch = false;
+
+ // is this a deep query? (store setting overrides queryOption)
+ if (this.overrideDeep) {
+ isDeep = this.overrideDeep.deep;
+ } else if(queryOptions&&queryOptions.deep) {
+ isDeep = queryOptions.deep;
+ }
+
+ // query depth/level specified? (store setting overrides queryOption)
+ // deep = true & no depth => depth is infinite
+ if(this.overrideDepth&&this.overrideDepth.depth) {
+ depth = this.overrideDepth.depth;
+ } else if (queryOptions&&queryOptions.depth) {
+ depth = queryOptions.depth;
+ } else if (isDeep){
+ depth = "infinity";
+ }
+
+ // mixin store query with caller-provided query
+ // won't work well if two queries share an attribute
+ if(this.query) {
+ if(!query) {
+ query = {};
+ }
+ dojo.mixin(query,this.query);
+ }
+
+ var url = this.uri + "."+(depth == "infinity" ? depth : depth+1)+".json";
+
+ // was a statement provided? if so, doing search
+ if(this.statement) {
+ isSearch = true;
+
+ // to make descend behave properly
+ depth = "infinity";
+ isDeep = true;
+
+ // construct search URL
+ url = this.uri + ".query.json?statement=" + this.statement;
+
+ /*
+ if(startVal != 0){
+ url = url + "&offset=" + startVal;
+ }
+ if(countVal && typeof countVal == "number"){
+ if(isFinite(countVal)) {
+ url = url + "&rows=" + countVal;
+ }
+ }
+ */
+
+ if(dojo.isArray(this.searchprops)) {
+ dojo.forEach(this.searchprops,function(prop) {
+ url = url + "&property=" + prop;
+ });
+ }
}
- var url = this.uri + "."+depth+".json";
+
var that = this;
xhr = dojo.xhrGet({
url: url,
handleAs: "json-comment-optional",
load: function(response, ioargs) {
- var item = { node: response, uri: that.uri};
+ var item = { node: response, uri: that.uri, depth: 0};
var items = [];
if (request.onComplete) {
- if (query&&query.level) {
+ if (isSearch || dojo.isArray(response)) {
+ var checkitems = [];
+ dojo.forEach(response, function(item,index,array) {
+ var anItem = {};
+ anItem.node = item;
+ anItem.uri = item['jcr:path'];
+ anItem.depth = 0;
+ checkitems.push(anItem);
+ });
+
+ items = that.descend(checkitems, query, depth, isDeep);
+ } else if (depth == "infinity" || depth > 0) {
//console.log("hehe. got a level");
- var checkitems = [ { node: item.node, uri: that.uri } ];
- items = that.descend(checkitems, query.level);
+ var checkitems = [ { node: item.node, uri: that.uri, depth: 0} ];
+ items = that.descend(checkitems, query, depth, isDeep );
} else {
- if (that.accept(item.node, query)) {
+ if (that.accept(item, query)) {
item.query = query;
items.push(item);
}
@@ -284,101 +422,87 @@
});
},
- descend: function(items, level) {
+ descend: function(items, query, level, isDeep) {
var allitems = [];
- console.log(level);
- if (level==0) {
- allitems = allitems.concat(items);
- } else {
+ //console.log(level);
+ if (level==0 || isDeep) {
+ for (var i=0;i<items.length;i++) {
+ var checkItem = items[i];
+ if(this.accept(checkItem,query)) {
+ checkItem.query = query;
+ allitems.push(checkItem);
+ }
+ }
+ //allitems = allitems.concat(items);
+ }
+
+ var objFound = false;
+
+ if(level != 0) {
var newitems = [];
for (var i=0;i<items.length;i++) {
var item = items[i];
+
for (var property in item.node) {
- if (dojo.isObject(item.node[property])) {
- var newitem = { node: item.node[property], uri: ( item.uri == "/" ? "" : item.uri ) + "/" + property };
+ if (!dojo.isArray(item.node[property])&&dojo.isObject(item.node[property])) {
+ objFound = true;
+ var newitem = { node: item.node[property], uri: ( item.uri == "/" ? "" : item.uri ) + "/" + property, depth: item.depth+1};
newitems.push(newitem);
}
}
}
- allitems = allitems.concat(this.descend(newitems, level - 1));
- }
- console.dir(allitems);
- return allitems;
- },
-
- _nofetch: function(/* object */ keywordArgs) {
- var request = keywordArgs;
-
- var xhr;
-
- request.abort = function() {
- if (xhr.abort) {
- xhr.abort();
+
+ if(level == "infinity" && objFound) {
+ allitems = allitems.concat(this.descend(newitems, query, "infinity", isDeep));
+ } else if (level >= 1) {
+ allitems = allitems.concat(this.descend(newitems, query, level - 1, isDeep));
}
- };
-
-
- var query = keywordArgs.query;
-
- var depth = 1;
- if (query.level) {
- depth = depth + query.level;
}
- var url = this.uri + "."+depth+".json";
- var that = this;
-
- xhr = dojo.xhrGet({
- url: url,
- handleAs: "json-comment-optional",
- load: function(response, ioargs) {
- var item = { node: response, uri: that.uri};
-
- if (request.onComplete) {
- if (query.level) {
-
- } else {
- if (that.accept(item.node, query)) {
- item.query = query;
- request.onComplete([ item ], request);
- }
- }
- }
- }
- });
- //TODO: implement
- //alert(this.url);
- return request;
+ //console.dir(allitems);
+ return allitems;
},
-
- accept: function(node, query) {
+
+ accept: function(item, query) {
//TODO: handle querying for arrays
if (!query) {
return true;
}
- if (!query.query) {
- return true;
- }
- for (var property in query.query) {
+
+ var ignoreCase = true;
+
+ //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
+ //same value for each item examined. Much more efficient.
+ var regexpList = {};
+ for(var key in query){
+ var value = query[key];
+ if(typeof value === "string"){
+ regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+ }
+ }
+
+ for (var property in query) {
//console.log(property);
- if (node[property]) {
- if (dojo.isArray(query.query[property])) {
+ if (item.node[property]) {
+ var checkItem = item;
+ if (dojo.isArray(query[property])) {
//console.log("multiple values possible");
var onematch = false;
- for (var value in query.query[property]) {
- //console.log("checking value " + query.query[property][value]);
- if (node[property]==query.query[property][value]) {
- onematch = true;
- }
+
+ for (var value in query[property]) {
+ //console.log("checking value " + query[property][value]);
+ if (!this._containsValue(checkItem, property, checkItem.node[property], regexpList[property])){
+ onematch = false;
+ }
}
if (!onematch) {
- //console.log("required property " + property + " has wrong value "+ node[property]);
+ //console.log("required property " + property + " has wrong value "+ item.node[property]);
return false;
}
} else {
- if (node[property]!=query.query[property]) {
- //console.log("required property " + property + " has wrong value "+ node[property]);
- return false;
- }
+ if (!this._containsValue(checkItem, property, checkItem.node[property], regexpList[property])){
+ //console.log("required property " + property + " has wrong value "+ item.node[property]);
+ return false;
+ }
}
} else {
//console.log("required property " + property + " missing");
@@ -388,6 +512,37 @@
return true;
},
+ _containsValue: function( /* item */ item,
+ /* attribute-name-string */ attribute,
+ /* anything */ value,
+ /* RegExp?*/ regexp){
+ // summary:
+ // Internal function for looking at the values contained by the item.
+ // description:
+ // Internal function for looking at the values contained by the item. This
+ // function allows for denoting if the comparison should be case sensitive for
+ // strings or not (for handling filtering cases where string case should not matter)
+ //
+ // item:
+ // The data item to examine for attribute values.
+ // attribute:
+ // The attribute to inspect.
+ // value:
+ // The value to match.
+ // regexp:
+ // Optional regular expression generated off value if value was of string type to handle wildcarding.
+ // If present and attribute values are string, then it can be used for comparison instead of 'value'
+ return dojo.some(this.getValues(item, attribute), function(possibleValue){
+ if(possibleValue !== null && !dojo.isObject(possibleValue) && regexp){
+ if(possibleValue.toString().match(regexp)){
+ return true; // Boolean
+ }
+ }else if(value === possibleValue){
+ return true; // Boolean
+ }
+ });
+ },
+
getFeatures: function() {
return {
"dojo.data.api.Read": true,
@@ -435,7 +590,7 @@
getIdentityAttributes: function(/* item */ item) {
//console.log("getIdentityAttributes");
//identity depends on the URI, not the representation
- return null;
+ return ["sling:uri"];
},
fetchItemByIdentity: function(/* object */ keywordArgs) {
@@ -449,7 +604,28 @@
// scope: object
// }
- //TODO: implement
+ var request = keywordArgs;
+
+ var url = keywordArgs.identity + ".1.json";
+
+ var that = this;
+
+ xhr = dojo.xhrGet({
+ url: url,
+ handleAs: "json-comment-optional",
+ load: function(response, ioargs) {
+ var item = { node: response, uri: request.identity};
+
+ if (request.onItem) {
+ request.onItem(item);
+ }
+ },
+ error: function(response, ioargs) {
+ if(request.onError) {
+ request.onError(response);
+ }
+ }
+ });
},
@@ -498,8 +674,7 @@
setValues: function(item, attribute, values) { console.log("setValues");
- throw new Error('Unimplemented API: dojo.data.api.Write.setValues');
- this.onSet(item, attribute, oldvalues, values);
+ this.setValue(item, attribute, values);
},
unsetAttribute: function( /* item */ item,
Modified: incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingPropertyStore.js
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingPropertyStore.js?rev=728626&r1=728625&r2=728626&view=diff
==============================================================================
--- incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingPropertyStore.js (original)
+++ incubator/sling/trunk/extensions/dojo-sling/src/main/resources/dojox/data/SlingPropertyStore.js Sun Dec 21 23:58:06 2008
@@ -18,6 +18,7 @@
dojo._hasResource["dojox.data.SlingPropertyStore"] = true;
dojo.require("dojo.data.util.simpleFetch");
+dojo.require("dojo.data.util.filter");
dojo.provide("dojox.data.SlingPropertyStore");
dojo.declare("dojox.data.SlingPropertyStore", null, {
@@ -29,9 +30,17 @@
* It will return one data item for every property found
*/
constructor: function(/* Object */ keywordParameters){ console.log("constructor");
- this.uri = keywordParameters.url;
+ this.uri = keywordParameters.url;
+ if(keywordParameters.query) {
+ this.query = keywordParameters.query;
+ }
},
-
+ setUrl: function(/* String */ url) {
+ this.uri = url;
+ },
+ setQuery: function(/* Object */ query) {
+ this.query = query;
+ },
getValue: function( /* item */ item, /* attribute-name-string */ attribute, /* value? */ defaultValue){
//console.log("getValue " + attribute + " " + item.name);
if (!this.isItem(item)) {
@@ -51,8 +60,17 @@
if (!dojo.isString(attribute)) {
throw new Error(attribute + " is not a string");
}
- return item[attribute];
- },
+ if (item[attribute]) {
+ if (dojo.isArray(item[attribute])) {
+ return item[attribute]
+ } else {
+ return [item[attribute]];
+ }
+ } else {
+ var array = [];
+ return array; // an array that may contain literals and items
+ }
+ },
getAttributes: function(/* item */ item){ //console.log("getAttributes");
//console.log("getAttributes");
@@ -116,30 +134,44 @@
_fetchItems: function( /* Object */ keywordArgs,
/* Function */ findCallback,
/* Function */ errorCallback) {
- var request = keywordArgs;
-
+ var request = keywordArgs;
+
var xhr;
request.abort = function() {
- errorCallback.("XHR aborted", keywordArgs)
+ if (xhr.abort) {
+ xhr.abort();
+ }
};
- var depth = 1;
+ var query = keywordArgs.query;
+
+ var depth = 0;
var url = this.uri + "."+depth+".json";
var that = this;
- var query = keywordArgs.query;
-
+ // mixin store query with caller-provided query
+ // won't work well if two queries share an attribute
+ if(this.query) {
+ if(!query) {
+ query = {};
+ }
+ dojo.mixin(query,this.query);
+ }
+
xhr = dojo.xhrGet({
url: url,
handleAs: "json-comment-optional",
load: function(response, ioargs) {
var items = [];
for (var property in response) {
- if (!dojo.isObject(response[property])) {
+ if (dojo.isArray(response[property]) || !dojo.isObject(response[property])) {
//console.debug(property);
- items.push({ uri: that.uri, name: property, value: response[property]});
+ var checkitem = { uri: that.uri, name: property, value: response[property]};
+ if(that.accept(checkitem,query)) {
+ items.push(checkitem);
+ }
}
}
findCallback(items, keywordArgs);
@@ -148,59 +180,86 @@
},
- _nofetch: function(/* object */ keywordArgs) { console.log("fetch");
- var request = keywordArgs;
-
- var xhr;
-
- request.abort = function() {
- if (xhr.abort) {
- xhr.abort();
- }
- };
-
- var depth = 1;
-
- /*
- if (keywordArgs.count) {
- depth = keywordArgs.count;
+ accept: function(item, query) {
+ // TODO: handle querying for arrays
+ if (!query) {
+ return true;
}
- */
-
- var url = this.uri + "."+depth+".json";
- var that = this;
-
- var query = keywordArgs.query;
-
- xhr = dojo.xhrGet({
- url: url,
- handleAs: "json-comment-optional",
- load: function(response, ioargs) { console.log("load");
- //console.dir(response);
- var items = [];
-
- for (var property in response) {
- if (!dojo.isObject(response[property])) {
- //console.debug(property);
- items.push({ uri: that.uri, name: property, value: response[property]});
- }
+
+ var ignoreCase = true;
+
+ //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
+ //same value for each item examined. Much more efficient.
+ var regexpList = {};
+ for(var key in query){
+ var value = query[key];
+ if(typeof value === "string"){
+ regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+ }
+ }
+
+ for (var property in query) {
+ //console.log(property);
+ if (item[property]) {
+ var checkItem = item;
+ if (dojo.isArray(query[property])) {
+ //console.log("multiple values possible");
+ var onematch = false;
+
+ for (var value in query[property]) {
+ //console.log("checking value " + query[property][value]);
+ if (!this._containsValue(checkItem, property, checkItem[property], regexpList[property])){
+ onematch = false;
+ }
}
-
- if (request.onComplete) {
- if (request.scope) {
- request.onComplete.call(request.scope, item. request)
- } else {
- request.onComplete(items, request);
- }
- //request.onComplete(items, request);
+ if (!onematch) {
+ //console.log("required property " + property + " has wrong value "+ item.node[property]);
+ return false;
}
+ } else {
+ if (!this._containsValue(checkItem, property, checkItem[property], regexpList[property])){
+ //console.log("required property " + property + " has wrong value "+ item.node[property]);
+ return false;
+ }
}
- });
- //TODO: implement
- //alert(this.url);
- return request;
+ } else {
+ //console.log("required property " + property + " missing");
+ return false;
+ }
+ }
+ return true;
},
-
+
+ _containsValue: function( /* item */ item,
+ /* attribute-name-string */ attribute,
+ /* anything */ value,
+ /* RegExp?*/ regexp){
+ // summary:
+ // Internal function for looking at the values contained by the item.
+ // description:
+ // Internal function for looking at the values contained by the item. This
+ // function allows for denoting if the comparison should be case sensitive for
+ // strings or not (for handling filtering cases where string case should not matter)
+ //
+ // item:
+ // The data item to examine for attribute values.
+ // attribute:
+ // The attribute to inspect.
+ // value:
+ // The value to match.
+ // regexp:
+ // Optional regular expression generated off value if value was of string type to handle wildcarding.
+ // If present and attribute values are string, then it can be used for comparison instead of 'value'
+ return dojo.some(this.getValues(item, attribute), function(possibleValue){
+ if(possibleValue !== null && !dojo.isObject(possibleValue) && regexp){
+ if(possibleValue.toString().match(regexp)){
+ return true; // Boolean
+ }
+ }else if(value === possibleValue){
+ return true; // Boolean
+ }
+ });
+ },
getFeatures: function() { console.log("getFeatures");
console.log("getFeatures");
@@ -237,7 +296,7 @@
console.log("error: not an item");
throw new Error(item + " is not an item");
}
- return item.uri + "[" + item.name + "]";
+ return this.uri + "[" + item.name + "]";
},
getIdentityAttributes: function(/* item */ item) { console.log("getIdentityAttributes");
@@ -256,8 +315,37 @@
// onError: Function,
// scope: object
// }
+ var request = keywordArgs;
- //TODO: implement
+ var itemId = keywordArgs.identity;
+ var idParts = itemId.split('[');
+ var itemUri = idParts[0];
+ var itemName = idParts[1].substring(0,idParts[1].length-1);
+ var url = itemUri + "/" + itemName + ".0.json";
+
+ var that = this;
+
+ xhr = dojo.xhrGet({
+ url: url,
+ handleAs: "json-comment-optional",
+ load: function(response, ioargs) {
+
+ if (request.onItem) {
+ for (var property in response) {
+ if (dojo.isArray(response[property]) || !dojo.isObject(response[property])) {
+ var checkitem = { uri: itemUri, name: property, value: response[property]};
+ request.onItem(checkitem);
+ break;
+ }
+ }
+ }
+ },
+ error: function(response, ioargs) {
+ if(request.onError) {
+ request.onError(response);
+ }
+ }
+ });
},
@@ -322,11 +410,7 @@
setValues: function(item, attribute, values) { console.log("setValues");
console.log("setValues");
- var oldvalues = item.values;
- item.value = values;
- item.dirty = true;
-
- this.onSet(item, attribute, oldvalues, values);
+ this.setValue(item, attribute, values);
},
unsetAttribute: function( /* item */ item,