Author: reebalazs
Date: Fri Dec 28 12:41:02 2007
New Revision: 50149

Modified:
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/   (props changed)
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/errors.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/forms.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kssparser.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kukit.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js
   kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js
Log:
Base value providers on registry.
Also clean the parameter evaluation a bit,
now all values incl. text are always wrapped.
- in progress...

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/errors.js
==============================================================================
--- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/errors.js     
(original)
+++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/errors.js     
Fri Dec 28 12:41:02 2007
@@ -206,6 +206,11 @@
 ;;;    return setErrorInfo(e, 'EventSetupError', message);
 ;;; };
 
+;;; err.valueProviderError = function(e, message){
+;;;    var message = 'Error checking value provider';
+;;;    return setErrorInfo(e, 'ValueProviderError', message);
+;;; };
+
 
 // any error that happens because the required information
 // cannot be found in the plugin

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js
==============================================================================
--- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js   
(original)
+++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js   
Fri Dec 28 12:41:02 2007
@@ -429,7 +429,7 @@
         // Annotate the bind key on the binder instance
         // the bind key consists of the (generated) classname, and the kss id
         // of the binder.
-        binder.__bindKey__ = kssSelector.getBindKey(); 
+        binder.__bindKey__ = key; 
     }
     return binderInfo;
 };

Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/forms.js
==============================================================================
--- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/forms.js      
(original)
+++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/forms.js      
Fri Dec 28 12:41:02 2007
@@ -305,11 +305,12 @@
 // fieldUpdateRegistry is a public service, available to all components
 // that want to be notified when kss wants to use a field value.
 this.fieldUpdateRegistry = new _FieldUpdateRegistry();
-
+    
 
 // Registry of the pprovider functions for kssSubmitForm
 
-fo.pproviderFormRegistry = new kukit.pr.ValueProviderRegistry();
+fo.pproviderFormRegistry = new kukit.pr.ValueProviderRegistry(
+        kukit.interfaces.global.get('formproviders', 
kukit.interfaces.PluginMethodDescriptor));
 
 // form, currentForm will provide identical functions to those 
 // in normal parameters

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js
==============================================================================
--- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js 
(original)
+++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js 
Fri Dec 28 12:41:02 2007
@@ -67,12 +67,11 @@
     this.name = name;
     this.finalized = false;
     this.registry = {};
-    this.klass;
     this.MethodDescriptor = MethodDescriptor;
 
     this.getMethodDescriptor = function(methodName) {
         // assert prohibited names
-        if (methodName == 'Interfaces' || methodName.substr(0, 3) == 'get' || 
methodName == '_interface') {
+        if (methodName == 'get' || methodName == 'registry') {
 ;;;         kukit.E = 'Method name "' + methodName + '" is prohibited, in 
interface [';
 ;;;         kukit.E += this.name + ']';
             throw new Error(kukit.E);
@@ -151,6 +150,12 @@
     this.registry = {};
 
     this.get = function(name, MethodDescriptor) {
+;;;     // Check for missing parameter; this will cause an error later anyway.
+;;;     if (! MethodDescriptor) {
+;;;             kukit.E = 'NamedInterfaces.get is called for interface [';
+;;;             kukit.E += name + '] without a MethodDescriptor parameter.';
+;;;             throw new Error(kukit.E);
+;;;     }
         // create the descriptor on demand
         var interfaceDescriptor;
         interfaceDescriptor = this.registry[name];
@@ -388,6 +393,8 @@
     this.global.get('binditerations', 
this.BindIterationDescriptor).finalize({});
     // this is not strictly necessary, as we don't get as far as execution
     this.global.get('actions', this.PluginMethodDescriptor).finalize({});
+    this.global.get('valueproviders', 
this.PluginMethodDescriptor).finalize({});
+    this.global.get('selectors', this.PluginMethodDescriptor).finalize({});
 };
 
 this.cleanRoomTearDown = function(suite) {

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kssparser.js
==============================================================================
--- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kssparser.js  
(original)
+++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kssparser.js  
Fri Dec 28 12:41:02 2007
@@ -266,10 +266,10 @@
 }
 
 kukit.kssp.Block.prototype.addActionParameter = function(action, key, value) {
-    var ppRegistries = {
-        '': kukit.pprovidersGlobalRegistry,
-        'kssSelector': kukit.sr.pproviderSelRegistry,
-        'kssSubmitForm': kukit.fo.pproviderFormRegistry
+    var interfaceForAction = {
+        '': kukit.interfaces.global.valueproviders,
+        'kssSelector': kukit.interfaces.global.selectorproviders,
+        'kssSubmitForm': kukit.interfaces.global.formproviders
     };
 
     // <ACTIONNAME>-<KEY>: <VALUE>
@@ -283,19 +283,20 @@
     // (from check).
     //
     // Figure out which registry to use.
-    var registry = ppRegistries[key];
-    if (typeof(registry) == 'undefined') {
-        // use default pproviders
-        registry = ppRegistries[''];
+    var iface = interfaceForAction[key];
+    if (typeof(iface) == 'undefined') {
+        // for all other actions:
+        // use default value pproviders
+        iface = interfaceForAction[''];
     }
     //
-    try {
+;;; try {
         // Check also sets the value provider on the value.
-        value.check(registry);
-    } catch(e) {
-;;;     kukit.E = 'Error in value : ' + e + '.';
-        this.emitError(kukit.E);
-    }
+        value.check(iface);
+;;; } catch(e) {
+;;;     kukit.E = 'Error in value provider for parameter [' + key + '].';
+;;;     kukit.err.valueProviderError(e, kukit.E);
+;;; }
     action.parms[key] = value;
 }
 
@@ -450,8 +451,8 @@
 kukit.kssp.PropValueInMethod.prototype.process =
     kukit.kssp.PropValue.prototype.process;
 kukit.kssp.PropValueInMethod.prototype.produceTxt = function(txt) {
-    // txt parms are returned unwrapped
-    this.txt = txt;
+    // txt parms are returned embedded
+    this.value = new kukit.rd.KssTextValue(txt);
 };
 
 /*
@@ -490,7 +491,12 @@
     } else if (this.notInTokens(context, kukit.kssp.openParent)) {
         this.expectToken(context, kukit.kssp.openParent);
         this.expectToken(context, kukit.kssp.PropValue);
-        this.value = new kukit.rd.KssEventValue(txt, context.token.value);
+        // Create the event binder id
+        // as a method value with a single parameter
+        // to be evaluated later
+        // At this moment context.token.value contains an object with
+        // check and evaluate methods.
+        this.value = new kukit.rd.KssMethodValue(txt, [context.token.value]);
         this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment);
         // we have to be at the end and have no text after
         if (context.txt) {
@@ -524,7 +530,7 @@
 
 kukit.kssp.EventValue.prototype.produceTxt = function(txt) {
     // txt parms are returned embedded
-    this.value = new kukit.rd.KssEventValue(txt, null);
+    this.value = new kukit.rd.KssTextValue(txt);
 };
 
 /*
@@ -631,19 +637,14 @@
                 this.emitError(kukit.E);
             }
         }
-        var valueClass;
-        var args;
         var providedValue;
         if (this.notInTokens(context, kukit.kssp.MethodArgs)){
             this.expectToken(context, kukit.kssp.MethodArgs);
-             valueClass = kukit.rd.KssMethodValue;
-             args = context.token.args;
+             var valueClass = kukit.rd.KssMethodValue;
+             var args = context.token.args;
              providedValue = new valueClass(value, args);
         } else {
-             // XXX This should be wrapped too !
-             //valueClass = kukit.rd.KssTextValue;
-             //providedValue = new valueClass(value);
-             providedValue = value;
+             providedValue = new kukit.rd.KssTextValue(value);
         }
         this.args.push(providedValue);
         if (context.nextTokenIndex == this.result.length-1) break;
@@ -759,9 +760,10 @@
 ;;;     kukit.E += ' space before the colon.';
         this.emitError(kukit.E);
     }
-    if (! pseudotoken.value.methodName) {
+    if ((! pseudotoken.value.isMethod && ! pseudotoken.value.txt) ||
+            (pseudotoken.value.isMethod && ! pseudotoken.value.methodName)) {
 ;;;     kukit.E = 'Wrong event selector :';
-;;;     kukit.E += ' event name cannot have spaces.';
+;;;     kukit.E += ' event name must exist.';
         this.emitError(kukit.E);
     }
     css = this.cursor.text.substring(this.startpos, commatoken.startpos);
@@ -776,26 +778,40 @@
         // just store the single word, in case of event selectors
         css = singleword;
     }
+    // XXX The interfaces for the selector can be taken from a given interface
+    // registry. We use kukit.interfaces now which will make it operate on
+    // the global registry. (This value is also passed to the KssSelector
+    // upon its creation.)
+    var interfaces = kukit.interfaces.global; 
     // create the selector.
     var id = null;
     var ppid = null;
-    if (pseudotoken.value.arg) {
-        // We have something in the parentheses after the event name.
-        if (pseudotoken.value.arg.isMethod) {
-            // we have a param provider here. Just store.
-            ppid = pseudotoken.value.arg;
-            // Check its syntax too.
-            ppid.check(kukit.pprovidersGlobalRegistry);
+    // Process the pseudotoken
+    // it is like: click(1) or sdnd-drag(kssAttr(poolid))
+    var eventName;
+    if (pseudotoken.value.isMethod) {
+        eventName = pseudotoken.value.methodName;
+        var args = pseudotoken.value.args;
+        // XXX TODO check that there is only 1 arg? Should already be checked.
+        var arg = args[0];
+        // Check it in every case.
+        // always check as value provider
+        arg.check(interfaces.valueproviders);
+        if (arg.isMethod) {
+            // store it as ppid
+            ppid = arg;
         } else {
             // just an id. Express in txt.
-            id = pseudotoken.value.arg.txt;
+            id = arg.txt;
         }
+    } else {
+        eventName = pseudotoken.value.txt;
     }
+    //
     // XXX We really don't use the name and the namespace
     // separated here, so the following code could be removed
     // and multi-level namespaces would be supported.
-    var origName = pseudotoken.value.methodName;
-    var name = origName;
+    var name = eventName;
     var splitname = name.split('-');
     var namespace = null;
     if (splitname.length > 2) {
@@ -807,13 +823,9 @@
         name = splitname[1];
         namespace = splitname[0];
     }
-    // XXX The interfaces for the selector can be taken from a given interface
-    // registry. We use kukit.interfaces now which will make it operate on
-    // the global registry.
-    var interfaces = kukit.interfaces.global;
     // Protect the error for better logging
 ;;; try {
-        this.kssSelector = new kukit.rd.KssSelector(isEvent, css, origName,
+        this.kssSelector = new kukit.rd.KssSelector(isEvent, css, eventName,
                 id, ppid, interfaces);
 ;;; } catch(e) {
 ;;;     if (e.name == 'KssSelectorError' || e.name == 'PluginRegistryError') {

Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kukit.js
==============================================================================
--- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kukit.js      
(original)
+++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kukit.js      
Fri Dec 28 12:41:02 2007
@@ -246,6 +246,9 @@
     interfaces.get('events', 
kukit.interfaces.PluginMethodDescriptor).finalize({});
     interfaces.get('binditerations', 
kukit.interfaces.BindIterationDescriptor).finalize({});
     interfaces.get('actions', 
kukit.interfaces.PluginMethodDescriptor).finalize({});
+    interfaces.get('valueproviders', 
kukit.interfaces.PluginMethodDescriptor).finalize({});
+    interfaces.get('formproviders', 
kukit.interfaces.PluginMethodDescriptor).finalize({});
+    interfaces.get('selectorproviders', 
kukit.interfaces.PluginMethodDescriptor).finalize({});
 ;;; kukit.log('All interfaces finalized.');
 ;;; kukit.log('Initializing kinetic stylesheets.');
     // Succesful initialization. At the moment the engine is kept

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js
==============================================================================
--- 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js    
    (original)
+++ 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js    
    Fri Dec 28 12:41:02 2007
@@ -25,8 +25,8 @@
 *  The parameter providers need to be registered here.
 */
 
-kukit.pr.ValueProviderRegistry = function () {
-    this.content = {};
+kukit.pr.ValueProviderRegistry = function (iface) {
+    this.iface = iface;
 };
 
 kukit.pr.ValueProviderRegistry.prototype.register = function(name, func) {
@@ -35,37 +35,12 @@
 ;;;     kukit.E += ' provider [ValueProviderRegistry.register].';
         throw new Error(kukit.E);
     }
-;;; if (this.content[name]) {
-;;;    // Do not allow redefinition
-;;;    var msg = 'Error : parameter provider [' + name;
-;;;    msg += '] already registered.';
-;;;    kukit.logError(msg);
-;;;    return;
-;;; }
-    this.content[name] = func;
-};
-
-kukit.pr.ValueProviderRegistry.prototype.exists = function(name) {
-    var entry = this.content[name];
-    return (typeof(entry) != 'undefined');
-};
-
-kukit.pr.ValueProviderRegistry.prototype.get = function(name) {
-    var func = this.content[name];
-    if (! func) {
-        // not found
-        if (name == '') {
-            // default provider for the strings
-            return kukit.pr.IdentityPP;
-         } else {
-;;;         kukit.E = 'Error : undefined parameter provider [' + name + '].';
-            throw new Error(kukit.E);
-        }
-    }
-    return func;
+    var descriptor = this.iface.getMethodDescriptor(name);
+    descriptor.register(func);
 };
 
-kukit.pprovidersGlobalRegistry = new kukit.pr.ValueProviderRegistry();
+kukit.pprovidersGlobalRegistry = new kukit.pr.ValueProviderRegistry(
+        kukit.interfaces.global.get('valueproviders', 
kukit.interfaces.PluginMethodDescriptor));
 
 /*
 * Register the core parameter providers
@@ -210,12 +185,6 @@
 ;;;         kukit.E += ' [recurseParents]).';
 ;;;         throw new Error(kukit.E);
 ;;;     }
-;;;     if (args[0].toLowerCase() == 'style') {
-;;;         throw new Error('nodeAttr method does not accept [style] as 
attrname.');
-;;;     }
-;;;     if (args[0].match(/[ ]/)) {
-;;;         throw new Error('attrname parameter in nodeAttr method cannot 
contain space.');
-;;;     }
     },
     eval: function(args, node) {
         var argname = args[0];
@@ -225,6 +194,14 @@
 ;;;         kukit.E = '2nd attribute of nodeAttr must be a boolean.';
             kukit.ut.evalBool(recurseParents, kukit.E);
         }
+        if (args[0].toLowerCase() == 'style') {
+;;;         kukit.E = 'nodeAttr method does not accept [style] as attrname.';
+            throw new Error(kukit.E);
+        }
+        if (args[0].match(/[ ]/)) {
+;;;         throw new Error('attrname parameter in nodeAttr method cannot 
contain space.');
+            throw new Error(kukit.E);
+        }
         return kukit.dom.getRecursiveAttribute(node, argname, recurseParents,
             kukit.dom.getAttribute);
     }
@@ -239,11 +216,6 @@
 ;;;         kukit.E += ' [recurseParents]).';
 ;;;         throw new Error(kukit.E);
 ;;;     }
-;;;     if (args[0].match(/[ -]/)) {
-;;;         kukit.E = 'attrname parameter in kssAttr method cannot contain';
-;;;         kukit.E += ' dashes or spaces.';
-;;;         throw new Error(kukit.E);
-;;;     }
     },
     eval: function(args, node) {
         var argname =  args[0];
@@ -253,6 +225,11 @@
 ;;;         kukit.E = '2nd attribute of kssAttr must be a boolean.';
             kukit.ut.evalBool(recurseParents, kukit.E);
         }
+        if (args[0].match(/[ -]/)) {
+;;;         kukit.E = 'attrname parameter in kssAttr method cannot contain';
+;;;         kukit.E += ' dashes or spaces.';
+            throw new Error(kukit.E);
+        }
         return kukit.dom.getRecursiveAttribute(node, argname, recurseParents,
             kukit.dom.getKssAttribute);
     }

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js
==============================================================================
--- 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js   
    (original)
+++ 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js   
    Fri Dec 28 12:41:02 2007
@@ -44,10 +44,6 @@
 ;;;     var msg = 'Kss selector must have a name.';
 ;;;     throw kukit.err.kssSelectorError(msg);
 ;;; }
-;;; if (name.indexOf('@') != -1) {
-;;;     var msg = 'Kss selector name must not contain @: [' + name + '].';
-;;;     throw kukit.err.kssSelectorError(msg);
-;;;     }
 ;;; if (! isEvent) {
 ;;;     // method rule
 ;;;     if (css != 'document' && css != 'behaviour') {
@@ -138,7 +134,7 @@
         return this.id;
     } else {
         // Evaluate it.
-        var id = this.ppid.pprovider.eval(this.ppid.args, node, {});
+        var id = this.ppid.evaluate(node, {});
         // check that the id is not empty or null!
         if (! id) {
 ;;;         kukit.E = 'Did not get a valid state id, when evaluated';
@@ -227,9 +223,9 @@
 
 kukit.rd.KssTextValue.prototype.isMethod = false;
 
-kukit.rd.KssTextValue.prototype.check = function(registry) {
+kukit.rd.KssTextValue.prototype.check = function(iface) {
     // use the IdentityPP provider.
-    this.pprovider = new (registry.get(''))();
+    this.pprovider = new (iface[''])();
 };
 
 kukit.rd.KssTextValue.prototype.evaluate =
@@ -241,7 +237,7 @@
 };
 
 /*
-*  class KssTextValue
+*  class KssMethodValue
 */
 kukit.rd.KssMethodValue = function(methodName, args) {
     // A method parameter in the format 
@@ -252,60 +248,38 @@
 
 kukit.rd.KssMethodValue.prototype.isMethod = true;
 
-kukit.rd.KssMethodValue.prototype.check = function(registry) {
+kukit.rd.KssMethodValue.prototype.check = function(iface) {
     // Check syntax
-    var f = registry.get(this.methodName);
+    var f = iface[this.methodName];
+    // XXX TODO not found error?
     this.pprovider = new f();
+    // Check the providers, this will give diagnostics errors
+    // in case something is wrong with the parameters.
+    // Checking is also needed in production mode.
+    // XXX We use global interfaces
+    var interfaces = kukit.interfaces.global;
+    var valueproviders = interfaces.valueproviders;
     for(i=0; i < this.args.length; i++){
-        // XXX We treat text values separetly because
-        // they are now currently wrapped as KssTextValue
-        // (as they should). TODO
-        var arg = this.args[i];
-        if(arg.check){
-            // With the recursion we always use the global
-            // provider registry
-            arg.check(kukit.pprovidersGlobalRegistry);
-        }
+        // With the recursion we always use the
+        // value provider registry from the same interfaces
+        this.args[i].check(valueproviders);
     }
+;;; // Checking of the value provider itself (nr of args)
 ;;; this.pprovider.check(this.args);
 };
 
 kukit.rd.KssMethodValue.prototype.evaluate =
     function(node, defaultParameters) {
-    // First recursivly evaluate all arguments
+    // First recursively evaluate all arguments
     var newArgs = [];
     for(var i=0; i < this.args.length; i++){
-        // XXX We treat text values separetly because
-        // they are now currently wrapped as KssTextValue
-        // (as they should). TODO
         var arg = this.args[i];
-        if(arg.evaluate){
-            newArgs.push(arg.evaluate(node, defaultParameters));
-        } else {
-            newArgs.push(arg);
-        }
+        newArgs.push(arg.evaluate(node, defaultParameters));
     }
     // return the value
     return this.pprovider.eval(newArgs, node, defaultParameters);
 };
 
-/*
-*  class KssEventValue
-*/
-kukit.rd.KssEventValue = function(methodName, arg) {
-    // A method parameter in the format 
-    //      methodname(v1)
-    // can be also:
-    //      methodname(methodname2(v2))
-    //  in both cases, arg is KssTextValue, or KssMethodValue
-    this.methodName = methodName;
-    this.arg = arg;
-};
-
-kukit.rd.KssEventValue.prototype.isMethod = true;
-
-kukit.rd.KssEventValue.prototype.check = function() {
-};
 
 kukit.rd.EventRuleNr = 0;            // just a counter
 

Modified: 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js
==============================================================================
--- 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js    
    (original)
+++ 
kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js    
    Fri Dec 28 12:41:02 2007
@@ -21,7 +21,8 @@
 
 // Registry of the pprovider functions for selecting
 
-kukit.sr.pproviderSelRegistry = new kukit.pr.ValueProviderRegistry();
+kukit.sr.pproviderSelRegistry = new kukit.pr.ValueProviderRegistry(
+        kukit.interfaces.global.get('selectorproviders', 
kukit.interfaces.PluginMethodDescriptor)); // XXX XXX XXX
 
 
 // this will provide an arbitrary selector, and is designed to
@@ -92,9 +93,12 @@
 kukit.sr.SelectorTypeRegistry.prototype.defaultSelectorType = 'css';
 
 kukit.sr.SelectorTypeRegistry.prototype.register = function(name, func) {
-    if (typeof(func) == 'undefined') {
-        throw new Error('Func is mandatory.');
-    }
+;;; // Check func parameter: diagnostics only, as this will cause
+;;; // an error later anyway.
+;;; if (typeof(func) == 'undefined') {
+;;;     kukit.E = 'Func is mandatory in SelectorTypeRegistry.register.';
+;;;     throw new Error(kukit.E);
+;;; }
 ;;; if (this.mapping[name]) {
 ;;;    // Do not allow redefinition
 ;;;    kukit.logError('Error : redefinition attempt of selector ' + name);
_______________________________________________
Kukit-checkins mailing list
[email protected]
http://codespeak.net/mailman/listinfo/kukit-checkins

Reply via email to