KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nightlabs > ipanema > store > Product


1 /*
2  * Created on 24.09.2004
3  *
4  */

5 package com.nightlabs.ipanema.store;
6
7 import java.io.Serializable JavaDoc;
8 import java.util.Collection JavaDoc;
9 import java.util.HashMap JavaDoc;
10 import java.util.HashSet JavaDoc;
11 import java.util.Map JavaDoc;
12 import java.util.Set JavaDoc;
13
14 import javax.jdo.JDOHelper;
15 import javax.jdo.PersistenceManager;
16 import javax.jdo.StoreCallback;
17
18 import com.nightlabs.inheritance.FieldInheriter;
19 import com.nightlabs.inheritance.Inheritable;
20 import com.nightlabs.inheritance.InheritanceCallbacks;
21 import com.nightlabs.inheritance.MapFieldInheriter;
22 import com.nightlabs.inheritance.jdo.JDOSimpleFieldInheriter;
23 import com.nightlabs.ipanema.organisation.LocalOrganisation;
24 import com.nightlabs.jdo.BaseObjectID;
25
26 /**
27  * @author Niklas Schiffler <nick@nightlabs.de>
28  * @author marco schulze - marco at nightlabs dot de
29  *
30  * @jdo.persistence-capable
31  * identity-type = "application"
32  * objectid-class = "com.nightlabs.ipanema.store.id.ProductID"
33  * detachable = "true"
34  *
35  * @jdo.inheritance strategy = "new-table"
36  **/

37 public class Product
38         implements
39                 StoreCallback,
40                 Inheritable, InheritanceCallbacks,
41                 Serializable JavaDoc
42 {
43     /**
44      * If the organisationID is null while the object is about to be persisted,
45      * it is automatically set to the local organisationID.
46      *
47      * @jdo.field primary-key="true"
48      * @jdo.column length="100"
49      */

50     private String JavaDoc organisationID = null;
51
52     /**
53      * @jdo.field primary-key="true"
54      * @jdo.column length="100"
55      */

56     private String JavaDoc productID;
57
58     /**
59      * @jdo.field persistence-modifier="persistent"
60      */

61     private Product extendedProduct;
62
63     public static final String JavaDoc NATURE_TYPE = "type";
64     public static final String JavaDoc NATURE_INSTANCE = "instance";
65
66     /**
67      * Products use inheritence. This means, there is a tree of which Types form the branches
68      * and instances are the leafs. It is not possible to extend a ProductInstance.
69      *
70      * @jdo.field persistence-modifier="persistent"
71      */

72     private String JavaDoc nature;
73
74     /**
75      * key: String fieldName<br/>
76      * value: ProductFieldMetaData fieldMetaData
77      *
78      * @jdo.field
79      * persistence-modifier="persistent"
80      * collection-type="map"
81      * key-type="java.lang.String"
82      * value-type="ProductFieldMetaData"
83      * dependent="true"
84      * mapped-by="product"
85      *
86      * @jdo.map-vendor-extension vendor-name="jpox" key="key-field" value="fieldName"
87      * @jdo.map-vendor-extension vendor-name="jpox" key="key-length" value="max 100"
88      */

89     protected Map JavaDoc fieldMetaDataMap = new HashMap JavaDoc();
90
91     // IMHO The base class of Product should not have a multilingual name. It should not have
92
// a name at all, because this causes heavy load and most products (e.g. seats) do not need
93
// it. They need a row and a column which is sth. different.
94
// /**
95
// * key: String languageID<br/>
96
// * value: String productName
97
// *
98
// * @jdo.field
99
// * persistence-modifier="persistent"
100
// * collection-type="map"
101
// * key-type="java.lang.String"
102
// * value-type="java.lang.String"
103
// * dependent="true"
104
// *
105
// * @jdo.join
106
// *
107
// * @jdo.map-vendor-extension vendor-name="jpox" key="key-length" value="max 100"
108
// * @jdo.map-vendor-extension vendor-name="jpox" key="value-length" value="max 255"
109
// */
110
// protected Map names = new HashMap();
111

112 // /**
113
// * key: String propertyName<br/>
114
// * value: String propertyValue
115
// *
116
// * @jdo.field
117
// * persistence-modifier="persistent"
118
// * collection-type="map"
119
// * key-type="java.lang.String"
120
// * value-type="java.lang.String"
121
// *
122
// * @jdo.join
123
// *
124
// * @jdo.map-vendor-extension vendor-name="jpox" key="clear-on-delete" value="true"
125
// * @jdo.map-vendor-extension vendor-name="jpox" key="key-length" value="max 200"
126
// * @jdo.map-vendor-extension vendor-name="jpox" key="value-length" value="max 255"
127
// */
128
// protected Map properties = new HashMap();
129

130     /**
131      * key: String compositeKey(organisationID + '/' + productID)<br/>
132      * value: Product product
133      * <p>
134      * The nature of all packagedProducts must match the nature of this Product.
135      * Means, if the nature of this Product is "Type", this Map must exclusively contain
136      * Products with the nature "Type". If the nature is "Instance", it must contain
137      * Products with the nature "Instance".
138      *
139      * @jdo.field
140      * persistence-modifier="persistent"
141      * collection-type="map"
142      * key-type="java.lang.String"
143      * value-type="Product"
144      *
145      * @jdo.join
146      */

147     private Map JavaDoc packagedProducts = new HashMap JavaDoc();
148
149     /**
150      * @jdo.field persistence-modifier="persistent"
151      */

152     private boolean productFactoryAssigned;
153
154     /**
155      * @jdo.field persistence-modifier="persistent"
156      */

157     private ProductFactory productFactory;
158     
159     /**
160      * A <tt>Product</tt> is tagged internal if it is not intended for being
161      * sold outside of a package. Certain helper products (e.g. the inner
162      * product of a seat representing the basic price) have this flag set true.
163      *
164      * @jdo.field persistence-modifier="persistent"
165      */

166     private boolean internal;
167
168     protected static String JavaDoc EMPTYSTRING = "";
169
170     protected Product() {}
171
172     /**
173      * @param organisationID This may be null. It will then be found out while being persisted the first time.
174      * @param productID
175      * @param extendedProduct
176      * @param nature
177      * @param productFactory
178      * @param internal True, if the Product cannot be sold directly but is only sold while
179      * packaged within a different Product.
180      */

181     public Product(
182             String JavaDoc organisationID, String JavaDoc productID, Product extendedProduct,
183             String JavaDoc nature, ProductFactory productFactory, boolean internal)
184     {
185         if (organisationID != null)
186           setOrganisationID(organisationID);
187
188         setProductID(productID);
189         setNature(nature);
190         setExtendedProduct(extendedProduct);
191
192         this.setProductFactory(productFactory);
193         this.internal = internal;
194
195 // initFieldMetaData();
196
}
197
198     /**
199      * @return Returns the organisationID.
200      */

201     public String JavaDoc getOrganisationID()
202     {
203         return organisationID;
204     }
205     /**
206      * @param organisationID The organisationID to set.
207      */

208     protected void setOrganisationID(String JavaDoc organisationID)
209     {
210         BaseObjectID.assertValidIDString(organisationID, "organisationID");
211         this.organisationID = organisationID;
212     }
213     /**
214      * @param productID The productID to set.
215      */

216     protected void setProductID(String JavaDoc productID)
217     {
218         BaseObjectID.assertValidIDString(productID, "productID");
219         this.productID = productID;
220     }
221     public String JavaDoc getProductID()
222     {
223         return productID;
224     }
225
226     public static String JavaDoc getPrimaryKey(String JavaDoc organisationID, String JavaDoc productID)
227     {
228         if (organisationID == null)
229             throw new NullPointerException JavaDoc("organisationID must not be null!");
230         if (productID == null)
231             throw new NullPointerException JavaDoc("productID must not be null!");
232         return organisationID + '/' + productID;
233     }
234     public String JavaDoc getPrimaryKey()
235     {
236         return organisationID + '/' + productID;
237     }
238
239     /**
240      * @return Returns the extendedProduct.
241      */

242     public Product getExtendedProduct()
243     {
244         return extendedProduct;
245     }
246     /**
247      * @param extendedProduct The extendedProduct to set.
248      */

249     protected void setExtendedProduct(Product extendedProduct)
250     {
251         if (extendedProduct != null) {
252             if (!NATURE_TYPE.equals(extendedProduct.getNature()))
253                 throw new IllegalArgumentException JavaDoc("extendedProduct is not of nature NATURE_TYPE. Cannot extend!");
254
255             if (!(extendedProduct.getClass().isInstance(this)))
256                 throw new IllegalArgumentException JavaDoc("This product (\""+this.getPrimaryKey()+"\") is of type " + this.getClass().getName() + " and cannot extend the product \""+extendedProduct.getPrimaryKey()+"\" which is of type "+extendedProduct.getClass().getName());
257         }
258
259         this.extendedProduct = extendedProduct;
260     }
261
262     /**
263      * @return Returns the nature.
264      */

265     public String JavaDoc getNature()
266     {
267         return nature;
268     }
269     /**
270      * @param nature The nature to set.
271      */

272     protected void setNature(String JavaDoc nature)
273     {
274         if (nature == null)
275             throw new NullPointerException JavaDoc("nature must not be null!");
276         if (!NATURE_INSTANCE.equals(nature) && !NATURE_TYPE.equals(nature))
277             throw new IllegalArgumentException JavaDoc("nature must be one of: NATURE_TYPE, NATURE_INSTANCE");
278         this.nature = nature;
279     }
280
281 // public String getName()
282
// {
283
// return (String)names.get(EMPTYSTRING);
284
// }
285
//
286
// public String getName(String languageID)
287
// {
288
// if (languageID == null)
289
// languageID = EMPTYSTRING;
290
// String res = (String)names.get(languageID);
291
// if (res == null)
292
// res = (String)names.get(EMPTYSTRING);
293
// return res;
294
// }
295
//
296
// public void setName(String languageID, String name)
297
// {
298
// if (languageID == null)
299
// languageID = EMPTYSTRING;
300
// names.put(languageID, name);
301
// }
302

303 // // *** begin: properties ***
304
// public Map getProperties()
305
// {
306
// return properties;
307
// }
308
//
309
// public void setProperty(String name, String value)
310
// {
311
// if (name == null)
312
// throw new NullPointerException("name must not be null!");
313
// properties.put(name, value);
314
// }
315
//
316
// public void removeProperty(String name)
317
// {
318
// properties.remove(name);
319
// }
320
//
321
// public String getProperty(String name)
322
// {
323
// if(properties.containsKey(name))
324
// return (String)properties.get(name);
325
// else
326
// return EMPTYSTRING;
327
// }
328
//
329
// public boolean propertyExists(String name)
330
// {
331
// return properties.containsKey(name);
332
// }
333
// // *** end: properties ***
334

335     // *** begin: packagedProducts ***
336
public void addPackagedProduct(Product product)
337     {
338         if (!this.getNature().equals(product.getNature()))
339             throw new IllegalArgumentException JavaDoc("Nature of product to package (\""+product.getNature()+"\") and this nature (\""+this.getNature()+"\") does not match!");
340
341         packagedProducts.put(product.getPrimaryKey(), product);
342     }
343     /**
344      * @return Returns a Collection of Product.
345      */

346     public Collection JavaDoc getPackagedProducts()
347     {
348         return packagedProducts.values();
349     }
350     /**
351      * @param organisationID
352      * @param productID
353      * @return Returns a packaged product or <tt>null</tt> if none with the given ID exists.
354      */

355     public Product getPackagedProduct(String JavaDoc organisationID, String JavaDoc productID, boolean throwExceptionIfNotExistent)
356     {
357         Product res = (Product)packagedProducts.get(getPrimaryKey(organisationID, productID));
358         if (res == null && throwExceptionIfNotExistent)
359             throw new IllegalArgumentException JavaDoc("No packaged Product existing with organisationID=\""+organisationID+"\", productID=\""+productID+"\"!");
360         return res;
361     }
362     /**
363      * Removes a packaged product from this package.
364      * @param organisationID
365      * @param productID
366      */

367     public void removePackagedProduct(String JavaDoc organisationID, String JavaDoc productID)
368     {
369         packagedProducts.remove(getPrimaryKey(organisationID, productID));
370     }
371     // *** end: packagedProducts ***
372

373     /**
374      * @return Returns the <tt>ProductFactory</tt> that can create instances for this
375      * product type or <tt>null</tt> if none is assigned.
376      *
377      * @see #isProductFactoryAssigned()
378      * @see #setProductFactory(ProductFactory)
379      */

380     public ProductFactory getProductFactory()
381     {
382         return productFactory;
383     }
384     /**
385      * @param productFactory The <tt>ProductFactory</tt> to set. This factory must be able
386      * to create product instances for this product type. If this param is <tt>null</tt>,
387      * the method <tt>isProductFactoryAssigned()</tt> will return <tt>false</tt> afterwards.
388      *
389      * @see #getProductFactory()
390      */

391     public void setProductFactory(ProductFactory productFactory)
392     {
393         this.productFactory = productFactory;
394         this.productFactoryAssigned = productFactory != null;
395     }
396     /**
397      * @return Returns the <tt>true</tt>, if this <tt>Product</tt> has a <tt>ProductFactory</tt>
398      * assigned for automatic creation of product instances. If <tt>Product.productFactory</tt>
399      * is <tt>null</tt>, this method returns <tt>false</tt>.
400      *
401      * @see #getProductFactory()
402      */

403     public boolean isProductFactoryAssigned()
404     {
405         return productFactoryAssigned;
406     }
407
408     // /// *** begin inheritence *** ///
409
private static Set JavaDoc nonInheritableFields = new HashSet JavaDoc();
410
411     /**
412      * @see com.nightlabs.inheritance.Inheritable#getFieldMetaData(java.lang.String)
413      */

414     public com.nightlabs.inheritance.FieldMetaData getFieldMetaData(String JavaDoc fieldName)
415     {
416         if (fieldName.startsWith("jdo"))
417             return null;
418
419         synchronized (nonInheritableFields) {
420             if (nonInheritableFields.isEmpty()) {
421                 nonInheritableFields.add("organisationID");
422                 nonInheritableFields.add("productID");
423                 nonInheritableFields.add("extendedProduct");
424                 nonInheritableFields.add("nature");
425                 nonInheritableFields.add("fieldMetaDataMap");
426 // nonInheritableFields.add("names");
427
nonInheritableFields.add("creationSupported");
428             }
429             if (nonInheritableFields.contains(fieldName))
430                 return null;
431         }
432
433         ProductFieldMetaData fmd = (ProductFieldMetaData)fieldMetaDataMap.get(fieldName);
434         if (fmd == null) {
435             if ("properties".equals(fieldName) || "packagedProducts".equals(fieldName))
436                 fmd = new MapFieldMetaData(this, fieldName);
437             else
438                 fmd = new ProductFieldMetaData(this, fieldName);
439
440             fieldMetaDataMap.put(fieldName, fmd);
441         } // if (fmd == null) {
442

443         return fmd;
444     }
445
446     /**
447      * @see com.nightlabs.inheritance.Inheritable#getFieldInheriter(java.lang.String)
448      */

449     public FieldInheriter getFieldInheriter(String JavaDoc fieldName)
450     {
451         if ("packagedProducts".equals(fieldName)) {
452             return new MapFieldInheriter();
453         }
454
455         return new JDOSimpleFieldInheriter();
456     }
457
458     /**
459      * @see com.nightlabs.inheritance.InheritanceCallbacks#preInherit()
460      */

461     public void preInherit()
462     {
463         // names.size(); // not inheritable
464
// properties.size();
465
packagedProducts.size();
466     }
467
468     /**
469      * @see com.nightlabs.inheritance.InheritanceCallbacks#postInherit()
470      */

471     public void postInherit()
472     {
473     }
474
475     // *** end fieldMetaData ***
476
// /// *** end inheritence *** ///
477

478     /**
479      * @see javax.jdo.StoreCallback#jdoPreStore()
480      */

481     public void jdoPreStore()
482     {
483         if (organisationID != null)
484             return;
485
486         PersistenceManager pm = JDOHelper.getPersistenceManager(this);
487         this.organisationID = LocalOrganisation.getLocalOrganisation(pm).getOrganisationID();
488     }
489
490 }
491
Popular Tags