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.geo.server.graphql;
018
019import com.echothree.model.control.geo.common.GeoCodeTypes;
020import com.echothree.model.control.geo.server.control.GeoControl;
021import com.echothree.model.control.graphql.server.graphql.BaseEntityInstanceObject;
022import com.echothree.model.control.graphql.server.graphql.count.Connections;
023import com.echothree.model.control.graphql.server.graphql.count.CountedObjects;
024import com.echothree.model.control.graphql.server.graphql.count.CountingDataConnectionFetcher;
025import com.echothree.model.control.graphql.server.graphql.count.CountingPaginatedData;
026import com.echothree.model.control.graphql.server.util.BaseGraphQl;
027import com.echothree.model.control.graphql.server.util.count.ObjectLimiter;
028import com.echothree.model.control.user.server.control.UserControl;
029import com.echothree.model.data.geo.common.GeoCodeAliasConstants;
030import com.echothree.model.data.geo.common.GeoCodeCurrencyConstants;
031import com.echothree.model.data.geo.common.GeoCodeDateTimeFormatConstants;
032import com.echothree.model.data.geo.common.GeoCodeLanguageConstants;
033import com.echothree.model.data.geo.common.GeoCodeRelationshipConstants;
034import com.echothree.model.data.geo.common.GeoCodeTimeZoneConstants;
035import com.echothree.model.data.geo.server.entity.GeoCode;
036import com.echothree.model.data.geo.server.entity.GeoCodeDetail;
037import com.echothree.util.server.persistence.Session;
038import graphql.annotations.annotationTypes.GraphQLDescription;
039import graphql.annotations.annotationTypes.GraphQLField;
040import graphql.annotations.annotationTypes.GraphQLName;
041import graphql.annotations.annotationTypes.GraphQLNonNull;
042import graphql.annotations.connection.GraphQLConnection;
043import graphql.schema.DataFetchingEnvironment;
044import java.util.ArrayList;
045import java.util.stream.Collectors;
046
047@GraphQLDescription("geo code object")
048@GraphQLName("GeoCode")
049public class GeoCodeObject
050        extends BaseEntityInstanceObject {
051
052    private final GeoCode geoCode; // Always Present
053
054    public GeoCodeObject(GeoCode geoCode) {
055        super(geoCode.getPrimaryKey());
056
057        this.geoCode = geoCode;
058    }
059
060    private GeoCodeDetail geoCodeDetail; // Optional, use getGeoCodeDetail()
061
062    private GeoCodeDetail getGeoCodeDetail() {
063        if(geoCodeDetail == null) {
064            geoCodeDetail = geoCode.getLastDetail();
065        }
066
067        return geoCodeDetail;
068    }
069
070    @GraphQLField
071    @GraphQLDescription("geo code type name")
072    @GraphQLNonNull
073    public String getGeoCodeName() {
074        return getGeoCodeDetail().getGeoCodeName();
075    }
076
077    @GraphQLField
078    @GraphQLDescription("geo code type")
079    public GeoCodeTypeObject getGeoCodeType(final DataFetchingEnvironment env) {
080        return GeoSecurityUtils.getHasGeoCodeTypeAccess(env) ? new GeoCodeTypeObject(getGeoCodeDetail().getGeoCodeType()) : null;
081    }
082
083    @GraphQLField
084    @GraphQLDescription("geo code scope")
085    public GeoCodeScopeObject getGeoCodeScope(final DataFetchingEnvironment env) {
086        return GeoSecurityUtils.getHasGeoCodeScopeAccess(env) ? new GeoCodeScopeObject(getGeoCodeDetail().getGeoCodeScope()) : null;
087    }
088
089    @GraphQLField
090    @GraphQLDescription("is default")
091    @GraphQLNonNull
092    public boolean getIsDefault() {
093        return getGeoCodeDetail().getIsDefault();
094    }
095
096    @GraphQLField
097    @GraphQLDescription("sort order")
098    @GraphQLNonNull
099    public int getSortOrder() {
100        return getGeoCodeDetail().getSortOrder();
101    }
102
103    @GraphQLField
104    @GraphQLDescription("description")
105    @GraphQLNonNull
106    public String getDescription(final DataFetchingEnvironment env) {
107        var geoControl = Session.getModelController(GeoControl.class);
108        var userControl = Session.getModelController(UserControl.class);
109
110        return geoControl.getBestGeoCodeDescription(geoCode, userControl.getPreferredLanguageFromUserVisit(BaseGraphQl.getUserVisit(env)));
111    }
112
113    private GeoCodeTypes geoCodeTypeEnum = null; // Optional, use getGeoCodeTypeEnum()
114
115    protected GeoCodeTypes getGeoCodeTypeEnum() {
116        if(geoCodeTypeEnum == null) {
117            geoCodeTypeEnum = GeoCodeTypes.valueOf(getGeoCodeDetail().getGeoCodeType().getLastDetail().getGeoCodeTypeName());
118        }
119
120        return geoCodeTypeEnum;
121    }
122
123    @GraphQLField
124    @GraphQLDescription("geo code")
125    public GeoCodeInterface getGeoCode(final DataFetchingEnvironment env) {
126        var geoControl = Session.getModelController(GeoControl.class);
127
128        return switch(getGeoCodeTypeEnum()) {
129            case ROOT -> null;
130            case COUNTRY -> new GeoCodeCountryObject(geoControl.getGeoCodeCountry(geoCode));
131            case STATE -> null;
132            case COUNTY -> null;
133            case CITY -> null;
134            case ZIP_CODE -> null;
135        };
136    }
137
138    @GraphQLField
139    @GraphQLDescription("geo code aliases")
140    @GraphQLNonNull
141    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
142    public CountingPaginatedData<GeoCodeAliasObject> getGeoCodeAliases(final DataFetchingEnvironment env) {
143        if(GeoSecurityUtils.getHasGeoCodeAliasesAccess(env)) {
144            var geoControl = Session.getModelController(GeoControl.class);
145            var totalCount = geoControl.countGeoCodeAliasesByGeoCode(geoCode);
146
147            try(var objectLimiter = new ObjectLimiter(env, GeoCodeAliasConstants.COMPONENT_VENDOR_NAME, GeoCodeAliasConstants.ENTITY_TYPE_NAME, totalCount)) {
148                var entities = geoControl.getGeoCodeAliasesByGeoCode(geoCode);
149                var items = entities.stream().map(GeoCodeAliasObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
150
151                return new CountedObjects<>(objectLimiter, items);
152            }
153        } else {
154            return Connections.emptyConnection();
155        }
156    }
157
158    @GraphQLField
159    @GraphQLDescription("from geo code relationships")
160    @GraphQLNonNull
161    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
162    public CountingPaginatedData<GeoCodeRelationshipObject> getFromGeoCodeRelationships(final DataFetchingEnvironment env) {
163        var geoControl = Session.getModelController(GeoControl.class);
164        var totalCount = geoControl.countGeoCodeRelationshipsByFromGeoCode(geoCode);
165
166        try(var objectLimiter = new ObjectLimiter(env, GeoCodeRelationshipConstants.COMPONENT_VENDOR_NAME, GeoCodeRelationshipConstants.ENTITY_TYPE_NAME, totalCount)) {
167            var entities = geoControl.getGeoCodeRelationshipsByFromGeoCode(geoCode);
168            var items = entities.stream().map(GeoCodeRelationshipObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
169
170            return new CountedObjects<>(objectLimiter, items);
171        }
172    }
173
174    @GraphQLField
175    @GraphQLDescription("to geo code relationships")
176    @GraphQLNonNull
177    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
178    public CountingPaginatedData<GeoCodeRelationshipObject> getToGeoCodeRelationships(final DataFetchingEnvironment env) {
179        var geoControl = Session.getModelController(GeoControl.class);
180        var totalCount = geoControl.countGeoCodeRelationshipsByToGeoCode(geoCode);
181
182        try(var objectLimiter = new ObjectLimiter(env, GeoCodeRelationshipConstants.COMPONENT_VENDOR_NAME, GeoCodeRelationshipConstants.ENTITY_TYPE_NAME, totalCount)) {
183            var entities = geoControl.getGeoCodeRelationshipsByToGeoCode(geoCode);
184            var items = entities.stream().map(GeoCodeRelationshipObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
185
186            return new CountedObjects<>(objectLimiter, items);
187        }
188    }
189
190    @GraphQLField
191    @GraphQLDescription("geo code languages")
192    @GraphQLNonNull
193    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
194    public CountingPaginatedData<GeoCodeLanguageObject> getGeoCodeLanguages(final DataFetchingEnvironment env) {
195        if(GeoSecurityUtils.getHasGeoCodeLanguagesAccess(env)) {
196            var geoControl = Session.getModelController(GeoControl.class);
197            var totalCount = geoControl.countGeoCodeLanguagesByGeoCode(geoCode);
198
199            try(var objectLimiter = new ObjectLimiter(env, GeoCodeLanguageConstants.COMPONENT_VENDOR_NAME, GeoCodeLanguageConstants.ENTITY_TYPE_NAME, totalCount)) {
200                var entities = geoControl.getGeoCodeLanguagesByGeoCode(geoCode);
201                var items = entities.stream().map(GeoCodeLanguageObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
202
203                return new CountedObjects<>(objectLimiter, items);
204            }
205        } else {
206            return Connections.emptyConnection();
207        }
208    }
209
210    @GraphQLField
211    @GraphQLDescription("geo code currencies")
212    @GraphQLNonNull
213    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
214    public CountingPaginatedData<GeoCodeCurrencyObject> getGeoCodeCurrencies(final DataFetchingEnvironment env) {
215        if(GeoSecurityUtils.getHasGeoCodeCurrenciesAccess(env)) {
216            var geoControl = Session.getModelController(GeoControl.class);
217            var totalCount = geoControl.countGeoCodeCurrenciesByGeoCode(geoCode);
218
219            try(var objectLimiter = new ObjectLimiter(env, GeoCodeCurrencyConstants.COMPONENT_VENDOR_NAME, GeoCodeCurrencyConstants.ENTITY_TYPE_NAME, totalCount)) {
220                var entities = geoControl.getGeoCodeCurrenciesByGeoCode(geoCode);
221                var items = entities.stream().map(GeoCodeCurrencyObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
222
223                return new CountedObjects<>(objectLimiter, items);
224            }
225        } else {
226            return Connections.emptyConnection();
227        }
228    }
229
230    @GraphQLField
231    @GraphQLDescription("geo code time zones")
232    @GraphQLNonNull
233    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
234    public CountingPaginatedData<GeoCodeTimeZoneObject> getGeoCodeTimeZones(final DataFetchingEnvironment env) {
235        if(GeoSecurityUtils.getHasGeoCodeTimeZonesAccess(env)) {
236            var geoControl = Session.getModelController(GeoControl.class);
237            var totalCount = geoControl.countGeoCodeTimeZonesByGeoCode(geoCode);
238
239            try(var objectLimiter = new ObjectLimiter(env, GeoCodeTimeZoneConstants.COMPONENT_VENDOR_NAME, GeoCodeTimeZoneConstants.ENTITY_TYPE_NAME, totalCount)) {
240                var entities = geoControl.getGeoCodeTimeZonesByGeoCode(geoCode);
241                var items = entities.stream().map(GeoCodeTimeZoneObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
242
243                return new CountedObjects<>(objectLimiter, items);
244            }
245        } else {
246            return Connections.emptyConnection();
247        }
248    }
249
250    @GraphQLField
251    @GraphQLDescription("geo code date time formats")
252    @GraphQLNonNull
253    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
254    public CountingPaginatedData<GeoCodeDateTimeFormatObject> getGeoCodeDateTimeFormats(final DataFetchingEnvironment env) {
255        if(GeoSecurityUtils.getHasGeoCodeDateTimeFormatsAccess(env)) {
256            var geoControl = Session.getModelController(GeoControl.class);
257            var totalCount = geoControl.countGeoCodeDateTimeFormatsByGeoCode(geoCode);
258
259            try(var objectLimiter = new ObjectLimiter(env, GeoCodeDateTimeFormatConstants.COMPONENT_VENDOR_NAME, GeoCodeDateTimeFormatConstants.ENTITY_TYPE_NAME, totalCount)) {
260                var entities = geoControl.getGeoCodeDateTimeFormatsByGeoCode(geoCode);
261                var items = entities.stream().map(GeoCodeDateTimeFormatObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
262
263                return new CountedObjects<>(objectLimiter, items);
264            }
265        } else {
266            return Connections.emptyConnection();
267        }
268    }
269
270}