KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > product > feature > ProductFeatureServices


1 /*
2  * $Id: ProductFeatureServices.java 5867 2005-09-30 16:34:06Z sichen $
3  *
4  * Copyright (c) 2004 The Open For Business Project (www.ofbiz.org)
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
20  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */

23 package org.ofbiz.product.feature;
24
25 import java.util.ArrayList JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.LinkedHashMap JavaDoc;
29 import java.util.LinkedList JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import org.ofbiz.base.util.Debug;
34 import org.ofbiz.base.util.UtilMisc;
35 import org.ofbiz.entity.GenericDelegator;
36 import org.ofbiz.entity.GenericEntity;
37 import org.ofbiz.entity.GenericEntityException;
38 import org.ofbiz.entity.GenericValue;
39 import org.ofbiz.entity.util.EntityUtil;
40 import org.ofbiz.service.DispatchContext;
41 import org.ofbiz.service.GenericServiceException;
42 import org.ofbiz.service.LocalDispatcher;
43 import org.ofbiz.service.ModelService;
44 import org.ofbiz.service.ServiceUtil;
45
46
47 /**
48  * Services for product features
49  *
50  * @author <a HREF="mailto:schen@graciousstyle.com">Si Chen</a>
51  * @version $Revision: 5867 $
52  * @since 3.0
53  */

54
55 public class ProductFeatureServices {
56
57     public static final String JavaDoc module = ProductFeatureServices.class.getName();
58     public static final String JavaDoc resource = "ProductUiLabels";
59     
60     /*
61      * Parameters: productFeatureCategoryId, productFeatureGroupId, productId, productFeatureApplTypeId
62      * Result: productFeaturesByType, a Map of all product features from productFeatureCategoryId, group by productFeatureType -> List of productFeatures
63      * If the parameter were productFeatureCategoryId, the results are from ProductFeatures. If productFeatureCategoryId were null and there were a productFeatureGroupId,
64      * the results are from ProductFeatureGroupAndAppl. Otherwise, if there is a productId, the results are from ProductFeatureAndAppl.
65      * The optional productFeatureApplTypeId causes results to be filtered by this parameter--only used in conjunction with productId.
66      */

67     public static Map JavaDoc getProductFeaturesByType(DispatchContext dctx, Map JavaDoc context) {
68         Map JavaDoc results = new HashMap JavaDoc();
69         GenericDelegator delegator = dctx.getDelegator();
70
71         /* because we might need to search either for product features or for product features of a product, the search code has to be generic.
72          * we will determine which entity and field to search on based on what the user has supplied us with.
73          */

74         String JavaDoc valueToSearch = (String JavaDoc) context.get("productFeatureCategoryId");
75         String JavaDoc productFeatureApplTypeId = (String JavaDoc) context.get("productFeatureApplTypeId");
76         
77         String JavaDoc entityToSearch = "ProductFeature";
78         String JavaDoc fieldToSearch = "productFeatureCategoryId";
79         List JavaDoc orderBy = UtilMisc.toList("productFeatureTypeId", "description");
80         
81         if (valueToSearch == null && context.get("productFeatureGroupId") != null) {
82             entityToSearch = "ProductFeatureGroupAndAppl";
83             fieldToSearch = "productFeatureGroupId";
84             valueToSearch = (String JavaDoc) context.get("productFeatureGroupId");
85             // use same orderBy as with a productFeatureCategoryId search
86
} else if (valueToSearch == null && context.get("productId") != null){
87             entityToSearch = "ProductFeatureAndAppl";
88             fieldToSearch = "productId";
89             valueToSearch = (String JavaDoc) context.get("productId");
90             orderBy = UtilMisc.toList("sequenceNum", "productFeatureApplTypeId", "productFeatureTypeId", "description");
91         }
92         
93         if (valueToSearch == null) {
94             return ServiceUtil.returnError("This service requires a productId, a productFeatureGroupId, or a productFeatureCategoryId to run.");
95         }
96         
97         try {
98             // get all product features in this feature category
99
List JavaDoc allFeatures = delegator.findByAnd(entityToSearch, UtilMisc.toMap(fieldToSearch, valueToSearch), orderBy);
100         
101             if (entityToSearch.equals("ProductFeatureAndAppl") && productFeatureApplTypeId != null)
102                 allFeatures = EntityUtil.filterByAnd(allFeatures, UtilMisc.toMap("productFeatureApplTypeId", productFeatureApplTypeId));
103                 
104             List JavaDoc featureTypes = new ArrayList JavaDoc(); // or LinkedList?
105
Map JavaDoc featuresByType = new LinkedHashMap JavaDoc();
106             GenericValue feature = null;
107             for (Iterator JavaDoc featuresIter = allFeatures.iterator(); featuresIter.hasNext(); ) {
108                 feature = (GenericValue) featuresIter.next();
109                 String JavaDoc featureType = feature.getString("productFeatureTypeId");
110                 if (!featureTypes.contains(featureType)) {
111                     featureTypes.add(featureType);
112                 }
113                 if (!featuresByType.containsKey(featureType)) {
114                     featuresByType.put(featureType, new ArrayList JavaDoc());
115                 }
116                 List JavaDoc features = (List JavaDoc)featuresByType.get(featureType);
117                 features.add(feature);
118             }
119
120             results = ServiceUtil.returnSuccess();
121             results.put("productFeatureTypes", featureTypes);
122             results.put("productFeaturesByType", featuresByType);
123         } catch (GenericEntityException ex) {
124             Debug.logError(ex, ex.getMessage(), module);
125             return ServiceUtil.returnError(ex.getMessage());
126         }
127         return results;
128     }
129     
130     /*
131      * Parameter: productId, productFeatureAppls (a List of ProductFeatureAndAppl entities of features applied to productId)
132      * Result: variantProductIds: a List of productIds of variants with those features
133      */

134     public static Map JavaDoc getAllExistingVariants(DispatchContext dctx, Map JavaDoc context) {
135         Map JavaDoc results = new HashMap JavaDoc();
136         Map JavaDoc featuresByType = new HashMap JavaDoc();
137         GenericDelegator delegator = dctx.getDelegator();
138
139         String JavaDoc productId = (String JavaDoc) context.get("productId");
140         List JavaDoc curProductFeatureAndAppls = (List JavaDoc) context.get("productFeatureAppls");
141         List JavaDoc existingVariantProductIds = new ArrayList JavaDoc();
142         
143         try {
144             /*
145              * get a list of all products which are associated with the current one as PRODUCT_VARIANT and for each one,
146              * see if it has every single feature in the list of productFeatureAppls as a STANDARD_FEATURE. If so, then
147              * it qualifies and add it to the list of existingVariantProductIds.
148              */

149             List JavaDoc productAssocs = EntityUtil.filterByDate(delegator.findByAnd("ProductAssoc", UtilMisc.toMap("productId", productId, "productAssocTypeId", "PRODUCT_VARIANT")), true);
150             if (productAssocs != null && productAssocs.size() > 0) {
151                 Iterator JavaDoc productAssocIter = productAssocs.iterator();
152                 while (productAssocIter.hasNext()) {
153                     GenericEntity productAssoc = (GenericEntity) productAssocIter.next();
154                     
155                     //for each associated product, if it has all standard features, display it's productId
156
boolean hasAllFeatures = true;
157                     Iterator JavaDoc curProductFeatureAndApplIter = curProductFeatureAndAppls.iterator();
158                     while (curProductFeatureAndApplIter.hasNext()) {
159                         String JavaDoc productFeatureAndAppl = (String JavaDoc) curProductFeatureAndApplIter.next();
160                         Map JavaDoc findByMap = UtilMisc.toMap("productId", productAssoc.getString("productIdTo"),
161                                 "productFeatureId", productFeatureAndAppl,
162                                 "productFeatureApplTypeId", "STANDARD_FEATURE");
163
164                         //Debug.log("Using findByMap: " + findByMap);
165

166                         List JavaDoc standardProductFeatureAndAppls = EntityUtil.filterByDate(delegator.findByAnd("ProductFeatureAppl", findByMap), true);
167                         if (standardProductFeatureAndAppls == null || standardProductFeatureAndAppls.size() == 0) {
168                             // Debug.log("Does NOT have this standard feature");
169
hasAllFeatures = false;
170                             break;
171                         } else {
172                             // Debug.log("DOES have this standard feature");
173
}
174                     }
175
176                     if (hasAllFeatures) {
177                         // add to list of existing variants: productId=productAssoc.productIdTo
178
existingVariantProductIds.add(productAssoc.get("productIdTo"));
179                     }
180                 }
181             }
182             results = ServiceUtil.returnSuccess();
183             results.put("variantProductIds", existingVariantProductIds);
184         } catch (GenericEntityException ex) {
185             Debug.logError(ex, ex.getMessage(), module);
186             return ServiceUtil.returnError(ex.getMessage());
187         }
188     return results;
189     }
190
191     /*
192      * Parameter: productId (of the parent product which has SELECTABLE features)
193      * Result: featureCombinations, a List of Maps containing, for each possible variant of the productid:
194      * {defaultVariantProductId: id of this variant; curProductFeatureAndAppls: features applied to this variant; existingVariantProductIds: List of productIds which are already variants with these features }
195      */

196     public static Map JavaDoc getVariantCombinations(DispatchContext dctx, Map JavaDoc context) {
197         Map JavaDoc results = new HashMap JavaDoc();
198         Map JavaDoc featuresByType = new HashMap JavaDoc();
199         GenericDelegator delegator = dctx.getDelegator();
200         LocalDispatcher dispatcher = dctx.getDispatcher();
201         
202         String JavaDoc productId = (String JavaDoc) context.get("productId");
203         
204         try {
205             Map JavaDoc featuresResults = dispatcher.runSync("getProductFeaturesByType", UtilMisc.toMap("productId", productId));
206             Map JavaDoc features = new HashMap JavaDoc();
207             
208             if (featuresResults.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_SUCCESS))
209                 features = (Map JavaDoc) featuresResults.get("productFeaturesByType");
210             else
211                 return ServiceUtil.returnError((String JavaDoc) featuresResults.get(ModelService.ERROR_MESSAGE_LIST));
212
213             // need to keep 2 lists, oldCombinations and newCombinations, and keep swapping them after each looping. Otherwise, you'll get a
214
// concurrent modification exception
215
List JavaDoc oldCombinations = new LinkedList JavaDoc();
216
217             // loop through each feature type
218
for (Iterator JavaDoc fi = features.keySet().iterator(); fi.hasNext(); ) {
219                 String JavaDoc currentFeatureType = (String JavaDoc) fi.next();
220                 List JavaDoc currentFeatures = (List JavaDoc) features.get(currentFeatureType);
221
222                 List JavaDoc newCombinations = new LinkedList JavaDoc();
223                 List JavaDoc combinations;
224
225                 // start with either existing combinations or from scratch
226
if (oldCombinations.size() > 0)
227                     combinations = oldCombinations;
228                 else
229                     combinations = new LinkedList JavaDoc();
230
231                 // in both cases, use each feature of current feature type's idCode and
232
// product feature and add it to the id code and product feature applications
233
// of the next variant. just a matter of whether we're starting with an
234
// existing list of features and id code or from scratch.
235
if (combinations.size()==0) {
236                    for (Iterator JavaDoc cFi = currentFeatures.iterator(); cFi.hasNext(); ) {
237                            GenericEntity currentFeature = (GenericEntity) cFi.next();
238                            if (currentFeature.getString("productFeatureApplTypeId").equals("SELECTABLE_FEATURE")) {
239                                Map JavaDoc newCombination = new HashMap JavaDoc();
240                                List JavaDoc newFeatures = new LinkedList JavaDoc();
241                                List JavaDoc newFeatureIds = new LinkedList JavaDoc();
242                                if (currentFeature.getString("idCode") != null)
243                                 newCombination.put("defaultVariantProductId", productId + currentFeature.getString("idCode"));
244                             else
245                                 newCombination.put("defaultVariantProductId", productId);
246                             newFeatures.add(currentFeature);
247                             newFeatureIds.add(currentFeature.getString("productFeatureId"));
248                             newCombination.put("curProductFeatureAndAppls", newFeatures);
249                             newCombination.put("curProductFeatureIds", newFeatureIds);
250                             newCombinations.add(newCombination);
251                        }
252                    }
253                 } else {
254                   for (Iterator JavaDoc comboIt = combinations.iterator(); comboIt.hasNext(); ) {
255                           Map JavaDoc combination = (Map JavaDoc) comboIt.next();
256                           for (Iterator JavaDoc cFi = currentFeatures.iterator(); cFi.hasNext(); ) {
257                               GenericEntity currentFeature = (GenericEntity) cFi.next();
258                                                         String JavaDoc defaultVariantProductId = null;
259                               if (currentFeature.getString("productFeatureApplTypeId").equals("SELECTABLE_FEATURE")) {
260                                   Map JavaDoc newCombination = new HashMap JavaDoc();
261                                   // .clone() is important, or you'll keep adding to the same List for all the variants
262
// have to cast twice: once from get() and once from clone()
263
List JavaDoc newFeatures = ((List JavaDoc) ((LinkedList JavaDoc) combination.get("curProductFeatureAndAppls")).clone());
264                                   List JavaDoc newFeatureIds = ((List JavaDoc) ((LinkedList JavaDoc) combination.get("curProductFeatureIds")).clone());
265                                   if (currentFeature.getString("idCode") != null)
266                                           newCombination.put("defaultVariantProductId", combination.get("defaultVariantProductId") + currentFeature.getString("idCode"));
267                                   else
268                                           newCombination.put("defaultVariantProductId", combination.get("defaultVariantProductId"));
269                                   newFeatures.add(currentFeature);
270                                   newFeatureIds.add(currentFeature.getString("productFeatureId"));
271                                   newCombination.put("curProductFeatureAndAppls", newFeatures);
272                                   newCombination.put("curProductFeatureIds", newFeatureIds);
273                                   newCombinations.add(newCombination);
274                               }
275                           }
276                       }
277                 }
278                 if (newCombinations.size() >= oldCombinations.size())
279                     oldCombinations = newCombinations; // save the newly expanded list as oldCombinations
280
}
281
282                         int defaultCodeCounter = 1;
283                         HashMap JavaDoc defaultVariantProductIds = new HashMap JavaDoc(); // this map will contain the codes already used (as keys)
284
defaultVariantProductIds.put(productId, null);
285                         
286             // now figure out which of these combinations already have productIds associated with them
287
for (Iterator JavaDoc fCi = oldCombinations.iterator(); fCi.hasNext(); ) {
288                 Map JavaDoc combination = (Map JavaDoc) fCi.next();
289                             // Verify if the default code is already used, if so add a numeric suffix
290
if (defaultVariantProductIds.containsKey(combination.get("defaultVariantProductId"))) {
291                                 combination.put("defaultVariantProductId", combination.get("defaultVariantProductId") + (defaultCodeCounter < 10? "0" + defaultCodeCounter: "" + defaultCodeCounter));
292                                 defaultCodeCounter++;
293                             }
294                             defaultVariantProductIds.put(combination.get("defaultVariantProductId"), null);
295                 results = dispatcher.runSync("getAllExistingVariants", UtilMisc.toMap("productId", productId,
296                                             "productFeatureAppls", combination.get("curProductFeatureIds")));
297                 combination.put("existingVariantProductIds", results.get("variantProductIds"));
298             }
299             results = ServiceUtil.returnSuccess();
300             results.put("featureCombinations", oldCombinations);
301         } catch (GenericServiceException ex) {
302             Debug.logError(ex, ex.getMessage(), module);
303             return ServiceUtil.returnError(ex.getMessage());
304         }
305         
306         return results;
307     }
308
309     /*
310      * Parameters: productCategoryId (String) and productFeatures (a List of ProductFeature GenericValues)
311      * Result: products (a List of Product GenericValues)
312      */

313     public static Map JavaDoc getCategoryVariantProducts(DispatchContext dctx, Map JavaDoc context) {
314         Map JavaDoc results = new HashMap JavaDoc();
315         GenericDelegator delegator = dctx.getDelegator();
316         LocalDispatcher dispatcher = dctx.getDispatcher();
317
318         List JavaDoc productFeatures = (List JavaDoc) context.get("productFeatures");
319         String JavaDoc productCategoryId = (String JavaDoc) context.get("productCategoryId");
320
321         // get all the product members of the product category
322
Map JavaDoc result = new HashMap JavaDoc();
323         try {
324             result = dispatcher.runSync("getProductCategoryMembers", UtilMisc.toMap("categoryId", productCategoryId));
325         } catch (GenericServiceException ex) {
326             Debug.logError("Cannot get category memebers for " + productCategoryId + " due to error: " + ex.getMessage(), module);
327             return ServiceUtil.returnError(ex.getMessage());
328         }
329
330         List JavaDoc memberProducts = (List JavaDoc) result.get("categoryMembers");
331         if ((memberProducts != null) && (memberProducts.size() > 0)) {
332             // construct a Map of productFeatureTypeId -> productFeatureId from the productFeatures List
333
Map JavaDoc featuresByType = new HashMap JavaDoc();
334             for (Iterator JavaDoc pFi = productFeatures.iterator(); pFi.hasNext(); ) {
335                 GenericValue nextFeature = (GenericValue) pFi.next();
336                 featuresByType.put(nextFeature.getString("productFeatureTypeId"), nextFeature.getString("productFeatureId"));
337             }
338
339             List JavaDoc products = new ArrayList JavaDoc(); // final list of variant products
340
for (Iterator JavaDoc mPi = memberProducts.iterator(); mPi.hasNext(); ) {
341                 // find variants for each member product of the category
342
GenericValue memberProduct = (GenericValue) mPi.next();
343
344                 try {
345                     result = dispatcher.runSync("getProductVariant", UtilMisc.toMap("productId", memberProduct.getString("productId"), "selectedFeatures", featuresByType));
346                 } catch (GenericServiceException ex) {
347                     Debug.logError("Cannot get product variants for " + memberProduct.getString("productId") + " due to error: " + ex.getMessage(), module);
348                     return ServiceUtil.returnError(ex.getMessage());
349                 }
350
351                 List JavaDoc variantProducts = (List JavaDoc) result.get("products");
352                 if ((variantProducts != null) && (variantProducts.size() > 0)) {
353                     products.addAll(variantProducts);
354                 } else {
355                     Debug.logWarning("Product " + memberProduct.getString("productId") + " did not have any variants for the given features", module);
356                 }
357             }
358
359             if (products.size() == 0) {
360                 return ServiceUtil.returnError("No products which fit your requirements were found.");
361             } else {
362                 results = ServiceUtil.returnSuccess();
363                 results.put("products", products);
364             }
365
366         } else {
367             Debug.logWarning("No products found in " + productCategoryId, module);
368         }
369
370         return results;
371     }
372 }
373
Popular Tags