PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/connector/src/main/java/net/magja/service/category/CategoryRemoteServiceImpl.java

http://github.com/magja/magja
Java | 734 lines | 432 code | 118 blank | 184 comment | 84 complexity | e23fc5090f0c451af5945d5f6e27f387 MD5 | raw file
  1. package net.magja.service.category;
  2. import net.magja.magento.ResourcePath;
  3. import net.magja.model.category.Category;
  4. import net.magja.model.product.Product;
  5. import net.magja.service.GeneralServiceImpl;
  6. import net.magja.service.RemoteServiceFactory;
  7. import net.magja.service.ServiceException;
  8. import com.google.common.base.Function;
  9. import com.google.common.collect.Maps;
  10. import net.magja.soap.SoapClient;
  11. import org.apache.axis2.AxisFault;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import java.util.Map;
  17. /**
  18. * Category service implementation.
  19. * @author andre
  20. * @author Simon Zambrovski
  21. */
  22. public class CategoryRemoteServiceImpl extends GeneralServiceImpl<Category> implements CategoryRemoteService {
  23. private transient Logger log = LoggerFactory.getLogger(CategoryRemoteServiceImpl.class);
  24. private RemoteServiceFactory serviceFactory;
  25. private static final long serialVersionUID = 5806879316902937610L;
  26. public CategoryRemoteServiceImpl(SoapClient soapClient, RemoteServiceFactory serviceFactory) {
  27. super(soapClient);
  28. this.serviceFactory = serviceFactory;
  29. }
  30. /**
  31. * Load children for the category
  32. *
  33. * @param category
  34. * @throws ServiceException
  35. */
  36. private void loadChildren(Category category) throws ServiceException {
  37. if (category.get("children") != null) {
  38. if (category.get("children").toString().length() > 0) {
  39. String str_children = (String) category.get("children");
  40. String[] arr_children = str_children.split(",");
  41. for (String str_child : arr_children) {
  42. Category child = getByIdClean(new Integer(str_child));
  43. if (child != null)
  44. category.addChild(child);
  45. }
  46. }
  47. }
  48. }
  49. /**
  50. * load parent for the category
  51. *
  52. * @param category
  53. * @throws ServiceException
  54. */
  55. private void loadParent(Category category) throws ServiceException {
  56. if (category.get("parent_id") != null) {
  57. Category parent = getByIdClean((Integer) category.get("parent_id"));
  58. category.setParent(parent);
  59. }
  60. }
  61. /*
  62. * (non-Javadoc)
  63. *
  64. * @see
  65. * net.magja.magja.service.category.CategoryRemoteService#getByIdClean
  66. * (java.lang.Integer)
  67. */
  68. @Override
  69. public Category getByIdClean(Integer id) throws ServiceException {
  70. log.info("getIdByClean {}", id);
  71. Category category = new Category();
  72. if (id == null) {
  73. return null;
  74. }
  75. Map<String, Object> cat;
  76. try {
  77. cat = (Map<String, Object>) soapClient.callSingle(ResourcePath.CategoryInfo, id);
  78. } catch (AxisFault e) {
  79. if (debug)
  80. e.printStackTrace();
  81. throw new ServiceException(e.getMessage());
  82. }
  83. if (cat == null) {
  84. return null;
  85. }
  86. log.debug("Mappping to Category #{} from {}", id, cat);
  87. for (Map.Entry<String, Object> attribute : cat.entrySet()) {
  88. if (attribute.getKey().equals("available_sort_by")) {
  89. // category.set(attribute.getKey(), attribute.getValue());
  90. category.set(attribute.getKey(), (String) attribute.getValue());
  91. } else {
  92. category.set(attribute.getKey(), attribute.getValue());
  93. }
  94. }
  95. return category;
  96. }
  97. /*
  98. * (non-Javadoc)
  99. *
  100. * @see net.magja.magja.service.category.CategoryRemoteService#
  101. * getByIdWithChildren(java.lang.Integer)
  102. */
  103. @Override
  104. public Category getByIdWithChildren(Integer id) throws ServiceException {
  105. Category category = getByIdClean(id);
  106. // load category children
  107. loadChildren(category);
  108. return category;
  109. }
  110. /*
  111. * (non-Javadoc)
  112. *
  113. * @see net.magja.magja.service.category.CategoryRemoteService#
  114. * getByIdWithParent(java.lang.Integer)
  115. */
  116. @Override
  117. public Category getByIdWithParent(Integer id) throws ServiceException {
  118. Category category = getByIdClean(id);
  119. // load category parent
  120. loadParent(category);
  121. return category;
  122. }
  123. @Override
  124. public Category getByIdWithParentAndChildren(Integer id) throws ServiceException {
  125. Category category = getByIdClean(id);
  126. // load category parent and children
  127. loadChildren(category);
  128. loadParent(category);
  129. return category;
  130. }
  131. @SuppressWarnings("unchecked")
  132. public Category getTree(Integer id) throws ServiceException {
  133. Category category = new Category();
  134. if (id == null) {
  135. return null;
  136. }
  137. Map<String, Object> cat;
  138. try {
  139. cat = (Map<String, Object>) soapClient.callSingle(ResourcePath.CategoryTree, id);
  140. } catch (AxisFault e) {
  141. log.error("Error calling CategoryRemoteServiceImpl.getTree()", e);
  142. if (debug)
  143. e.printStackTrace();
  144. throw new ServiceException("Error calling CategoryRemoteServiceImpl.getTree()", e);
  145. }
  146. if (cat == null)
  147. return null;
  148. category = getCategoryFromMap(cat);
  149. return category;
  150. }
  151. /**
  152. * build category from Map
  153. *
  154. * @param cat
  155. */
  156. @SuppressWarnings("unchecked")
  157. private Category getCategoryFromMap(Map<String, Object> cat) {
  158. Category category = new Category();
  159. for (Map.Entry<String, Object> attribute : cat.entrySet()) {
  160. if (attribute.getKey().equals("children")) {
  161. List<Category> children = new ArrayList<Category>();
  162. List<Map<String, Object>> childrenList = (List<Map<String, Object>>) attribute.getValue();
  163. for (Map<String, Object> child : childrenList) {
  164. Category c = getCategoryFromMap(child);
  165. children.add(c);
  166. }
  167. category.setChildren(children);
  168. } else {
  169. category.set(attribute.getKey(), attribute.getValue());
  170. }
  171. }
  172. return category;
  173. }
  174. /**
  175. * print all categories
  176. *
  177. * @param category
  178. */
  179. public void print(Category category) {
  180. if (category != null) {
  181. String s = "";
  182. for (int i = 1; i < category.getLevel(); i++) {
  183. s += " ";
  184. }
  185. log.debug(s + category.getName());
  186. for (Category child : category.getChildren()) {
  187. print(child);
  188. }
  189. }
  190. }
  191. /**
  192. * search categories
  193. *
  194. * @param category
  195. */
  196. public List<Category> search(Category category, List<String> categoryNames) throws ServiceException {
  197. List<Category> categories = new ArrayList<Category>();
  198. for (String name : categoryNames) {
  199. boolean found = false;
  200. for (Category child : category.getChildren()) {
  201. if (child.getName().equals(name)) {
  202. found = true;
  203. categories.add(child);
  204. // override parent with child
  205. category = child;
  206. break;
  207. }
  208. }
  209. if (!found) {
  210. throw new ServiceException("Category \"" + name + "\" not found.");
  211. }
  212. }
  213. return categories;
  214. }
  215. /**
  216. * search for equal child
  217. */
  218. public Category searchChild(Category category, Category search) throws ServiceException {
  219. if (category != null) {
  220. for (Category child : category.getChildren()) {
  221. if (child.getName().equals(search.getName())) {
  222. return child;
  223. }
  224. }
  225. }
  226. throw new ServiceException("Child not found");
  227. }
  228. /*
  229. * (non-Javadoc)
  230. *
  231. * @see
  232. * net.magja.magja.service.category.CategoryRemoteService#create(code
  233. * .google .magja.model.product.Category)
  234. */
  235. @SuppressWarnings("unchecked")
  236. @Override
  237. public int save(Category category) throws ServiceException {
  238. return save(category, "");
  239. }
  240. public int save(Category category, String storeView) throws ServiceException {
  241. if (category.getId() == null) {
  242. // List<Object> newCategory = new LinkedList<Object>();
  243. // newCategory.add(category.getParent().getId());
  244. // newCategory.add(category.getAllProperties());
  245. // means its a new category
  246. try {
  247. Integer id = Integer
  248. .parseInt((String) soapClient.callArgs(ResourcePath.CategoryCreate, new Object[] { category.getParent().getId(), category.getAllProperties() }));
  249. if (id > -1) {
  250. category.setId(id);
  251. return id;
  252. } else {
  253. throw new ServiceException("Error inserting new Category");
  254. }
  255. } catch (NumberFormatException e) {
  256. if (debug)
  257. e.printStackTrace();
  258. throw new ServiceException(e.getMessage());
  259. } catch (AxisFault e) {
  260. if (debug)
  261. e.printStackTrace();
  262. if (e.getMessage().indexOf("available_sort_by") > 0) {
  263. log.debug("Broken Magento API? Run this SQL code first\n" + "update eav_attribute set is_required = 0 where attribute_code = 'available_sort_by';");
  264. }
  265. throw new ServiceException(e.getMessage());
  266. }
  267. } else {
  268. // update existing category
  269. // List<Object> newCategory = new LinkedList<Object>();
  270. // newCategory.add(category.getId());
  271. // newCategory.add(category.getAllProperties());
  272. if (!storeView.isEmpty()) {
  273. // newCategory.add(storeView);
  274. }
  275. try {
  276. Boolean sucessed = (Boolean) soapClient.callArgs(ResourcePath.CategoryUpdate,
  277. new Object[] { category.getId(), category.getAllProperties(), !storeView.isEmpty() ? storeView : null });
  278. if (!sucessed) {
  279. throw new ServiceException("Error on update Category");
  280. }
  281. } catch (AxisFault e) {
  282. if (debug)
  283. e.printStackTrace();
  284. throw new ServiceException(e.getMessage());
  285. }
  286. return category.getId();
  287. }
  288. }
  289. /**
  290. * Delete a category by id
  291. *
  292. * @param id
  293. * @throws ServiceException
  294. */
  295. public void delete(Integer id) throws ServiceException {
  296. Boolean success = false;
  297. try {
  298. success = soapClient.callSingle(ResourcePath.CategoryDelete, id);
  299. } catch (AxisFault e) {
  300. log.debug(e.getMessage());
  301. throw new ServiceException(e.getMessage());
  302. }
  303. if (!success) {
  304. throw new ServiceException("Not success deleting category.");
  305. }
  306. }
  307. /**
  308. * Delete a delete all children in a category
  309. *
  310. * @param parent
  311. * category id
  312. * @throws ServiceException
  313. */
  314. public void deleteAllChildren(Integer id) throws ServiceException {
  315. Category parent = getByIdWithChildren(id);
  316. List<Category> children = parent.getChildren();
  317. for (Category category : children) {
  318. delete(category.getId());
  319. }
  320. }
  321. /**
  322. * get default root category
  323. *
  324. * @param id
  325. * @throws ServiceException
  326. */
  327. public Category getDefaultParent() throws ServiceException {
  328. return getByIdClean(soapClient.getConfig().getDefaultRootCategoryId());
  329. }
  330. /**
  331. * create category from minimal parameter
  332. * <p/>
  333. * Settings: availableSortBy = name defaultSortBy = name active = true anchor
  334. * = true
  335. */
  336. public Category getMinimalCategory(Integer parentId, String categoryName) {
  337. return getRequiredCategory(parentId, categoryName, "name", "name", true, true);
  338. }
  339. /**
  340. * create category with required parameter (this parameter are required by
  341. * Magento)
  342. */
  343. public Category getRequiredCategory(Integer parentId, String categoryName, String availableSortBy, String defaultSortBy, Boolean active, Boolean anchor) {
  344. Category parent = new Category(parentId);
  345. Category category = new Category(categoryName);
  346. category.setParent(parent);
  347. category.setAvailableSortBy(availableSortBy);
  348. category.setDefaultSortBy(defaultSortBy);
  349. category.setActive(active);
  350. category.setAnchor(anchor);
  351. return category;
  352. }
  353. /**
  354. * create category tree from String
  355. */
  356. public Category create(Integer parentId, String categoryName) throws ServiceException {
  357. List<String> categoryNames = new ArrayList<String>();
  358. categoryNames.add(categoryName);
  359. List<Category> categories = create(parentId, categoryNames);
  360. return categories.get(0);
  361. }
  362. /**
  363. * create category from category list
  364. */
  365. public Category linkCategory(List<Category> categories) throws ServiceException {
  366. if (categories.size() > 0) {
  367. for (int i = 0; i < categories.size(); i++) {
  368. // set parent
  369. if (i > 0) {
  370. Category parent = categories.get(i - 1);
  371. categories.get(i).setParent(parent);
  372. }
  373. // set children
  374. if (i < categories.size() - 1) {
  375. List<Category> children = new ArrayList<Category>();
  376. children.add(categories.get(i + 1));
  377. categories.get(i).setChildren(children);
  378. }
  379. }
  380. return categories.get(0);
  381. }
  382. throw new ServiceException("Category list is empty");
  383. }
  384. /**
  385. * create category tree from String array
  386. */
  387. public List<Category> create(Integer parentId, List<String> categoryNames) throws ServiceException {
  388. List<Category> categories = new ArrayList<Category>();
  389. for (String categoryName : categoryNames) {
  390. categories.add(getMinimalCategory(0, categoryName));
  391. }
  392. return create(parentId, linkCategory(categories));
  393. }
  394. /**
  395. * create category if not exists already
  396. */
  397. public List<Category> create(Integer parentId, Category category) throws ServiceException {
  398. if (parentId > 0 && category != null) {
  399. List<Category> categories = new ArrayList<Category>();
  400. Category parent = getTree(parentId);
  401. while (category != null) {
  402. try {
  403. // search for category
  404. Category child = searchChild(parent, category);
  405. // category exists already, set id from existing one
  406. category.setId(child.getId());
  407. // set values for next loop
  408. parent = child;
  409. parentId = parent.getId();
  410. } catch (Exception e) {
  411. parent = null;
  412. }
  413. // create / update category
  414. category.setParent(new Category(parentId));
  415. parentId = save(category);
  416. // add category to return list
  417. categories.add(category);
  418. // set values for next loop
  419. if (category.getChildren().size() > 0) {
  420. // set values for next loop
  421. // FIXME: set more then one child
  422. category = category.getChildren().get(0);
  423. } else {
  424. return categories;
  425. }
  426. }
  427. }
  428. throw new ServiceException("Fail to create a new category");
  429. }
  430. /**
  431. * Assign product to category
  432. */
  433. public void assignProduct(Category category, Product product) throws ServiceException {
  434. // List<Object> list = new LinkedList<Object>();
  435. // list.add(category.getId());
  436. // list.add(product.getId());
  437. Boolean success = false;
  438. try {
  439. success = (Boolean) soapClient.callArgs(ResourcePath.CategoryAssignProduct, new Object[] { category.getId(), product.getId() });
  440. } catch (AxisFault e) {
  441. log.debug(e.getMessage());
  442. throw new ServiceException(e.getMessage());
  443. }
  444. if (!success) {
  445. throw new ServiceException("Not success assign product to category.");
  446. }
  447. }
  448. /**
  449. * Assign product to category
  450. */
  451. @Override
  452. public void removeProduct(Category category, Product product) throws ServiceException {
  453. // List<Object> list = new LinkedList<Object>();
  454. // list.add(category.getId());
  455. // list.add(product.getId());
  456. Boolean success = false;
  457. try {
  458. success = (Boolean) soapClient.callArgs(ResourcePath.CategoryRemoveProduct, new Object[] { category.getId(), product.getId() });
  459. } catch (AxisFault e) {
  460. log.debug(e.getMessage());
  461. throw new ServiceException(e.getMessage());
  462. }
  463. if (!success) {
  464. throw new ServiceException("No success assign product to category.");
  465. }
  466. }
  467. /**
  468. * Assign product to category
  469. */
  470. @Override
  471. public void assignProductWithPosition(Category category, Product product, Integer position) throws ServiceException {
  472. // List<Object> list = new LinkedList<Object>();
  473. // list.add(category.getId());
  474. // list.add(product.getId());
  475. // list.add(position);
  476. Boolean success = false;
  477. try {
  478. success = (Boolean) soapClient.callArgs(ResourcePath.CategoryAssignProduct, new Object[] { category.getId(), product.getId(), position });
  479. } catch (AxisFault e) {
  480. throw new ServiceException(e.getMessage());
  481. }
  482. if (!success) {
  483. throw new ServiceException("No success assign product to category.");
  484. }
  485. }
  486. /**
  487. * Get list of assigned products in default store
  488. */
  489. public List<Product> getProducts(Category category) throws ServiceException {
  490. return getProducts(category, 1, false);
  491. }
  492. /**
  493. * Get list of assigned products If dependencies are disabled, the Product
  494. * will contain only following attributes: product_id, type, set, sku. All
  495. * other attributes will be null.
  496. */
  497. public List<Product> getProducts(Category category, Integer storeID, boolean dependencies) throws ServiceException {
  498. if (category == null)
  499. return null;
  500. // List<Object> list = new LinkedList<Object>();
  501. // list.add(category.getId());
  502. // list.add(storeID);
  503. List<Product> products = new ArrayList<Product>();
  504. List<Map<String, Object>> productList;
  505. try {
  506. productList = soapClient.callArgs(ResourcePath.CategoryAssignedProducts, new Object[] { category.getId(), storeID });
  507. } catch (AxisFault e) {
  508. if (debug)
  509. e.printStackTrace();
  510. throw new ServiceException(e.getMessage());
  511. }
  512. if (productList == null)
  513. return products;
  514. for (Map<String, Object> mpp : productList) {
  515. Product product = new Product();
  516. if (dependencies) {
  517. // buid a full product object if required
  518. product = serviceFactory.getProductRemoteService().getBySku(mpp.get("sku").toString(), true);
  519. } else {
  520. // get minimal product object
  521. product = serviceFactory.getProductRemoteService().getBySku(mpp.get("sku").toString(), false);
  522. }
  523. products.add(product);
  524. }
  525. return products;
  526. }
  527. /**
  528. * get list of last categories in a category tree
  529. */
  530. public List<Category> getLastCategories(Category categoryTree) {
  531. List<Category> categoryList = new ArrayList<Category>();
  532. for (Category child : categoryTree.getChildren()) {
  533. if (child.getChildren().isEmpty()) {
  534. categoryList.add(child);
  535. } else {
  536. List<Category> categorys = getLastCategories(child);
  537. for (Category c : categorys) {
  538. categoryList.add(c);
  539. }
  540. }
  541. }
  542. return categoryList;
  543. }
  544. /**
  545. * get list of last categories without products
  546. */
  547. public List<Category> findEmpty(Integer id) throws ServiceException {
  548. Category startCategory = getTree(id);
  549. List<Category> lastCategories = getLastCategories(startCategory);
  550. List<Category> emptyCategories = new ArrayList<Category>();
  551. for (Category category : lastCategories) {
  552. if (getProducts(category).isEmpty()) {
  553. emptyCategories.add(category);
  554. }
  555. }
  556. return emptyCategories;
  557. }
  558. /**
  559. * delete last categories without products
  560. */
  561. public Integer deleteEmpty(Integer id) throws ServiceException {
  562. List<Category> emptyCategories = findEmpty(id);
  563. for (Category category : emptyCategories) {
  564. delete(category.getId());
  565. }
  566. // FIXME: delete empty parent
  567. return emptyCategories.size();
  568. }
  569. /**
  570. * delete delete recursive if empty
  571. */
  572. public void deleteEmptyRecursive(Category category) throws ServiceException {
  573. if (isEmpty(category)) {
  574. // get parent category
  575. Category parent = getByIdWithParent(category.getId()).getParent();
  576. // delete current empty category
  577. delete(category.getId());
  578. // delete parent category if empty
  579. deleteEmptyRecursive(parent);
  580. }
  581. }
  582. /**
  583. * Check if category is empty
  584. *
  585. * @param cagegory
  586. * @throws ServiceException
  587. */
  588. public Boolean isEmpty(Category category) throws ServiceException {
  589. if (category.getChildren().isEmpty() && getProducts(category).isEmpty()) {
  590. return true;
  591. } else {
  592. return false;
  593. }
  594. }
  595. /**
  596. * Return map of categories where the key is category URL path (e.g.
  597. * "accessories/bb-pouch") and the value is a map of [id, name].
  598. */
  599. @Override
  600. public Map<String, Category> listPaths() throws ServiceException {
  601. try {
  602. Map<String, Map<String, Object>> soapResult = (Map<String, Map<String, Object>>) soapClient.callSingle(ResourcePath.CategoryListPaths, "");
  603. log.debug("{} returned {} categories", ResourcePath.CategoryListPaths, soapResult.size());
  604. Map<String, Category> result = Maps.transformValues(soapResult, new Function<Map<String, Object>, Category>() {
  605. @Override
  606. public Category apply(Map<String, Object> input) {
  607. return new Category(Integer.valueOf((String) input.get("id")), (String) input.get("name"));
  608. }
  609. });
  610. return result;
  611. } catch (AxisFault e) {
  612. log.error("CategoryListPaths error", e);
  613. throw new ServiceException("CategoryListPaths error", e);
  614. }
  615. }
  616. }