001// --------------------------------------------------------------------------------
002// Copyright 2002-2026 Echo Three, LLC
003//
004// Licensed under the Apache License, Version 2.0 (the "License");
005// you may not use this file except in compliance with the License.
006// You may obtain a copy of the License at
007//
008//     http://www.apache.org/licenses/LICENSE-2.0
009//
010// Unless required by applicable law or agreed to in writing, software
011// distributed under the License is distributed on an "AS IS" BASIS,
012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013// See the License for the specific language governing permissions and
014// limitations under the License.
015// --------------------------------------------------------------------------------
016
017package com.echothree.model.control.party.server.graphql;
018
019import com.echothree.control.user.contact.common.form.ContactFormFactory;
020import com.echothree.control.user.contact.server.command.GetContactMechanismPurposeCommand;
021import com.echothree.model.control.accounting.server.graphql.AccountingSecurityUtils;
022import com.echothree.model.control.accounting.server.graphql.CurrencyObject;
023import com.echothree.model.control.contact.server.control.ContactControl;
024import com.echothree.model.control.contact.server.graphql.PartyContactMechanismObject;
025import com.echothree.model.control.contact.server.graphql.PartyContactMechanismPurposeObject;
026import com.echothree.model.control.contactlist.server.control.ContactListControl;
027import com.echothree.model.control.contactlist.server.graphql.ContactListSecurityUtils;
028import com.echothree.model.control.contactlist.server.graphql.PartyContactListObject;
029import com.echothree.model.control.graphql.server.graphql.BaseEntityInstanceObject;
030import com.echothree.model.control.graphql.server.graphql.count.Connections;
031import com.echothree.model.control.graphql.server.graphql.count.CountedObjects;
032import com.echothree.model.control.graphql.server.graphql.count.CountingDataConnectionFetcher;
033import com.echothree.model.control.graphql.server.graphql.count.CountingPaginatedData;
034import com.echothree.model.control.graphql.server.util.BaseGraphQl;
035import static com.echothree.model.control.graphql.server.util.BaseGraphQl.getUserVisitPK;
036import com.echothree.model.control.graphql.server.util.count.ObjectLimiter;
037import com.echothree.model.control.party.server.control.PartyControl;
038import com.echothree.model.control.subscription.server.control.SubscriptionControl;
039import com.echothree.model.control.subscription.server.graphql.SubscriptionObject;
040import com.echothree.model.control.subscription.server.graphql.SubscriptionSecurityUtils;
041import com.echothree.model.control.user.server.control.UserControl;
042import com.echothree.model.data.contact.common.PartyContactMechanismConstants;
043import com.echothree.model.data.contactlist.common.PartyContactListConstants;
044import com.echothree.model.data.party.common.PartyAliasConstants;
045import com.echothree.model.data.party.server.entity.Party;
046import com.echothree.model.data.party.server.entity.PartyDetail;
047import com.echothree.model.data.subscription.common.SubscriptionConstants;
048import com.echothree.util.server.persistence.Session;
049import graphql.annotations.annotationTypes.GraphQLDescription;
050import graphql.annotations.annotationTypes.GraphQLField;
051import graphql.annotations.annotationTypes.GraphQLName;
052import graphql.annotations.annotationTypes.GraphQLNonNull;
053import graphql.annotations.connection.GraphQLConnection;
054import graphql.schema.DataFetchingEnvironment;
055import java.util.ArrayList;
056import java.util.stream.Collectors;
057import javax.enterprise.inject.spi.CDI;
058
059public abstract class BasePartyObject
060        extends BaseEntityInstanceObject {
061
062    protected final Party party; // Always Present
063
064    protected BasePartyObject(Party party) {
065        super(party.getPrimaryKey());
066        
067        this.party = party;
068    }
069
070    private PartyDetail partyDetail; // Optional, use getPartyDetail()
071
072    protected PartyDetail getPartyDetail() {
073        if(partyDetail == null) {
074            partyDetail = party.getLastDetail();
075        }
076        
077        return partyDetail;
078    }
079    
080    @GraphQLField
081    @GraphQLDescription("party name")
082    @GraphQLNonNull
083    public String getPartyName() {
084        return getPartyDetail().getPartyName();
085    }
086
087    @GraphQLField
088    @GraphQLDescription("party type")
089    @GraphQLNonNull
090    public PartyTypeObject getPartyType(final DataFetchingEnvironment env) {
091        return PartySecurityUtils.getHasPartyTypeAccess(env) ? new PartyTypeObject(getPartyDetail().getPartyType()) : null;
092    }
093
094    @GraphQLField
095    @GraphQLDescription("preferred language")
096    public LanguageObject getPreferredLanguage(final DataFetchingEnvironment env) {
097        var preferredLanguage = getPartyDetail().getPreferredLanguage();
098        
099        return preferredLanguage != null && PartySecurityUtils.getHasLanguageAccess(env) ? new LanguageObject(preferredLanguage) : null;
100    }
101
102    @GraphQLField
103    @GraphQLDescription("preferred currency")
104    public CurrencyObject getPreferredCurrency(final DataFetchingEnvironment env) {
105        var preferredCurrency = getPartyDetail().getPreferredCurrency();
106        
107        return preferredCurrency != null && AccountingSecurityUtils.getHasCurrencyAccess(env) ? new CurrencyObject(preferredCurrency) : null;
108    }
109
110    @GraphQLField
111    @GraphQLDescription("preferred time zone")
112    public TimeZoneObject getPreferredTimeZone(final DataFetchingEnvironment env) {
113        var preferredTimeZone = getPartyDetail().getPreferredTimeZone();
114        
115        return preferredTimeZone != null && PartySecurityUtils.getHasTimeZoneAccess(env) ? new TimeZoneObject(preferredTimeZone) : null;
116    }
117
118    @GraphQLField
119    @GraphQLDescription("preferred date time format")
120    public DateTimeFormatObject getPreferredDateTimeFormat(final DataFetchingEnvironment env) {
121        var preferredDateTimeFormat = getPartyDetail().getPreferredDateTimeFormat();
122        
123        return preferredDateTimeFormat != null && PartySecurityUtils.getHasDateTimeFormatAccess(env) ? new DateTimeFormatObject(preferredDateTimeFormat) : null;
124    }
125    
126    @GraphQLField
127    @GraphQLDescription("person")
128    public PersonObject getPerson(final DataFetchingEnvironment env) {
129        var partyControl = Session.getModelController(PartyControl.class);
130        var person = partyControl.getPerson(party);
131        
132        return person == null ? null : new PersonObject(person);
133    }
134    
135    @GraphQLField
136    @GraphQLDescription("party group")
137    public PartyGroupObject getPartyGroup(final DataFetchingEnvironment env) {
138        var partyControl = Session.getModelController(PartyControl.class);
139        var partyGroup = partyControl.getPartyGroup(party);
140        
141        return partyGroup == null ? null : new PartyGroupObject(partyGroup);
142    }
143    
144    @GraphQLField
145    @GraphQLDescription("description")
146    @GraphQLNonNull
147    public String getDescription(final DataFetchingEnvironment env) {
148        var partyControl = Session.getModelController(PartyControl.class);
149        var userControl = Session.getModelController(UserControl.class);
150
151        return partyControl.getBestPartyDescription(party, userControl.getPreferredLanguageFromUserVisit(BaseGraphQl.getUserVisit(env)));
152    }
153
154    @GraphQLField
155    @GraphQLDescription("party aliases")
156    @GraphQLNonNull
157    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
158    public CountingPaginatedData<PartyAliasObject> getPartyAliases(final DataFetchingEnvironment env) {
159        if(PartySecurityUtils.getHasPartyAliasesAccess(env, party)) {
160            var partyControl = Session.getModelController(PartyControl.class);
161            var totalCount = partyControl.countPartyAliasesByParty(party);
162
163            try(var objectLimiter = new ObjectLimiter(env, PartyAliasConstants.COMPONENT_VENDOR_NAME, PartyAliasConstants.ENTITY_TYPE_NAME, totalCount)) {
164                var entities = partyControl.getPartyAliasesByParty(party);
165                var partyAliases = entities.stream().map(PartyAliasObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
166
167                return new CountedObjects<>(objectLimiter, partyAliases);
168            }
169        } else {
170            return Connections.emptyConnection();
171        }
172    }
173
174    @GraphQLField
175    @GraphQLDescription("party contact mechanisms")
176    @GraphQLNonNull
177    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
178    public CountingPaginatedData<PartyContactMechanismObject> getPartyContactMechanisms(final DataFetchingEnvironment env) {
179//        if(ContactSecurityUtils.getHasPartyContactMechanismsAccess(env, party)) {
180            var contactControl = Session.getModelController(ContactControl.class);
181            var totalCount = contactControl.countPartyContactMechanismsByParty(party);
182
183            try(var objectLimiter = new ObjectLimiter(env, PartyContactMechanismConstants.COMPONENT_VENDOR_NAME, PartyContactMechanismConstants.ENTITY_TYPE_NAME, totalCount)) {
184                var entities = contactControl.getPartyContactMechanismsByParty(party);
185                var partyContactMechanismes = entities.stream().map(PartyContactMechanismObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
186
187                return new CountedObjects<>(objectLimiter, partyContactMechanismes);
188            }
189//        } else {
190//            return Connections.emptyConnection();
191//        }
192    }
193
194    @GraphQLField
195    @GraphQLDescription("party contact mechanism purpose")
196    public PartyContactMechanismPurposeObject getPartyContactMechanismPurpose(final DataFetchingEnvironment env,
197            @GraphQLName("contactMechanismPurposeName") @GraphQLNonNull final String contactMechanismPurposeName) {
198        var commandForm = ContactFormFactory.getGetContactMechanismPurposeForm();
199
200        commandForm.setContactMechanismPurposeName(contactMechanismPurposeName);
201
202        var contactMechanismPurpose = CDI.current().select(GetContactMechanismPurposeCommand.class).get().getEntityForGraphQl(getUserVisitPK(env), commandForm);
203        if(contactMechanismPurpose != null) {
204            var contactControl = Session.getModelController(ContactControl.class);
205            var partyContactMechanismPurpose = contactControl.getDefaultPartyContactMechanismPurpose(party, contactMechanismPurpose);
206
207            return partyContactMechanismPurpose == null ? null : new PartyContactMechanismPurposeObject(partyContactMechanismPurpose);
208        } else {
209            return null;
210        }
211    }
212
213    @GraphQLField
214    @GraphQLDescription("subscriptions")
215    @GraphQLNonNull
216    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
217    public CountingPaginatedData<SubscriptionObject> getSubscriptions(final DataFetchingEnvironment env) {
218        if(SubscriptionSecurityUtils.getHasSubscriptionsAccess(env)) {
219            var subscriptionControl = Session.getModelController(SubscriptionControl.class);
220            var totalCount = subscriptionControl.countSubscriptionsByParty(party);
221
222            try(var objectLimiter = new ObjectLimiter(env, SubscriptionConstants.COMPONENT_VENDOR_NAME, SubscriptionConstants.ENTITY_TYPE_NAME, totalCount)) {
223                var entities = subscriptionControl.getSubscriptionsByParty(party);
224                var subscriptions = entities.stream().map(SubscriptionObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
225
226                return new CountedObjects<>(objectLimiter, subscriptions);
227            }
228        } else {
229            return Connections.emptyConnection();
230        }
231    }
232
233    @GraphQLField
234    @GraphQLDescription("party contact lists")
235    @GraphQLNonNull
236    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
237    public CountingPaginatedData<PartyContactListObject> getPartyContactLists(final DataFetchingEnvironment env) {
238        if(ContactListSecurityUtils.getHasPartyContactListsAccess(env)) {
239            var contactListControl = Session.getModelController(ContactListControl.class);
240            var totalCount = contactListControl.countPartyContactListsByParty(party);
241
242            try(var objectLimiter = new ObjectLimiter(env, PartyContactListConstants.COMPONENT_VENDOR_NAME, PartyContactListConstants.ENTITY_TYPE_NAME, totalCount)) {
243                var entities = contactListControl.getPartyContactListsByParty(party);
244                var partyContactLists = entities.stream().map(PartyContactListObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
245
246                return new CountedObjects<>(objectLimiter, partyContactLists);
247            }
248        } else {
249            return Connections.emptyConnection();
250        }
251    }
252
253}