From VisualWorks®, 7.2 of October 20, 2003 on October 20, 2003 at 1:15:30 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] Item Smalltalk Core.Object false none id name description picture price ShoppingDemo ShoppingDemo Item An item for sale. Instance Variables: id <Intger> a unique identifier name <String> The short name of the item. description <String> A longer description of the item. picture <String> a path to the picture that shows this item price <Number> The price of the item. Customer Smalltalk Core.Object false none id name creditCardNumber shoppingCart ShoppingDemo ShoppingDemo Customer This represents a customer Instance Variables: id <Integer> The unique identifier for the customer. name <String> Customer's login name creditCardNumber <String> The customer's credit card number for purchases. shoppingCart <ShoppingCart> The purchases this customer has made. ToyzInput Smalltalk VisualWave.SingleThreadModelServlet false none model ShoppingDemo ShoppingDemo ToyzInput ToyzInput is the single servlet that handles all input, and delegates to the ShoppingSite object (the model). Instance Variables: model <ShoppingSite> acts as a glue layer to the actual domain objects ShoppingSite Smalltalk Core.Object false none actions currentPage catalog shoppingCart tempId ShoppingDemo ShoppingDemo ShoppingSite This is the main class for the shopping example, it acts like an application model to tie together the various domain objects and to control the display. The typical flow of control is that input comes in via the ToyzInput servlet. The ShoppingSite maps the input to its various aspects. These aspects do not (currently) hold ValueModels as in a traditional ApplicationModel, but are simply get/set method pairs. Once the input has been accepted, the servlet asks the site for the appropriate action based on its input and performs the method. These methods may change the current page, in which case the result displayed back to the browser will change. Instance Variables: actions <Dictionary from: String to: Symbol> Mapping from HTML actions to methods to be performed on this object. e.g. Login->login. currentPage <String> The name of the current HTML page being displayed. catalog <Catalog> The current catalog being viewed. shoppingCart <ShoppingCart> The current customer's shopping cart. tempId <String> A temporary aspect for holding the id of an object to be operated on. ShoppingCart Smalltalk Core.Object false none id customer items ShoppingDemo ShoppingDemo ShoppingCart A standard shopping cart, the set of items this customer has put aside for purchase in this session. Instance Variables: id <Integer> A unique identifier. customer <Customer> The customer who is buying these items. items <Collection of: Item> The items being purchased. Catalog Smalltalk Core.Object false none id itemsForSale ShoppingDemo ShoppingDemo Catalog This class represents one of our multiple catalogs. Instance Variables: id <Integer> The unique identifier for this catalog. itemsForSale <Collection of: Item> The items available in this catalog. Item accessing description ^description. description: aString description := aString. displayPrice ^ (NumberPrintPolicy print: price using: '$ #,###.00;($ #,###.00);$ 0.00;$ 0.00') asString. id ^id. id: anInteger id := anInteger. name ^name name: aString name := aString. picture ^picture picture: aString picture := aString. price ^price price: aNumber price := aNumber. Item printing printOn: aStream aStream nextPutAll: self name. Item class examples example1 ^self new id: 1; name: 'Assault Penguin'; description: 'Authentic replica, in finest plastic, of a fully armed and armoured assault penguin'; picture: 'assault.gif'; price: 49.95. example2 ^self new id: 2; name: 'Wind-Up Penguin'; description: 'This beautiful penguin, hand-crafted from the finest plastic, will delight any child and be an ornament to any home'; picture: 'windup.gif'; price: 4.49. example3 ^self new id: 3; name: 'Stained Glass Penguin'; description: 'A stained-glass penguin to catch and reflect the light, or just sit on the bookshelf'; picture: 'stainedglass.gif'; price: 57.63. example4 ^self new id: 4; name: 'Penguin Pull-Toy'; description: 'A charming hardwood pull-toy, complete with wheels'; picture: 'pulltoy.gif'; price: 40.00. example5 ^self new id: 5; name: 'Racing Cockroach'; description: 'Fun for the whole family'; picture: 'cockroach.gif'; price: 3.95. Customer initialize initialize shoppingCart := ShoppingCart new. Customer accessing name ^name. name: aString name := aString. Customer class instance creation named: aString "It would be nice to remember who our customers are, but not necessary for today." ^self new name: aString. new ^super new initialize. ToyzInput executing action ^model actionFor: (request method = 'POST' ifTrue: [self submitAction] ifFalse: [self queryAction]) doGet self doStuff. doPost self doStuff. doStuff "We can answer gets or posts interchangeably" model := session at: 'model' ifAbsentPut: [ShoppingSite new]. model getInputFrom: request parameters. model perform: self action. self forward: model currentPage. "We have registered the Servlet using a logical name in the configuration file, so we can just use the file name for the current page. If you do not register the Servlet, you must prefix the current page with ../ because we will always be coming here from something which is /servlet, and the ssp pages are not /servlet." forward: aString "Forward the request. Here we'll use a redirect. This is slower than a true forward, because it makes the client go and get the other page, but it leaves the URLS looking correct, which otherwise is harder to deal with." self redirectTo: aString. "The alternative would be " " (self getRequestDispatcher: aString) forward: request response: response." ToyzInput private queryAction ^(request parameters at: 'action') first. submitAction ^(request parameters at: 'Submit') first. ShoppingSite aspects actionFor: aString ^self actions at: aString ifAbsent: [#doNothing]. actions actions isNil ifTrue: [self initializeActions]. ^actions. catalogName ^ self catalog name. catalogName: aString catalog := self lookupCatalogByName: aString. catalogs: aCollection self catalogName: aCollection first. itemId: aString self tempId: aString. lookupCatalogByName: aString ^Catalog named: aString. tempId ^tempId. tempId: aString tempId := aString. username ^shoppingCart customer name. username: aString shoppingCart customer: (shoppingCart lookupCustomerByName: aString). ShoppingSite accessing catalog catalog isNil ifTrue: [ catalog := Catalog default ]. ^ catalog. catalogHeader self catalog id = 1 ifTrue: [ ^ 'mainCatalogHeader' ]. ^ 'clearanceCatalogHeader'. currentPage ^currentPage. displayTotalAmount ^ (NumberPrintPolicy print: (shoppingCart totalAmount) using: '$ #,###.00;($ #,###.00);$ 0.00;$ 0.00') asString. items ^ self catalog items. itemsInCart ^shoppingCart items. totalAmount ^ shoppingCart totalAmount. ShoppingSite actions addToShoppingCart shoppingCart addItem: (self catalog itemWithId: tempId). currentPage := 'reviewcart.ssp'. doNothing self halt. login self username isEmpty ifFalse: [ shoppingCart clearItems. currentPage := 'catalog.ssp' ]. loginAsGuest self username: 'Guest'. self login. logoff shoppingCart clearItems. currentPage := 'main.ssp'. reviewShoppingCart currentPage := 'reviewcart.ssp'. selectClearanceCatalog self catalogName: 'ClearanceItems'. currentPage := 'catalog.ssp'. selectDefaultCatalog self catalogName: 'Default'. currentPage := 'catalog.ssp'. ShoppingSite input getInputFrom: aDictionary aDictionary keysAndValuesDo: [:key :value | self setAspectFor: key to: value]. setAspectFor: key to: value | selector | selector := (key, ':') asSymbol. (self respondsTo: selector) ifTrue: [ self perform: selector with: value first]. ShoppingSite initialize initialize shoppingCart := ShoppingCart new. currentPage := 'main.ssp'. initializeActions actions := Dictionary new. actions at: 'Login as Guest' put: #loginAsGuest. actions at: 'Login' put: #login. actions at: 'logoff' put: #logoff. actions at: 'add' put: #addToShoppingCart. actions at: 'selectClearance' put: #selectClearanceCatalog. actions at: 'selectDefault' put: #selectDefaultCatalog. actions at: 'reviewCart' put: #reviewShoppingCart. ShoppingSite class instance creation new ^super new initialize. ShoppingCart accessing addItem: anItem items add: anItem. clearItems items := OrderedCollection new. customer ^customer. customer: aCustomer customer := aCustomer. items ^items. totalAmount ^items inject: 0 into: [:sum :each | sum + each price]. ShoppingCart initialize initialize items := OrderedCollection new. ShoppingCart lookup lookupCustomerByName: aString ^Customer named: aString. ShoppingCart class instance creation new ^super new initialize. Catalog accessing addItem: anItem itemsForSale add: anItem. allCatalogs "Return a list of all catalog names" ^#('Default' 'ClearanceItems'). id ^ id. items ^itemsForSale. itemWithId: anId ^self items detect: [:each | each id displayString = anId] ifNone: [nil]. Catalog initialize initialize itemsForSale := OrderedCollection new. initializeClearance self addItem: Item example5. id := 0. initializeDefault self addItem: Item example1. self addItem: Item example2. self addItem: Item example3. self addItem: Item example4. id := 1. Catalog class instance creation clearanceitems ^Catalog new initializeClearance. default ^Catalog new initializeDefault. named: aString | catalogName | catalogName := aString asLowercase asSymbol. ^self perform: catalogName. new ^super new initialize. "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' Object Core false none Kernel-Objects Kernel-Objects SingleThreadModelServlet VisualWave VisualWave.HttpServlet false none request response session Web Toolkit-Servlet Servlet