| 1 | #LyX 1.3 created this file. For more info see http://www.lyx.org/ |
| 2 | \lyxformat 221 |
| 3 | \textclass article |
| 4 | \language english |
| 5 | \inputencoding auto |
| 6 | \fontscheme default |
| 7 | \graphics default |
| 8 | \paperfontsize default |
| 9 | \papersize Default |
| 10 | \paperpackage a4 |
| 11 | \use_geometry 0 |
| 12 | \use_amsmath 0 |
| 13 | \use_natbib 0 |
| 14 | \use_numerical_citations 0 |
| 15 | \paperorientation portrait |
| 16 | \secnumdepth 3 |
| 17 | \tocdepth 3 |
| 18 | \paragraph_separation indent |
| 19 | \defskip medskip |
| 20 | \quotes_language english |
| 21 | \quotes_times 2 |
| 22 | \papercolumns 1 |
| 23 | \papersides 1 |
| 24 | \paperpagestyle default |
| 25 | |
| 26 | \layout Title |
| 27 | |
| 28 | LISP-ON-LINES |
| 29 | \layout Section |
| 30 | |
| 31 | Components |
| 32 | \layout Description |
| 33 | |
| 34 | Meta\SpecialChar ~ |
| 35 | Model\SpecialChar ~ |
| 36 | Protocol A Protocol for introspection on relational objects. |
| 37 | \layout Description |
| 38 | |
| 39 | Mewa\SpecialChar ~ |
| 40 | Presentations A Mewa-like |
| 41 | \begin_inset Foot |
| 42 | collapsed true |
| 43 | |
| 44 | \layout Standard |
| 45 | |
| 46 | http://www.adrian-lienhard.ch/files/mewa.pdf |
| 47 | \end_inset |
| 48 | |
| 49 | layer for UncommonWeb |
| 50 | \begin_inset Foot |
| 51 | collapsed true |
| 52 | |
| 53 | \layout Standard |
| 54 | |
| 55 | http://common-lisp.net/project/ucw/ |
| 56 | \end_inset |
| 57 | |
| 58 | Presentations. |
| 59 | \layout Section |
| 60 | |
| 61 | Description |
| 62 | \layout Standard |
| 63 | |
| 64 | LISP-ON-LINES (LOL) is a framework for rapid development of complex data-driven |
| 65 | web appilcations. |
| 66 | |
| 67 | \layout Section |
| 68 | |
| 69 | Introduction: |
| 70 | \layout Section |
| 71 | |
| 72 | Example: |
| 73 | \layout Standard |
| 74 | |
| 75 | First we start with the data model. |
| 76 | The Meta Model Protocol (MMP) is used to provide information on the data |
| 77 | objects and how they relate to one another. |
| 78 | Its is currently implemented as a layer over CLSQL |
| 79 | \begin_inset Foot |
| 80 | collapsed true |
| 81 | |
| 82 | \layout Standard |
| 83 | |
| 84 | http://clsql.b9.com/ |
| 85 | \end_inset |
| 86 | |
| 87 | , although support is planned for other backends (CLOS, Elephant[4], whatever). |
| 88 | \layout Standard |
| 89 | |
| 90 | The MMP shares its definition syntax with CLSQL's Object Oriented Data Definitio |
| 91 | n Language (OODDL) |
| 92 | \begin_inset Foot |
| 93 | collapsed true |
| 94 | |
| 95 | \layout Standard |
| 96 | |
| 97 | http://clsql.b9.com/manual/ref-ooddl.html |
| 98 | \begin_inset Note |
| 99 | collapsed true |
| 100 | |
| 101 | \layout Standard |
| 102 | |
| 103 | Shouldn't this footnote be a bibliographical entry ? or something like that |
| 104 | ? |
| 105 | \end_inset |
| 106 | |
| 107 | |
| 108 | \end_inset |
| 109 | |
| 110 | . |
| 111 | The macro to define view-classes is named DEF-VIEW-CLASS/META, and takes |
| 112 | the same arguments as DEF-VIEW-CLASS from CLSQL. |
| 113 | For the purposes of this simple example, we will only need two functions |
| 114 | from the MMP beyond what CLSQL provides : LIST-SLOTS and LIST-SLOT-TYPES[5]. |
| 115 | \layout Standard |
| 116 | |
| 117 | We'll define a simple class to hold a user. |
| 118 | \layout LyX-Code |
| 119 | |
| 120 | (def-view-class/meta user () |
| 121 | \layout LyX-Code |
| 122 | |
| 123 | ((userid :initarg :userid :accessor userid :type integer :db-kind :key) |
| 124 | \layout LyX-Code |
| 125 | |
| 126 | (username :initarg :username :accessor username :type string :db-kind |
| 127 | :base) |
| 128 | \layout LyX-Code |
| 129 | |
| 130 | (password :initarg :password :accessor password :type string :db-kind |
| 131 | :base))) |
| 132 | \layout LyX-Code |
| 133 | |
| 134 | \layout LyX-Code |
| 135 | |
| 136 | STYLE-WARNING: redefining META-MODEL.METADATA (USER) in DEFMETHOD |
| 137 | \layout LyX-Code |
| 138 | |
| 139 | #<CLSQL-SYS::STANDARD-DB-CLASS USER> |
| 140 | \layout LyX-Code |
| 141 | |
| 142 | \layout LyX-Code |
| 143 | |
| 144 | (defparameter user (make-instance 'user :userid 1 |
| 145 | \layout LyX-Code |
| 146 | |
| 147 | :username "drewc" |
| 148 | \layout LyX-Code |
| 149 | |
| 150 | :password "p@ssw0rd")) |
| 151 | \layout LyX-Code |
| 152 | |
| 153 | \layout LyX-Code |
| 154 | |
| 155 | USER |
| 156 | \layout LyX-Code |
| 157 | |
| 158 | \layout LyX-Code |
| 159 | |
| 160 | LISP-ON-LINES> (list-slots user) |
| 161 | \layout LyX-Code |
| 162 | |
| 163 | (USERID USERNAME PASSWORD) |
| 164 | \layout LyX-Code |
| 165 | |
| 166 | LISP-ON-LINES> (list-slot-types user) |
| 167 | \layout LyX-Code |
| 168 | |
| 169 | ((USERID INTEGER) (USERNAME STRING) (PASSWORD STRING)) |
| 170 | \layout LyX-Code |
| 171 | |
| 172 | ; compiling file "/tmp/fileQQsHyN" (written 03 JUN 2005 03:20:06 PM): |
| 173 | \layout LyX-Code |
| 174 | |
| 175 | ; /tmp/fileQQsHyN.fasl written |
| 176 | \layout LyX-Code |
| 177 | |
| 178 | ; compilation finished in 0:00:00 |
| 179 | \layout LyX-Code |
| 180 | |
| 181 | \layout LyX-Code |
| 182 | |
| 183 | \layout LyX-Code |
| 184 | |
| 185 | (default-attributes user) |
| 186 | \layout LyX-Code |
| 187 | |
| 188 | ((userid integer :label "User ID" :slot-name 'userid) |
| 189 | \layout LyX-Code |
| 190 | |
| 191 | (username string :label "User name" :slot-name 'username) |
| 192 | \layout LyX-Code |
| 193 | |
| 194 | (password string :label "Password" :slot-name 'password)) |
| 195 | \layout LyX-Code |
| 196 | |
| 197 | \layout LyX-Code |
| 198 | |
| 199 | LISP-ON-LINES> (set-default-attributes user) |
| 200 | \layout LyX-Code |
| 201 | |
| 202 | ((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 203 | \layout LyX-Code |
| 204 | |
| 205 | (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 206 | \layout LyX-Code |
| 207 | |
| 208 | (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)) |
| 209 | \layout LyX-Code |
| 210 | |
| 211 | LISP-ON-LINES> (find-class-attributes user) |
| 212 | \layout LyX-Code |
| 213 | |
| 214 | (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) |
| 215 | \layout LyX-Code |
| 216 | |
| 217 | (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 218 | \layout LyX-Code |
| 219 | |
| 220 | (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 221 | \layout LyX-Code |
| 222 | |
| 223 | COMMON-LISP:NIL) |
| 224 | \layout LyX-Code |
| 225 | |
| 226 | LISP-ON-LINES> ;;;; note that the mewa functions (find-attribute, set-attribute |
| 227 | etc) can take either an instance, or a class-name as a symbol , ie : |
| 228 | \layout LyX-Code |
| 229 | |
| 230 | ; No value |
| 231 | \layout LyX-Code |
| 232 | |
| 233 | LISP-ON-LINES> (find-class-attributes 'user) |
| 234 | \layout LyX-Code |
| 235 | |
| 236 | (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) |
| 237 | \layout LyX-Code |
| 238 | |
| 239 | (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 240 | \layout LyX-Code |
| 241 | |
| 242 | (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 243 | \layout LyX-Code |
| 244 | |
| 245 | COMMON-LISP:NIL) |
| 246 | \layout LyX-Code |
| 247 | |
| 248 | LISP-ON-LINES> (find-class-attributes (make-instance 'user)) |
| 249 | \layout LyX-Code |
| 250 | |
| 251 | (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) |
| 252 | \layout LyX-Code |
| 253 | |
| 254 | (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 255 | \layout LyX-Code |
| 256 | |
| 257 | (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 258 | \layout LyX-Code |
| 259 | |
| 260 | COMMON-LISP:NIL) |
| 261 | \layout LyX-Code |
| 262 | |
| 263 | LISP-ON-LINES> |
| 264 | \layout Standard |
| 265 | |
| 266 | Using that information, we have enough to create an interface to the object. |
| 267 | UncommonWeb includes a powerful presentation system, but it is not quite |
| 268 | dynamic enough for our needs. |
| 269 | Mewa defines an approach to presentations that suits our purposes, but |
| 270 | the paper is written from a smalltalk point of view. |
| 271 | A mixture of the two , Mewa Presentations(MP), is described here. |
| 272 | \layout Standard |
| 273 | |
| 274 | MP introduces to UCW the concept of attributes. |
| 275 | an attribute is essentially a named version of the defpresentation slot-like |
| 276 | arguments. |
| 277 | for example in : |
| 278 | \layout Standard |
| 279 | |
| 280 | (defpresentation person-editor (object-presentation) |
| 281 | \layout Standard |
| 282 | |
| 283 | ((string :label "First Name" :slot-name 'first-name :max-length 30))) |
| 284 | \layout Standard |
| 285 | |
| 286 | the (string :label "First Name" ...) form is an attribute definiton. |
| 287 | Attributes are accessed through FIND-ATTIRIBUTES, and are composed at run |
| 288 | time (where the current system is done at compile time) to display the |
| 289 | object. |
| 290 | This allows a very flexible system of displaying objects which is reminiscent |
| 291 | of CSS. |
| 292 | I discovered this, rather than invent or design it, so there are some rough |
| 293 | edges, but its a good start. |
| 294 | \layout Standard |
| 295 | |
| 296 | Its much easier to show this then to tell. |
| 297 | Lets present our user class. |
| 298 | Currently in UCW, you'd define a presentation as such : |
| 299 | \layout Standard |
| 300 | |
| 301 | (defpresentation user-presentation (object-presentation) |
| 302 | \layout Standard |
| 303 | |
| 304 | ((INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 305 | \layout Standard |
| 306 | |
| 307 | (STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 308 | \layout Standard |
| 309 | |
| 310 | (STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD))) |
| 311 | \layout Standard |
| 312 | |
| 313 | which could be presented using PRESENT-OBJECT : |
| 314 | \layout Standard |
| 315 | |
| 316 | (present-object user :using 'user-presentation) |
| 317 | \layout Standard |
| 318 | |
| 319 | The equiv approach using mewa presentations is actually longer and more |
| 320 | verbose(!) but it serves to demonstrate how the MP system works. |
| 321 | \layout Standard |
| 322 | |
| 323 | Mewa Presentations adds a set of attributes to a class, keyed off the class |
| 324 | name. |
| 325 | Attributes are inherited, so if you define an attribute on T, you can use |
| 326 | it with any class. |
| 327 | \layout Standard |
| 328 | |
| 329 | MP stores named attributes keyed on a class name. |
| 330 | to achieve the same functionality as the above using mp would look like |
| 331 | this : |
| 332 | \layout Standard |
| 333 | |
| 334 | LISP-ON-LINES> (setf (find-attribute 'user :viewer) '(mewa-object-presentation |
| 335 | :attributes (userid username password) :global-properties (:editablep nil))) |
| 336 | \layout Standard |
| 337 | |
| 338 | (:VIEWER MEWA-OBJECT-PRESENTATION |
| 339 | \layout Standard |
| 340 | |
| 341 | :ATTRIBUTES |
| 342 | \layout Standard |
| 343 | |
| 344 | (USERID USERNAME PASSWORD) |
| 345 | \layout Standard |
| 346 | |
| 347 | :GLOBAL-PROPERTIES |
| 348 | \layout Standard |
| 349 | |
| 350 | (:EDITABLEP NIL)) |
| 351 | \layout Standard |
| 352 | |
| 353 | LISP-ON-LINES> (setf (find-attribute 'user 'userid) '(INTEGER :LABEL "USERID" |
| 354 | :SLOT-NAME USERID)) |
| 355 | \layout Standard |
| 356 | |
| 357 | (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 358 | \layout Standard |
| 359 | |
| 360 | LISP-ON-LINES> (setf (find-attribute 'user 'username) '(STRING :LABEL "USERNAME" |
| 361 | :SLOT-NAME USERNAME)) |
| 362 | \layout Standard |
| 363 | |
| 364 | (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 365 | \layout Standard |
| 366 | |
| 367 | LISP-ON-LINES> (setf (find-attribute 'user 'password) '(STRING :LABEL "USERNAME" |
| 368 | :SLOT-NAME PASSWORD)) |
| 369 | \layout Standard |
| 370 | |
| 371 | (PASSWORD STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD) |
| 372 | \layout Standard |
| 373 | |
| 374 | LISP-ON-LINES> (find-class-attributes 'user) |
| 375 | \layout Standard |
| 376 | |
| 377 | (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD) |
| 378 | \layout Standard |
| 379 | |
| 380 | (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME) |
| 381 | \layout Standard |
| 382 | |
| 383 | (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID) |
| 384 | \layout Standard |
| 385 | |
| 386 | (:VIEWER MEWA-OBJECT-PRESENTATION |
| 387 | \layout Standard |
| 388 | |
| 389 | :ATTRIBUTES |
| 390 | \layout Standard |
| 391 | |
| 392 | (USERID USERNAME PASSWORD) |
| 393 | \layout Standard |
| 394 | |
| 395 | :GLOBAL-PROPERTIES |
| 396 | \layout Standard |
| 397 | |
| 398 | (:EDITABLEP NIL)) |
| 399 | \layout Standard |
| 400 | |
| 401 | COMMON-LISP:NIL) |
| 402 | \layout Standard |
| 403 | |
| 404 | this is all turned into a UCW presentation at runtime using MAKE-PRESENTATION |
| 405 | : |
| 406 | \layout Standard |
| 407 | |
| 408 | (defmethod render-on ((res response) (e presentations-index)) |
| 409 | \layout Standard |
| 410 | |
| 411 | " |
| 412 | \layout Standard |
| 413 | |
| 414 | As you'll see, nothing is exported from the LISP-ON-LINES package. |
| 415 | |
| 416 | \layout Standard |
| 417 | |
| 418 | if you wish to use LOL in your own package (or in UCW-USER or whatever), |
| 419 | \layout Standard |
| 420 | |
| 421 | you simply need to use the MEWA and META-MODEL packages" |
| 422 | \layout Standard |
| 423 | |
| 424 | (<ucw:render-component :component (lisp-on-lines::make-presentation lisp-on-line |
| 425 | s::user :type :viewer))) |
| 426 | \layout Standard |
| 427 | |
| 428 | SET-ATTRIBUTE can be used in place of (setf (find-attribute)) when you want |
| 429 | to "inherit" the properties of an existing attribute definition : |
| 430 | \layout Standard |
| 431 | |
| 432 | LISP-ON-LINES> (set-attribute 'user 'password '(string :label "password: |
| 433 | (must be at leat 8 chars)")) |
| 434 | \layout Standard |
| 435 | |
| 436 | (PASSWORD STRING |
| 437 | \layout Standard |
| 438 | |
| 439 | :LABEL |
| 440 | \layout Standard |
| 441 | |
| 442 | "password: (must be at leat 8 chars)" |
| 443 | \layout Standard |
| 444 | |
| 445 | :SLOT-NAME |
| 446 | \layout Standard |
| 447 | |
| 448 | PASSWORD) |
| 449 | \layout Standard |
| 450 | |
| 451 | Now we want to create a presentation with which to edit the username. |
| 452 | we will use the existing attributes on a subclass of mewa-object-presetation |
| 453 | : |
| 454 | \layout Standard |
| 455 | |
| 456 | LISP-ON-LINES> (defcomponent user-editor (mewa-object-presentation) |
| 457 | \layout Standard |
| 458 | |
| 459 | () |
| 460 | \layout Standard |
| 461 | |
| 462 | (:default-initargs |
| 463 | \layout Standard |
| 464 | |
| 465 | :attributes '((username :label "Enter your New Username") password) |
| 466 | \layout Standard |
| 467 | |
| 468 | :global-properties '(:editablep t))) |
| 469 | \layout Standard |
| 470 | |
| 471 | USER-EDITOR |
| 472 | \layout Standard |
| 473 | |
| 474 | LISP-ON-LINES> (setf (find-attribute 'user :editor) '(user-editor)) |
| 475 | \layout Standard |
| 476 | |
| 477 | (:EDITOR USER-EDITOR) |
| 478 | \layout Standard |
| 479 | |
| 480 | LISP-ON-LINES> |
| 481 | \layout Standard |
| 482 | |
| 483 | which we then can display below our earlier example : |
| 484 | \layout Standard |
| 485 | |
| 486 | (defmethod render-on ((res response) (e presentations-index)) |
| 487 | \layout Standard |
| 488 | |
| 489 | " |
| 490 | \layout Standard |
| 491 | |
| 492 | As you'll see, nothing is exported from the LISP-ON-LINES package. |
| 493 | |
| 494 | \layout Standard |
| 495 | |
| 496 | if you wish to use LOL in your own package (or in UCW-USER or whatever), |
| 497 | \layout Standard |
| 498 | |
| 499 | you simply need to use the MEWA and META-MODEL packages" |
| 500 | \layout Standard |
| 501 | |
| 502 | (<ucw:render-component :component (lisp-on-lines::make-presentation lisp-on-line |
| 503 | s::user :type :viewer)) |
| 504 | \layout Standard |
| 505 | |
| 506 | (<ucw:render-component :component (lisp-on-lines::make-presentation lisp-on-line |
| 507 | s::user :type :editor))) |
| 508 | \layout Standard |
| 509 | |
| 510 | that should give you some idea on how it works .. |
| 511 | ask me when you get confused :) |
| 512 | \the_end |