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}