nl.strohalm.cyclos.webservices.utils.MemberHelper.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.webservices.utils.MemberHelper.java

Source

/*
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.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import nl.strohalm.cyclos.entities.Relationship;
import nl.strohalm.cyclos.entities.access.Channel;
import nl.strohalm.cyclos.entities.access.ChannelPrincipal;
import nl.strohalm.cyclos.entities.access.MemberUser;
import nl.strohalm.cyclos.entities.access.PrincipalType;
import nl.strohalm.cyclos.entities.customization.fields.CustomField;
import nl.strohalm.cyclos.entities.customization.fields.MemberCustomField;
import nl.strohalm.cyclos.entities.customization.fields.MemberCustomFieldValue;
import nl.strohalm.cyclos.entities.exceptions.EntityNotFoundException;
import nl.strohalm.cyclos.entities.groups.Group.Status;
import nl.strohalm.cyclos.entities.groups.GroupFilter;
import nl.strohalm.cyclos.entities.groups.MemberGroup;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.FullTextMemberQuery;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.MemberQuery;
import nl.strohalm.cyclos.entities.services.ServiceClient;
import nl.strohalm.cyclos.services.access.AccessServiceLocal;
import nl.strohalm.cyclos.services.customization.MemberCustomFieldServiceLocal;
import nl.strohalm.cyclos.services.elements.ElementServiceLocal;
import nl.strohalm.cyclos.services.groups.GroupServiceLocal;
import nl.strohalm.cyclos.services.permissions.PermissionServiceLocal;
import nl.strohalm.cyclos.services.services.ServiceClientServiceLocal;
import nl.strohalm.cyclos.utils.CustomFieldHelper;
import nl.strohalm.cyclos.utils.EntityHelper;
import nl.strohalm.cyclos.utils.access.LoggedUser;
import nl.strohalm.cyclos.utils.conversion.Transformer;
import nl.strohalm.cyclos.webservices.PrincipalParameters;
import nl.strohalm.cyclos.webservices.WebServiceContext;
import nl.strohalm.cyclos.webservices.WebServiceFaultsEnum;
import nl.strohalm.cyclos.webservices.members.FullTextMemberSearchParameters;
import nl.strohalm.cyclos.webservices.members.MemberResultPage;
import nl.strohalm.cyclos.webservices.members.MemberSearchParameters;
import nl.strohalm.cyclos.webservices.members.RegisterMemberParameters;
import nl.strohalm.cyclos.webservices.model.FieldValueVO;
import nl.strohalm.cyclos.webservices.model.MemberVO;
import nl.strohalm.cyclos.webservices.model.MyProfileVO;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

/**
 * Utility class for members<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 MemberHelper {

    private QueryHelper queryHelper;
    private ImageHelper imageHelper;
    private FieldHelper fieldHelper;
    private ElementServiceLocal elementServiceLocal;
    private ServiceClientServiceLocal serviceClientServiceLocal;
    private MemberCustomFieldServiceLocal memberCustomFieldServiceLocal;
    private PermissionServiceLocal permissionService;
    private GroupServiceLocal groupServiceLocal;
    private ChannelHelper channelHelper;
    private AccessServiceLocal accessServiceLocal;
    private CustomFieldHelper customFieldHelper;

    /**
     * Throws an invalid-channel fault if the current client's channel is not enabled for the given member
     */
    public void checkChannelEnabledForMember(final Member member) {
        if (!isChannelEnabledForMember(member)) {
            throw WebServiceHelper.fault(WebServiceFaultsEnum.INVALID_CHANNEL);
        }
    }

    /**
     * Returns whether the current client's channel is enabled for the given member
     */
    public boolean isChannelEnabledForMember(final Member member) {
        final Channel channel = WebServiceContext.getChannel();
        // If not restricted to a channel, no need to check
        if (channel == null) {
            return true;
        }
        // If the channel restricted member is the same member, no need to check
        final Member restrictedMember = WebServiceContext.getMember();
        if (restrictedMember != null && restrictedMember.equals(member)) {
            return true;
        }
        return accessServiceLocal.isChannelEnabledForMember(channel.getInternalName(), member);
    }

    /**
     * Loads a member using the given principal, according to the current channel
     */
    public Member loadByPrincipal(PrincipalType principalType, final String principal,
            final Relationship... relationships) {
        if (StringUtils.isNotEmpty(principal)) {
            final Channel channel = WebServiceContext.getChannel();
            if (channel != null) {
                if (principalType == null) {
                    principalType = channel.getDefaultPrincipalType();
                } else if (!channel.getPrincipalTypes().contains(principalType)) {
                    return null;
                }
            }
            Member member;
            if (ArrayUtils.isNotEmpty(relationships)) {
                Relationship[] tmp = new Relationship[relationships.length + 2];
                tmp[0] = Element.Relationships.USER;
                tmp[1] = Element.Relationships.GROUP;
                System.arraycopy(relationships, 0, tmp, 2, relationships.length);
                member = elementServiceLocal.loadByPrincipal(principalType, principal, tmp);
            } else {
                member = elementServiceLocal.loadByPrincipal(principalType, principal, Element.Relationships.USER,
                        Element.Relationships.GROUP);
            }

            if (!permissionService.relatesTo(member)) {
                throw new EntityNotFoundException(Member.class);
            }
            return member;
        }
        return null;
    }

    /**
     * Loads a member using the given principal, according to the current channel
     */
    public Member loadByPrincipal(final String principalType, final String principal,
            final Relationship... relationships) {
        final PrincipalType type = channelHelper.resolvePrincipalType(principalType);
        return loadByPrincipal(type, principal, relationships);
    }

    /**
     * Checks the {@link ServiceClient#getMember()}. If restricted to a member, returns it, ignoring the received id. Otherwise, loads the member with
     * the given principal
     */
    public Member resolveMember(final PrincipalParameters params) {
        if (params == null) {
            return null;
        }
        return resolveMember(params.getPrincipalType(), params.getPrincipal());
    }

    /**
     * Checks the {@link ServiceClient#getMember()}. If restricted to a member, returns it, ignoring the received id. Otherwise, loads the member with
     * the given principal
     */
    public Member resolveMember(final PrincipalType principalType, final String principal) {
        final Member member = WebServiceContext.getMember();
        if (member == null) {
            if (StringUtils.isEmpty(principal)) {
                return null;
            }
            return loadByPrincipal(principalType, principal);
        } else {
            return member;
        }
    }

    /**
     * Checks the {@link ServiceClient#getMember()}. If restricted to a member, returns it, ignoring the received id. Otherwise, loads the member with
     * the given principal
     */
    public Member resolveMember(final String principalType, final String principal) {
        final PrincipalType type = channelHelper.resolvePrincipalType(principalType);
        return resolveMember(type, principal);
    }

    /**
     * Invokes resolveMember(String), returning it's user, or null
     */
    public MemberUser resolveUser(final PrincipalType principalType, final String principal) {
        final Member member = resolveMember(principalType, principal);
        return member == null ? null : member.getMemberUser();
    }

    public void setAccessServiceLocal(final AccessServiceLocal accessService) {
        accessServiceLocal = accessService;
    }

    public void setChannelHelper(final ChannelHelper channelHelper) {
        this.channelHelper = channelHelper;
    }

    public void setCustomFieldHelper(final CustomFieldHelper customFieldHelper) {
        this.customFieldHelper = customFieldHelper;
    }

    public void setElementServiceLocal(final ElementServiceLocal elementService) {
        elementServiceLocal = elementService;
    }

    public void setFieldHelper(final FieldHelper fieldHelper) {
        this.fieldHelper = fieldHelper;
    }

    public void setGroupServiceLocal(final GroupServiceLocal groupService) {
        groupServiceLocal = groupService;
    }

    public void setImageHelper(final ImageHelper imageHelper) {
        this.imageHelper = imageHelper;
    }

    public void setMemberCustomFieldServiceLocal(final MemberCustomFieldServiceLocal memberCustomFieldService) {
        memberCustomFieldServiceLocal = memberCustomFieldService;
    }

    public void setPermissionServiceLocal(final PermissionServiceLocal permissionService) {
        this.permissionService = permissionService;
    }

    public void setQueryHelper(final QueryHelper queryHelper) {
        this.queryHelper = queryHelper;
    }

    public void setServiceClientServiceLocal(final ServiceClientServiceLocal serviceClientService) {
        serviceClientServiceLocal = serviceClientService;
    }

    public FullTextMemberQuery toFullTextQuery(final FullTextMemberSearchParameters params) {
        if (params == null) {
            return null;
        }
        final FullTextMemberQuery query = new FullTextMemberQuery();
        query.setEnabled(true);
        query.fetch(Element.Relationships.GROUP, Element.Relationships.USER);
        if (params.getShowCustomFields()) {
            query.fetch(Member.Relationships.CUSTOM_VALUES);
        }
        if (params.getShowImages()) {
            query.fetch(Member.Relationships.IMAGES);
        }
        query.setKeywords(params.getKeywords());
        final GroupFilter[] groupFilters = EntityHelper.references(GroupFilter.class, params.getGroupFilterIds());
        if (groupFilters == null || groupFilters.length > 0) {
            query.setGroupFilters(Arrays.asList(groupFilters));
        }
        final MemberGroup[] groups = EntityHelper.references(MemberGroup.class, params.getGroupIds());
        if (groups == null || groups.length > 0) {
            query.setGroups(Arrays.asList(groups));
        }
        queryHelper.fill(params, query);
        if (params.getExcludeLoggedIn()) {
            Member member = LoggedUser.member();
            query.setExcludeElements(Collections.<Element>singleton(member));
        }
        query.setWithImagesOnly(params.getWithImagesOnly());
        List<MemberCustomField> memberFields = customFieldHelper
                .onlyForMemberSearch(memberCustomFieldServiceLocal.list());
        query.setCustomValues(customFieldHelper.toValueCollection(memberFields, params.getFields()));
        return query;
    }

    /**
     * Converts a member to VO with all custom fields and images
     */
    public MemberVO toFullVO(final Member member) {
        if (!member.isActive() || member.getGroup().getStatus() == Status.REMOVED) {
            throw new EntityNotFoundException();
        }
        List<MemberCustomField> fields = memberCustomFieldServiceLocal.list();
        if (!LoggedUser.isUnrestrictedClient()) {
            MemberGroup group = LoggedUser.member().getMemberGroup();
            fields = customFieldHelper.onlyVisibleFields(fields, group);
        }
        return toVO(member, fields, true);
    }

    public Member toMember(final RegisterMemberParameters params) {
        // Find the group
        MemberGroup group;
        try {
            final ServiceClient client = serviceClientServiceLocal.load(WebServiceContext.getClient().getId(),
                    ServiceClient.Relationships.MANAGE_GROUPS);
            final Set<MemberGroup> manageGroups = client.getManageGroups();
            final Long groupId = params.getGroupId();
            if (groupId == null || groupId.intValue() <= 0) {
                group = manageGroups.iterator().next();
            } else {
                group = groupServiceLocal.load(groupId);
                if (!manageGroups.contains(group)) {
                    throw new Exception();
                }
            }
        } catch (final Exception e) {
            throw new EntityNotFoundException();
        }

        final MemberUser user = new MemberUser();
        user.setUsername(params.getUsername());
        final Member member = new Member();
        member.setGroup(group);
        member.setUser(user);
        member.setName(params.getName());
        member.setEmail(params.getEmail());
        List<MemberCustomField> fields = memberCustomFieldServiceLocal.list();
        fields = customFieldHelper.onlyForGroup(fields, group);
        final Collection<MemberCustomFieldValue> fieldValues = customFieldHelper.toValueCollection(fields,
                params.getFields());
        member.setCustomValues(fieldValues);
        return member;
    }

    /**
     * Converts the given member into a {@link MyProfileVO}
     */
    public MyProfileVO toMyProfileVO(final Member member) {
        if (!member.isActive() || member.getGroup().getStatus() == Status.REMOVED) {
            throw new EntityNotFoundException();
        }
        List<MemberCustomField> fields = customFieldHelper.onlyOwnedFields(memberCustomFieldServiceLocal.list(),
                member.getMemberGroup());
        // Convert to VO
        MyProfileVO vo = toVO(MyProfileVO.class, member, fields, fields, true);

        // Find out the hidden fields
        Set<String> hiddenFields = new HashSet<String>();
        for (MemberCustomFieldValue fieldValue : member.getCustomValues()) {
            CustomField field = fieldValue.getField();
            if (fields.contains(field) && fieldValue.isHidden()) {
                hiddenFields.add(field.getInternalName());
            }
        }
        vo.setHiddenFields(hiddenFields);
        return vo;
    }

    public MemberQuery toQuery(final MemberSearchParameters params) {
        if (params == null) {
            return null;
        }
        final MemberQuery query = new MemberQuery();
        query.setEnabled(true);
        query.fetch(Element.Relationships.GROUP, Element.Relationships.USER);
        if (params.getShowCustomFields()) {
            query.fetch(Member.Relationships.CUSTOM_VALUES);
        }
        if (params.getShowImages()) {
            query.fetch(Member.Relationships.IMAGES);
        }
        final GroupFilter[] groupFilters = EntityHelper.references(GroupFilter.class, params.getGroupFilterIds());
        if (groupFilters == null || groupFilters.length > 0) {
            query.setGroupFilters(Arrays.asList(groupFilters));
        }
        final MemberGroup[] groups = EntityHelper.references(MemberGroup.class, params.getGroupIds());
        if (groups == null || groups.length > 0) {
            query.setGroups(Arrays.asList(groups));
        }
        query.setUsername(params.getUsername());
        query.setName(params.getName());
        query.setEmail(params.getEmail());
        query.setWithImagesOnly(params.getWithImagesOnly());
        query.setRandomOrder(params.getRandomOrder());
        if (params.getExcludeLoggedIn() && LoggedUser.isMember()) {
            query.setExcludeElements(Collections.singleton(LoggedUser.element()));
        }
        queryHelper.fill(params, query);
        final List<FieldValueVO> fields = params.getFields();
        if (fields != null && fields.size() > 0) {
            query.setCustomValues(
                    customFieldHelper.toValueCollection(memberCustomFieldServiceLocal.list(), fields));
        }
        return query;
    }

    public MemberResultPage toResultPage(final List<Member> members, final boolean useCustomFields,
            final boolean useImages) {
        final List<MemberCustomField> allFields = memberCustomFieldServiceLocal.list();
        final Map<MemberGroup, List<MemberCustomField>> fieldsByGroup = new HashMap<MemberGroup, List<MemberCustomField>>();
        return queryHelper.toResultPage(MemberResultPage.class, members, new Transformer<Member, MemberVO>() {
            @Override
            public MemberVO transform(final Member member) {
                MemberGroup memberGroup = member.getMemberGroup();
                List<MemberCustomField> fields = null;
                if (useCustomFields) {
                    fields = fieldsByGroup.get(memberGroup);
                    if (fields == null) {
                        fields = customFieldHelper.onlyForGroup(allFields, memberGroup);
                        fieldsByGroup.put(memberGroup, fields);
                    }
                }
                return toVO(member, fields, useImages);
            }
        });
    }

    /**
     * Converts a member to VO, with minimum details
     */
    public MemberVO toVO(final Member member) {
        return toVO(member, null, false);
    }

    /**
     * Converts a member to VO with customized details
     */
    public MemberVO toVO(final Member member, final Collection<MemberCustomField> fields,
            final Collection<MemberCustomField> requiredFields, final boolean useImages) {
        return toVO(MemberVO.class, member, fields, requiredFields, useImages);
    }

    /**
     * Converts a member to VO
     */
    public MemberVO toVO(final Member member, final List<MemberCustomField> fields, final boolean useImages) {
        Collection<MemberCustomField> requiredFields = null;
        Channel channel = WebServiceContext.getChannel();
        if (channel != null && !CollectionUtils.isEmpty(fields)) {
            // Ensure that any custom fields used as principal for the current channel are returned in the MemberVO
            Collection<ChannelPrincipal> principals = channel.getPrincipals();
            for (ChannelPrincipal principal : principals) {
                MemberCustomField customField = principal.getCustomField();
                if (customField != null && fields.contains(customField)) {
                    if (requiredFields == null) {
                        requiredFields = new HashSet<MemberCustomField>();
                    }
                    requiredFields.add(customField);
                }
            }
        }

        return toVO(member, fields, requiredFields, useImages);
    }

    private <VO extends MemberVO> VO toVO(final Class<VO> voType, final Member member,
            final Collection<MemberCustomField> fields, final Collection<MemberCustomField> requiredFields,
            final boolean useImages) {
        if (member == null) {
            return null;
        }
        VO vo;
        try {
            vo = voType.newInstance();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
        vo.setId(member.getId());
        vo.setName(member.getName());
        vo.setUsername(member.getUsername());
        vo.setEmail(member.getEmail());
        vo.setGroupId(member.getGroup().getId());
        if (fields != null) {
            final Collection<MemberCustomFieldValue> customValues = ((Member) elementServiceLocal
                    .load(member.getId(), Member.Relationships.CUSTOM_VALUES)).getCustomValues();
            vo.setFields(fieldHelper.toList(fields, requiredFields, customValues));
        } else {
            final List<FieldValueVO> empty = Collections.emptyList();
            vo.setFields(empty);
        }
        if (useImages) {
            vo.setImages(imageHelper.toVOs(member.getImages()));
        }
        return vo;
    }
}