Package org.broadleafcommerce.core.web.api.endpoint.catalog

Source Code of org.broadleafcommerce.core.web.api.endpoint.catalog.CatalogEndpoint

/*
* #%L
* BroadleafCommerce Framework Web
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.broadleafcommerce.core.web.api.endpoint.catalog;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.common.file.service.StaticAssetPathService;
import org.broadleafcommerce.common.media.domain.Media;
import org.broadleafcommerce.common.security.service.ExploitProtectionService;
import org.broadleafcommerce.core.catalog.domain.Category;
import org.broadleafcommerce.core.catalog.domain.CategoryAttribute;
import org.broadleafcommerce.core.catalog.domain.CategoryProductXref;
import org.broadleafcommerce.core.catalog.domain.Product;
import org.broadleafcommerce.core.catalog.domain.ProductAttribute;
import org.broadleafcommerce.core.catalog.domain.RelatedProduct;
import org.broadleafcommerce.core.catalog.domain.Sku;
import org.broadleafcommerce.core.catalog.domain.SkuAttribute;
import org.broadleafcommerce.core.catalog.service.CatalogService;
import org.broadleafcommerce.core.inventory.service.InventoryService;
import org.broadleafcommerce.core.search.domain.ProductSearchCriteria;
import org.broadleafcommerce.core.search.domain.ProductSearchResult;
import org.broadleafcommerce.core.search.domain.SearchFacetDTO;
import org.broadleafcommerce.core.search.service.SearchService;
import org.broadleafcommerce.core.web.api.BroadleafWebServicesException;
import org.broadleafcommerce.core.web.api.endpoint.BaseEndpoint;
import org.broadleafcommerce.core.web.api.wrapper.CategoriesWrapper;
import org.broadleafcommerce.core.web.api.wrapper.CategoryAttributeWrapper;
import org.broadleafcommerce.core.web.api.wrapper.CategoryWrapper;
import org.broadleafcommerce.core.web.api.wrapper.InventoryWrapper;
import org.broadleafcommerce.core.web.api.wrapper.MediaWrapper;
import org.broadleafcommerce.core.web.api.wrapper.ProductAttributeWrapper;
import org.broadleafcommerce.core.web.api.wrapper.ProductWrapper;
import org.broadleafcommerce.core.web.api.wrapper.RelatedProductWrapper;
import org.broadleafcommerce.core.web.api.wrapper.SearchResultsWrapper;
import org.broadleafcommerce.core.web.api.wrapper.SkuAttributeWrapper;
import org.broadleafcommerce.core.web.api.wrapper.SkuWrapper;
import org.broadleafcommerce.core.web.service.SearchFacetDTOService;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;

/**
* This class exposes catalog services as RESTful APIs.  It is dependent on
* a JAX-RS implementation such as Jersey.  This class must be extended, with appropriate JAX-RS
* annotations, such as: <br></br>
*
* <code>javax.ws.rs.@Scope</code> <br></br>
* <code>javax.ws.rs.@Path</code> <br></br>
* <code>javax.ws.rs.@Produces</code> <br></br>
* <code>javax.ws.rs.@Consumes</code> <br></br>
* <code>javax.ws.rs.@Context</code> <br></br>
* etc... <br></br>
*
* ... in the subclass.  The subclass must also be a Spring Bean.  The subclass can then override
* the methods, and specify custom inputs and outputs.  It will also specify
* <code>javax.ws.rs.@Path annotations</code>, <code>javax.ws.rs.@Context</code>,
* <code>javax.ws.rs.@PathParam</code>, <code>javax.ws.rs.@QueryParam</code>,
* <code>javax.ws.rs.@GET</code>, <code>javax.ws.rs.@POST</code>, etc...  Essentially, the subclass
* will override and extend the methods of this class, add new methods, and control the JAX-RS behavior
* using annotations according to the JAX-RS specification.
*
* User: Kelly Tisdell
*/
public abstract class CatalogEndpoint extends BaseEndpoint {

    @Resource(name="blCatalogService")
    protected CatalogService catalogService;

    @Resource(name = "blSearchService")
    protected SearchService searchService;

    @Resource(name = "blSearchFacetDTOService")
    protected SearchFacetDTOService facetService;

    @Resource(name = "blExploitProtectionService")
    protected ExploitProtectionService exploitProtectionService;

    @Resource(name = "blStaticAssetPathService")
    protected StaticAssetPathService staticAssetPathService;
   
    @Resource(name = "blInventoryService")
    protected InventoryService inventoryService;

    /**
     * Search for {@code Product} by product id
     *
     * @param id the product id
     * @return the product instance with the given product id
     */
    public ProductWrapper findProductById(HttpServletRequest request, Long id) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            ProductWrapper wrapper;
            wrapper = (ProductWrapper) context.getBean(ProductWrapper.class.getName());
            wrapper.wrapDetails(product, request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }

    /**
     * This uses Broadleaf's search service to search for products within a category.
     * @param request
     * @param q
     * @param categoryId
     * @param pageSize
     * @param page
     * @return
     */
    public SearchResultsWrapper findProductsByCategoryAndQuery(HttpServletRequest request,
            Long categoryId,
            String q,
            Integer pageSize,
            Integer page) {
        try {
            if (StringUtils.isNotEmpty(q)) {
                q = StringUtils.trim(q);
                q = exploitProtectionService.cleanString(q);
            } else {
                throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
                        .addMessage(BroadleafWebServicesException.SEARCH_QUERY_EMPTY);
            }
        } catch (ServiceException e) {
            throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
                    .addMessage(BroadleafWebServicesException.SEARCH_QUERY_MALFORMED, q);
        }

        if (categoryId == null) {
            throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
                    .addMessage(BroadleafWebServicesException.INVALID_CATEGORY_ID, categoryId);
        }

        Category category = null;
        category = catalogService.findCategoryById(categoryId);
        if (category == null) {
            throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
                    .addMessage(BroadleafWebServicesException.INVALID_CATEGORY_ID, categoryId);
        }

        List<SearchFacetDTO> availableFacets = getSearchService().getSearchFacets();
        ProductSearchCriteria searchCriteria = facetService.buildSearchCriteria(request, availableFacets);
        try {
            ProductSearchResult result = null;
            result = getSearchService().findProductsByCategoryAndQuery(category, q, searchCriteria);
            facetService.setActiveFacetResults(result.getFacets(), request);

            SearchResultsWrapper wrapper = (SearchResultsWrapper) context.getBean(SearchResultsWrapper.class.getName());
            wrapper.wrapDetails(result, request);
            return wrapper;
        } catch (ServiceException e) {
            throw BroadleafWebServicesException.build(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
        }
    }

    /**
     * Queries the products. The parameter q, which represents the query, is required. It can be any
     * string, but is typically a name or keyword, similar to a search engine search.
     * @param request
     * @param q
     * @param pageSize
     * @param page
     * @return
     */
    public SearchResultsWrapper findProductsByQuery(HttpServletRequest request,
            String q,
            Integer pageSize,
            Integer page) {
        try {
            if (StringUtils.isNotEmpty(q)) {
                q = StringUtils.trim(q);
                q = exploitProtectionService.cleanString(q);
            } else {
                throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
                        .addMessage(BroadleafWebServicesException.SEARCH_QUERY_EMPTY);
            }
        } catch (ServiceException e) {
            throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
                    .addMessage(BroadleafWebServicesException.SEARCH_QUERY_MALFORMED, q);
        }

        List<SearchFacetDTO> availableFacets = getSearchService().getSearchFacets();
        ProductSearchCriteria searchCriteria = facetService.buildSearchCriteria(request, availableFacets);
        try {
            ProductSearchResult result = null;
            result = getSearchService().findProductsByQuery(q, searchCriteria);
            facetService.setActiveFacetResults(result.getFacets(), request);

            SearchResultsWrapper wrapper = (SearchResultsWrapper) context.getBean(SearchResultsWrapper.class.getName());
            wrapper.wrapDetails(result, request);
            return wrapper;
        } catch (ServiceException e) {
            throw BroadleafWebServicesException.build(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode())
                    .addMessage(BroadleafWebServicesException.SEARCH_ERROR);

        }
    }

    /**
     * Search for {@code Sku} instances for a given product
     *
     * @param id
     * @return the list of sku instances for the product
     */
    public List<SkuWrapper> findSkusByProductById(HttpServletRequest request, Long id) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            List<Sku> skus = product.getAllSkus();
            List<SkuWrapper> out = new ArrayList<SkuWrapper>();
            if (skus != null) {
                for (Sku sku : skus) {
                    SkuWrapper wrapper = (SkuWrapper)context.getBean(SkuWrapper.class.getName());
                    wrapper.wrapSummary(sku, request);
                    out.add(wrapper);
                }
                return out;
            }
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }
   
    public SkuWrapper findDefaultSkuByProductId(HttpServletRequest request, Long id) {
        Product product = catalogService.findProductById(id);
        if (product != null && product.getDefaultSku() != null) {
            SkuWrapper wrapper = (SkuWrapper)context.getBean(SkuWrapper.class.getName());
            wrapper.wrapDetails(product.getDefaultSku(), request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }

    public CategoriesWrapper findAllCategories(HttpServletRequest request,
            String name,
            int limit,
            int offset) {
        List<Category> categories;
        if (name != null) {
            categories = catalogService.findCategoriesByName(name, limit, offset);
        } else {
            categories = catalogService.findAllCategories(limit, offset);
        }
        CategoriesWrapper wrapper = (CategoriesWrapper)context.getBean(CategoriesWrapper.class.getName());
        wrapper.wrapDetails(categories, request);
        return wrapper;
    }

    public CategoriesWrapper findSubCategories(HttpServletRequest request,
            Long id,
            int limit,
            int offset,
            boolean active) {
        Category category = catalogService.findCategoryById(id);
        if (category != null) {
            List<Category> categories;
            CategoriesWrapper wrapper = (CategoriesWrapper)context.getBean(CategoriesWrapper.class.getName());
            if (active) {
                categories = catalogService.findActiveSubCategoriesByCategory(category, limit, offset);
            } else {
                categories = catalogService.findAllSubCategories(category, limit, offset);
            }
            wrapper.wrapDetails(categories, request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.CATEGORY_NOT_FOUND, id);

    }

    public CategoriesWrapper findActiveSubCategories(HttpServletRequest request,
            Long id,
            int limit,
            int offset) {
        return findSubCategories(request, id, limit, offset, true);
    }

    public CategoryWrapper findCategoryById(HttpServletRequest request,
            Long id,
            int productLimit,
            int productOffset,
            int subcategoryLimit,
            int subcategoryOffset) {
        Category cat = catalogService.findCategoryById(id);
        if (cat != null) {

            //Explicitly setting these request attributes because the CategoryWrapper.wrap() method needs them
            request.setAttribute("productLimit", productLimit);
            request.setAttribute("productOffset", productOffset);
            request.setAttribute("subcategoryLimit", subcategoryLimit);
            request.setAttribute("subcategoryOffset", subcategoryOffset);

            CategoryWrapper wrapper = (CategoryWrapper)context.getBean(CategoryWrapper.class.getName());
            wrapper.wrapDetails(cat, request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.CATEGORY_NOT_FOUND, id);
    }

    /**
     * Allows you to search for a category by ID or by name.
     * @param request
     * @param searchParameter
     * @param productLimit
     * @param productOffset
     * @param subcategoryLimit
     * @param subcategoryOffset
     * @return
     */
    public CategoryWrapper findCategoryByIdOrName(HttpServletRequest request,
            String searchParameter,
            int productLimit,
            int productOffset,
            int subcategoryLimit,
            int subcategoryOffset) {

        Category cat = null;

        if (searchParameter != null) {
            try {
                cat = catalogService.findCategoryById(Long.parseLong(searchParameter));
            } catch (NumberFormatException e) {
                List<Category> categories = catalogService.findCategoriesByName(searchParameter);
                if (categories != null && !categories.isEmpty()) {
                    cat = categories.get(0);
                }
            }
        }
        if (cat != null) {

            //Explicitly setting these request attributes because the CategoryWrapper.wrap() method needs them
            request.setAttribute("productLimit", productLimit);
            request.setAttribute("productOffset", productOffset);
            request.setAttribute("subcategoryLimit", subcategoryLimit);
            request.setAttribute("subcategoryOffset", subcategoryOffset);

            CategoryWrapper wrapper = (CategoryWrapper) context.getBean(CategoryWrapper.class.getName());
            wrapper.wrapDetails(cat, request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.CATEGORY_NOT_FOUND, searchParameter);
    }

    public List<CategoryAttributeWrapper> findCategoryAttributesForCategory(HttpServletRequest request,
            Long id) {
        Category category = catalogService.findCategoryById(id);
        if (category != null) {
            ArrayList<CategoryAttributeWrapper> out = new ArrayList<CategoryAttributeWrapper>();
            if (category.getCategoryAttributes() != null) {
                for (CategoryAttribute attribute : category.getCategoryAttributes()) {
                    CategoryAttributeWrapper wrapper = (CategoryAttributeWrapper)context.getBean(CategoryAttributeWrapper.class.getName());
                    wrapper.wrapSummary(attribute, request);
                    out.add(wrapper);
                }
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.CATEGORY_NOT_FOUND, id);
    }

    public List<RelatedProductWrapper> findUpSaleProductsByProduct(HttpServletRequest request,
            Long id,
            int limit,
            int offset) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            List<RelatedProductWrapper> out = new ArrayList<RelatedProductWrapper>();

            //TODO: Write a service method that accepts offset and limit
            List<RelatedProduct> relatedProds = product.getUpSaleProducts();
            if (relatedProds != null) {
                for (RelatedProduct prod : relatedProds) {
                    RelatedProductWrapper wrapper = (RelatedProductWrapper)context.getBean(RelatedProductWrapper.class.getName());
                    wrapper.wrapSummary(prod, request);
                    out.add(wrapper);
                }
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }

    public List<RelatedProductWrapper> findCrossSaleProductsByProduct(HttpServletRequest request,
            Long id,
            int limit,
            int offset) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            List<RelatedProductWrapper> out = new ArrayList<RelatedProductWrapper>();

            //TODO: Write a service method that accepts offset and limit
            List<RelatedProduct> xSellProds = product.getCrossSaleProducts();
            if (xSellProds != null) {
                for (RelatedProduct prod : xSellProds) {
                    RelatedProductWrapper wrapper = (RelatedProductWrapper)context.getBean(RelatedProductWrapper.class.getName());
                    wrapper.wrapSummary(prod, request);
                    out.add(wrapper);
                }
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }
   
    public List<ProductAttributeWrapper> findProductAttributesForProduct(HttpServletRequest request,
            Long id) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            ArrayList<ProductAttributeWrapper> out = new ArrayList<ProductAttributeWrapper>();
            if (product.getProductAttributes() != null) {
                for (Map.Entry<String, ProductAttribute> entry : product.getProductAttributes().entrySet()) {
                    ProductAttributeWrapper wrapper = (ProductAttributeWrapper)context.getBean(ProductAttributeWrapper.class.getName());
                    wrapper.wrapSummary(entry.getValue(), request);
                    out.add(wrapper);
                }
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }

    public List<SkuAttributeWrapper> findSkuAttributesForSku(HttpServletRequest request,
            Long id) {
        Sku sku = catalogService.findSkuById(id);
        if (sku != null) {
            ArrayList<SkuAttributeWrapper> out = new ArrayList<SkuAttributeWrapper>();
            if (sku.getSkuAttributes() != null) {
                for (Map.Entry<String, SkuAttribute> entry : sku.getSkuAttributes().entrySet()) {
                    SkuAttributeWrapper wrapper = (SkuAttributeWrapper)context.getBean(SkuAttributeWrapper.class.getName());
                    wrapper.wrapSummary(entry.getValue(), request);
                    out.add(wrapper);
                }
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.SKU_NOT_FOUND, id);
    }

    public List<MediaWrapper> findMediaForSku(HttpServletRequest request,
            Long id) {
        Sku sku = catalogService.findSkuById(id);
        if (sku != null) {
            List<MediaWrapper> medias = new ArrayList<MediaWrapper>();
            if (sku.getSkuMedia() != null && ! sku.getSkuMedia().isEmpty()) {
                for (Media media : sku.getSkuMedia().values()) {
                    MediaWrapper wrapper = (MediaWrapper)context.getBean(MediaWrapper.class.getName());
                    wrapper.wrapSummary(media, request);
                    if (wrapper.isAllowOverrideUrl()){
                        wrapper.setUrl(staticAssetPathService.convertAssetPath(media.getUrl(), request.getContextPath(), request.isSecure()));
                    }
                    medias.add(wrapper);
                }
            }
            return medias;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.SKU_NOT_FOUND, id);
    }

    public SkuWrapper findSkuById(HttpServletRequest request,
            Long id) {
        Sku sku = catalogService.findSkuById(id);
        if (sku != null) {
            SkuWrapper wrapper = (SkuWrapper)context.getBean(SkuWrapper.class.getName());
            wrapper.wrapDetails(sku, request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.SKU_NOT_FOUND, id);
    }
   
    public List<InventoryWrapper> findInventoryForSkus(HttpServletRequest request, List<Long> ids) {
        List<Sku> skus = catalogService.findSkusByIds(ids);
        if (CollectionUtils.isNotEmpty(skus)) {
            Map<Sku, Integer> quantities = inventoryService.retrieveQuantitiesAvailable(new HashSet<Sku>(skus));
            List<InventoryWrapper> out = new ArrayList<InventoryWrapper>();
            for (Map.Entry<Sku, Integer> entry : quantities.entrySet()) {
                InventoryWrapper wrapper = (InventoryWrapper)context.getBean(InventoryWrapper.class.getName());
                wrapper.wrapSummary(entry.getKey(), entry.getValue(), request);
                out.add(wrapper);
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.SKU_NOT_FOUND, skus.toArray());
    }

    public List<MediaWrapper> findMediaForProduct(HttpServletRequest request,
            Long id) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            ArrayList<MediaWrapper> out = new ArrayList<MediaWrapper>();
            Map<String, Media> media = product.getMedia();
            if (media != null) {
                for (Media med : media.values()) {
                    MediaWrapper wrapper = (MediaWrapper)context.getBean(MediaWrapper.class.getName());
                    wrapper.wrapSummary(med, request);
                    if (wrapper.isAllowOverrideUrl()){
                        wrapper.setUrl(staticAssetPathService.convertAssetPath(med.getUrl(), request.getContextPath(), request.isSecure()));
                    }
                    out.add(wrapper);
                }
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }

    public List<MediaWrapper> findMediaForCategory(HttpServletRequest request,
            Long id) {
        Category category = catalogService.findCategoryById(id);
        if (category != null) {
            ArrayList<MediaWrapper> out = new ArrayList<MediaWrapper>();
            Map<String, Media> media = category.getCategoryMedia();
            for (Media med : media.values()) {
                MediaWrapper wrapper = (MediaWrapper)context.getBean(MediaWrapper.class.getName());
                wrapper.wrapSummary(med, request);
                out.add(wrapper);
            }
            return out;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.CATEGORY_NOT_FOUND, id);
    }

    public CategoriesWrapper findParentCategoriesForProduct(HttpServletRequest request,
            Long id) {
        Product product = catalogService.findProductById(id);
        if (product != null) {
            CategoriesWrapper wrapper = (CategoriesWrapper)context.getBean(CategoriesWrapper.class.getName());
            List<Category> categories = new ArrayList<Category>();
            for (CategoryProductXref categoryXref : product.getAllParentCategoryXrefs()) {
                categories.add(categoryXref.getCategory());
            }
            wrapper.wrapDetails(categories, request);
            return wrapper;
        }
        throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
                .addMessage(BroadleafWebServicesException.PRODUCT_NOT_FOUND, id);
    }

    protected SearchService getSearchService() {
        return searchService;
    }
}
TOP

Related Classes of org.broadleafcommerce.core.web.api.endpoint.catalog.CatalogEndpoint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.