/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.webservices.utils; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.List; import nl.strohalm.cyclos.entities.accounts.Currency; import nl.strohalm.cyclos.entities.ads.AbstractAdQuery; import nl.strohalm.cyclos.entities.ads.Ad; import nl.strohalm.cyclos.entities.ads.Ad.Status; import nl.strohalm.cyclos.entities.ads.Ad.TradeType; import nl.strohalm.cyclos.entities.ads.AdCategory; import nl.strohalm.cyclos.entities.ads.AdQuery; import nl.strohalm.cyclos.entities.ads.FullTextAdQuery; import nl.strohalm.cyclos.entities.customization.fields.AdCustomField; import nl.strohalm.cyclos.entities.customization.fields.AdCustomField.Visibility; import nl.strohalm.cyclos.entities.customization.fields.AdCustomFieldValue; import nl.strohalm.cyclos.entities.customization.fields.MemberCustomField; import nl.strohalm.cyclos.entities.customization.fields.MemberCustomFieldValue; import nl.strohalm.cyclos.entities.groups.GroupFilter; import nl.strohalm.cyclos.entities.groups.MemberGroup; import nl.strohalm.cyclos.entities.members.Member; import nl.strohalm.cyclos.entities.settings.LocalSettings; import nl.strohalm.cyclos.services.ads.AdServiceLocal; import nl.strohalm.cyclos.services.customization.AdCustomFieldServiceLocal; import nl.strohalm.cyclos.services.customization.MemberCustomFieldServiceLocal; import nl.strohalm.cyclos.services.settings.SettingsServiceLocal; import nl.strohalm.cyclos.utils.CustomFieldHelper; import nl.strohalm.cyclos.utils.EntityHelper; import nl.strohalm.cyclos.utils.Period; import nl.strohalm.cyclos.utils.TimePeriod; import nl.strohalm.cyclos.utils.access.LoggedUser; import nl.strohalm.cyclos.utils.conversion.CoercionHelper; import nl.strohalm.cyclos.utils.conversion.Transformer; import nl.strohalm.cyclos.webservices.ads.AbstractAdSearchParameters; import nl.strohalm.cyclos.webservices.ads.AbstractAdSearchParameters.AdVOStatus; import nl.strohalm.cyclos.webservices.ads.AbstractAdSearchParameters.AdVOTradeType; import nl.strohalm.cyclos.webservices.ads.AdResultPage; import nl.strohalm.cyclos.webservices.ads.AdSearchParameters; import nl.strohalm.cyclos.webservices.ads.FullTextAdSearchParameters; import nl.strohalm.cyclos.webservices.model.AdCategoryHierarchicalVO; import nl.strohalm.cyclos.webservices.model.AdCategoryVO; import nl.strohalm.cyclos.webservices.model.AdVO; import nl.strohalm.cyclos.webservices.model.DetailedAdCategoryVO; import nl.strohalm.cyclos.webservices.model.FieldValueVO; import nl.strohalm.cyclos.webservices.model.MyAdVO; import nl.strohalm.cyclos.webservices.model.TimePeriodVO; /** * Utility class for ads<br> * <b>WARN</b>: Be aware that this helper <b>doesn't</b> access the services through the security layer. They are all local services. * @author luis */ public class AdHelper { private CurrencyHelper currencyHelper; private FieldHelper fieldHelper; private ImageHelper imageHelper; private MemberHelper memberHelper; private SettingsServiceLocal settingsService; private QueryHelper queryHelper; private AdCustomFieldServiceLocal adCustomFieldService; private MemberCustomFieldServiceLocal memberCustomFieldService; private AdServiceLocal adServiceLocal; private CustomFieldHelper customFieldHelper; public void setAdCustomFieldServiceLocal(final AdCustomFieldServiceLocal adCustomFieldService) { this.adCustomFieldService = adCustomFieldService; } public void setAdServiceLocal(final AdServiceLocal adService) { adServiceLocal = adService; } public void setCurrencyHelper(final CurrencyHelper currencyHelper) { this.currencyHelper = currencyHelper; } public void setCustomFieldHelper(final CustomFieldHelper customFieldHelper) { this.customFieldHelper = customFieldHelper; } public void setFieldHelper(final FieldHelper fieldHelper) { this.fieldHelper = fieldHelper; } public void setImageHelper(final ImageHelper imageHelper) { this.imageHelper = imageHelper; } public void setMemberCustomFieldServiceLocal(final MemberCustomFieldServiceLocal memberCustomFieldService) { this.memberCustomFieldService = memberCustomFieldService; } public void setMemberHelper(final MemberHelper memberHelper) { this.memberHelper = memberHelper; } public void setQueryHelper(final QueryHelper queryHelper) { this.queryHelper = queryHelper; } public void setSettingsServiceLocal(final SettingsServiceLocal settingsService) { this.settingsService = settingsService; } public DetailedAdCategoryVO toDetailedVO(final AdCategory category) { if (category == null) { return null; } final DetailedAdCategoryVO vo = new DetailedAdCategoryVO(); vo.setId(category.getId()); vo.setName(category.getName()); vo.setFullName(category.getFullName()); vo.setLevel(category.getLevel()); // count only ads with external publication = true vo.setCountOffer(adServiceLocal.countExternalAds(category.getId(), TradeType.OFFER)); vo.setCountSearch(adServiceLocal.countExternalAds(category.getId(), TradeType.SEARCH)); final Collection<AdCategory> childrenList = category.getChildren(); final List<DetailedAdCategoryVO> children = new ArrayList<DetailedAdCategoryVO>(); for (final AdCategory child : childrenList) { children.add(toDetailedVO(child)); } vo.setChildren(children); return vo; } public FullTextAdQuery toFullTextQuery(final FullTextAdSearchParameters params) { if (params == null) { return null; } final FullTextAdQuery query = new FullTextAdQuery(); fill(params, query); return query; } /** * Converts the given ad into VO, using all custom fields and member fields */ public AdVO toFullVO(final Ad ad) { List<AdCustomField> adFields = adCustomFieldService.list(); List<MemberCustomField> memberFields = memberCustomFieldService.list(); if (!LoggedUser.isUnrestrictedClient()) { MemberGroup group = LoggedUser.member().getMemberGroup(); memberFields = customFieldHelper.onlyVisibleFields(memberFields, group); } return toVO(ad, adFields, memberFields); } /** * Converts a category into a hierarchical representation * @param category * @return */ public AdCategoryHierarchicalVO toHierarchicalVO(final AdCategory category) { if (category == null || !category.isActive()) { return null; } AdCategoryHierarchicalVO vo = new AdCategoryHierarchicalVO(); vo.setId(category.getId()); vo.setName(category.getName()); List<AdCategoryHierarchicalVO> children = new ArrayList<AdCategoryHierarchicalVO>(); for (AdCategory child : category.getChildren()) { AdCategoryHierarchicalVO childVO = toHierarchicalVO(child); if (childVO != null) { children.add(childVO); } } vo.setChildren(children); return vo; } /** * Converts the given ad into a {@link MyAdVO} with all ad fields and no member fields */ public MyAdVO toMyVO(final Ad ad) { List<AdCustomField> adFields = adCustomFieldService.list(); MyAdVO vo = toVO(MyAdVO.class, ad, adFields, null); vo.setStatus(AdVOStatus.valueOf(ad.getStatus().name())); return vo; } public AdQuery toQuery(final AdSearchParameters params) { if (params == null) { return null; } final AdQuery query = new AdQuery(); fill(params, query); query.setRandomOrder(params.getRandomOrder()); return query; } /** * Converts a list or page of ads into an AdResultPage */ public AdResultPage toResultPage(final AbstractAdSearchParameters params, final List<Ad> ads) { final List<AdCustomField> adFields = params.getShowAdFields() ? adCustomFieldService.list() : null; final List<MemberCustomField> allMemberFields = params.getShowMemberFields() ? memberCustomFieldService.list() : null; return queryHelper.toResultPage(AdResultPage.class, ads, new Transformer<Ad, AdVO>() { @Override public AdVO transform(final Ad ad) { List<MemberCustomField> memberFields = null; if (allMemberFields != null) { MemberGroup group = EntityHelper.reference(MemberGroup.class, ad.getOwner().getGroup().getId()); memberFields = customFieldHelper.onlyForGroup(allMemberFields, group); } return toVO(ad, adFields, memberFields); } }); } /** * Convert an advertisement to VO */ public AdVO toVO(final Ad ad) { return toVO(ad, null); } /** * Convert an advertisement to VO, filling the given ad custom fields */ public AdVO toVO(final Ad ad, final List<AdCustomField> fields) { return toVO(ad, fields, null); } /** * Convert an advertisement to VO, filling the given ad and owner custom fields */ public AdVO toVO(final Ad ad, final List<AdCustomField> adFields, final List<MemberCustomField> memberFields) { return toVO(AdVO.class, ad, adFields, memberFields); } /** * Convert a category to VO */ public AdCategoryVO toVO(final AdCategory category) { if (category == null) { return null; } final AdCategoryVO vo = new AdCategoryVO(); vo.setId(category.getId()); vo.setName(category.getFullName()); return vo; } /** * Convert an advertisement to VO, filling the given ad and owner custom fields */ public <VO extends AdVO> VO toVO(final Class<VO> voType, final Ad ad, final List<AdCustomField> adFields, final List<MemberCustomField> memberFields) { if (ad == null) { return null; } final LocalSettings localSettings = settingsService.getLocalSettings(); final VO vo; try { vo = voType.newInstance(); } catch (Exception e) { throw new IllegalStateException(e); } vo.setId(ad.getId()); vo.setCategory(toVO(ad.getCategory())); vo.setTitle(ad.getTitle()); vo.setDescription(ad.getDescription()); final Currency currency = ad.getCurrency(); vo.setCurrency(currencyHelper.toVO(currency)); vo.setPrice(ad.getPrice()); if (currency == null) { vo.setFormattedPrice(localSettings.getNumberConverter().toString(ad.getPrice())); } else { vo.setFormattedPrice(localSettings.getUnitsConverter(currency.getPattern()).toString(ad.getPrice())); } vo.setPermanent(ad.isPermanent()); vo.setSearching(ad.getTradeType() == Ad.TradeType.SEARCH); vo.setHtml(ad.isHtml()); final Period publicationPeriod = ad.getPublicationPeriod(); if (publicationPeriod != null) { final Calendar begin = publicationPeriod.getBegin(); final Calendar end = publicationPeriod.getEnd(); vo.setPublicationStart(begin); vo.setFormattedPublicationStart(localSettings.getRawDateConverter().toString(begin)); vo.setPublicationEnd(end); vo.setFormattedPublicationEnd(localSettings.getRawDateConverter().toString(end)); } vo.setOwner(memberHelper.toVO(ad.getOwner(), memberFields, false)); vo.setImages(imageHelper.toVOs(ad.getImages())); if (adFields != null) { List<AdCustomField> visibleAdFields = new ArrayList<AdCustomField>(); List<Visibility> allowedVisibilities = Arrays.asList(AdCustomField.Visibility.WEB_SERVICE, AdCustomField.Visibility.MEMBER); // filter by visibility for (AdCustomField adCustomField : adFields) { if (allowedVisibilities.contains(adCustomField.getVisibility())) { visibleAdFields.add(adCustomField); } } vo.setFields(fieldHelper.toList(visibleAdFields, null, ad.getCustomValues())); } return vo; } private void fill(final AbstractAdSearchParameters params, final AbstractAdQuery query) { query.fetch(Ad.Relationships.OWNER, Ad.Relationships.CUSTOM_VALUES, Ad.Relationships.IMAGES, Ad.Relationships.CATEGORY); queryHelper.fill(params, query); query.setExternalPublication(true); if (LoggedUser.isUnrestrictedClient()) { AdVOStatus status = params.getStatus(); if (status == null) { status = AdVOStatus.ACTIVE; } switch (status) { case PERMANENT: query.setStatus(Ad.Status.PERMANENT); break; case SCHEDULED: query.setStatus(Ad.Status.SCHEDULED); break; case EXPIRED: query.setStatus(Ad.Status.EXPIRED); break; default: query.setStatus(Ad.Status.ACTIVE); break; } } else { // Restricted clients can only search for active ads query.setStatus(Status.ACTIVE); } query.setCategory(params.getCategoryId() == null ? null : EntityHelper.reference(AdCategory.class, params.getCategoryId())); query.setKeywords(params.getKeywords()); query.setInitialPrice(params.getInitialPrice()); query.setFinalPrice(params.getFinalPrice()); final TimePeriodVO since = params.getSince(); if (since != null && since.getNumber() != null && since.getField() != null) { final TimePeriod timePeriod = new TimePeriod(since.getNumber(), TimePeriod.Field.valueOf(since.getField().name())); query.setSince(timePeriod); } if (params.getBeginDate() != null || params.getEndDate() != null) { query.setPeriod(Period.between(params.getBeginDate(), params.getEndDate())); } final AdVOTradeType tradeType = params.getTradeType(); if (tradeType != null) { switch (tradeType) { case OFFER: query.setTradeType(Ad.TradeType.OFFER); break; case SEARCH: query.setTradeType(Ad.TradeType.SEARCH); break; } } query.setOwner(CoercionHelper.coerce(Member.class, params.getMemberId())); final MemberGroup[] groups = EntityHelper.references(MemberGroup.class, params.getMemberGroupIds()); if (groups == null || groups.length > 0) { query.setGroups(Arrays.asList(groups)); } final GroupFilter[] groupFilters = EntityHelper.references(GroupFilter.class, params.getMemberGroupFilterIds()); if (groupFilters == null || groupFilters.length > 0) { query.setGroupFilters(Arrays.asList(groupFilters)); } final List<FieldValueVO> adFields = params.getAdFields(); if (adFields != null && adFields.size() > 0) { List<AdCustomField> adCustomFields = adCustomFieldService.list(); adCustomFields = customFieldHelper.onlyForAdsSearch(adCustomFields); query.setAdValues(customFieldHelper.<AdCustomFieldValue> toValueCollection(adCustomFields, adFields)); } final List<FieldValueVO> memberFields = params.getMemberFields(); if (memberFields != null && memberFields.size() > 0) { List<MemberCustomField> memberCustomFields = memberCustomFieldService.list(); memberCustomFields = customFieldHelper.onlyForAdSearch(memberCustomFields); query.setMemberValues(customFieldHelper.<MemberCustomFieldValue> toValueCollection(memberCustomFields, memberFields)); } query.setWithImagesOnly(params.getWithImagesOnly()); } }