1/*!
2  @header FTDictionaryServiceLoader
3  @abstract Module of FT
4
5  @availability OS X, GNUstep
6  @copyright 2004, 2005, 2006 Free Software Foundation, Inc.
7
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  Lesser General Public License for more details.
17
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
21
22  <pre>
23  -------------------------------------------------------------------------
24  Modification history
25
26  21.09.05 ola     initial version
27  16.07.06 ola     new implementation
28  23.08.06 ola     license changed
29  -------------------------------------------------------------------------
30  </pre>
31*/
32
33#include <FT/FTDictionaryServiceStorageException.h>
34#include <FT/FTDictionaryServiceLoader.h>
35#include <FT/FTDictionaryService.h>
36#include <FT/FTVersionImpl.h>
37#include <FT/FTLogging.h>
38#include "FTDictionaryServiceForGraphImpl.h"
39#include <FTNotifications.h>
40
41#define __VERSION_MAJOR 0
42#define __VERSION_MINOR 2
43#define __VERSION_BUILD 1
44#define __VERSION_STATE FT_VERSION_SNAPSHOT
45
46#define __FTDictionaryServiceId @"FTDictionaryService"
47#define __FTDictionaryServiceDataDirectory @"FTDictionaryServiceData"
48#define __FTDictionaryIndexDB @"DictionaryIndex.db"
49
50@implementation FTDictionaryServiceLoader
51
52- init {
53  self = [super init];
54  self->serviceVersion = [[FTVersionImpl alloc]
55    initWithMajor: __VERSION_MAJOR
56    withMinor: __VERSION_MINOR
57    withBuild: __VERSION_BUILD
58    asState: __VERSION_STATE];
59
60  self->serviceAvailability = [[FTDictionaryServiceAvailability alloc] init];
61  self->serviceEnvironment = nil;
62
63  self->graphToServiceImpl = nil;
64  self->generalLock = [[NSLock alloc] init];
65
66  return self;
67}
68
69
70- (void) dealloc {
71  [self->generalLock release];
72
73  if( nil != self->serviceVersion ) {
74    [self->serviceVersion release];
75  }
76
77  if( nil != self->serviceAvailability ) {
78    [self->serviceAvailability release];
79  }
80
81  if( nil != self->serviceEnvironment ) {
82    [self->serviceEnvironment release];
83  }
84
85
86  [self->databaseNameScheme release];
87
88  [super dealloc];
89}
90
91
92- (NSString *) databaseNameScheme {
93  return self->databaseNameScheme;
94}
95
96
97- onGraphClosed: (NSNotification *) notification {
98  FTDictionaryServiceForGraphImpl *serviceImpl;
99  FTGraphImpl *graphImpl;
100  unsigned cnt;
101
102  graphImpl = [notification object];
103
104  if( [[FTLogging coreLog] isTraceEnabled] ) {
105    [[FTLogging coreLog]
106      trace: @"FTDictionaryServiceLoader::onGraphClosed"];
107  }
108
109  serviceImpl = [[self->graphToServiceImpl
110    objectForKey: [graphImpl graphId]
111    incrementRefCounter: NO] retain];
112
113  NS_DURING
114
115    cnt =  [self->graphToServiceImpl
116        referenceCounterOfObjectForKey: [graphImpl graphId]] ;
117    if( nil != serviceImpl ) {
118      [self->graphToServiceImpl
119        decrementRefCounterForKey: [graphImpl graphId]];
120      cnt =  [self->graphToServiceImpl
121        referenceCounterOfObjectForKey: [graphImpl graphId]] ;
122      if(0 == cnt ) {
123        [[NSNotificationCenter defaultCenter]
124          removeObserver: self];
125        [serviceImpl close];
126      }
127    } else {
128      [[NSNotificationCenter defaultCenter]
129        removeObserver: self];
130    }
131  NS_HANDLER
132    [serviceImpl release];
133    [localException raise];
134  NS_ENDHANDLER
135
136  [serviceImpl release];
137  return self;
138}
139
140
141- (id <FTServiceAvailability>) serviceAvailability {
142  return self->serviceAvailability;
143}
144
145
146- (id <FTService>) serviceForGraph: (id <FTGraph>) aGraph {
147
148  return nil;
149}
150
151
152- (id <FTService>) serviceForNode: (id <FTNode>) aNode
153  ofGraph: (id <FTGraph>) aGraph {
154  FTDictionaryServiceForGraphImpl *serviceImpl;
155
156  [self->generalLock lock];
157
158  serviceImpl = [self->graphToServiceImpl
159    objectForKey: [aGraph graphId]
160    incrementRefCounter: NO];
161
162  if( nil == serviceImpl ) {
163    NS_DURING
164      serviceImpl = [[FTDictionaryServiceForGraphImpl alloc]
165        initForGraph: aGraph
166        serviceLoader: self];
167      [self->graphToServiceImpl
168        addObject: serviceImpl
169        forKey: [aGraph graphId]];
170
171      [[NSNotificationCenter defaultCenter]
172        addObserver: self
173        selector: @selector(onGraphClosed:)
174        name: FTNotification_Graph_afterClosed
175        object: nil];
176    NS_HANDLER
177      [self->generalLock unlock];
178      [[FTLogging coreLog]
179        error: @"FTDictionaryServiceLoader::serviceForNode: Unable to create "\
180          "new dictionary service instance due to exception: %@",
181          localException];
182      [localException raise];
183    NS_ENDHANDLER
184  }
185
186  [self->generalLock unlock];
187
188  return [serviceImpl serviceForNode: aNode];
189}
190
191
192- (NSString *) serviceId {
193  return __FTDictionaryServiceId;
194}
195
196
197- (id <FTVersion>) serviceVersion {
198  return self->serviceVersion;
199}
200
201
202- setDatabaseNameSchema: (NSString *) aDatabaseName {
203  [aDatabaseName retain];
204
205  [self->databaseNameScheme release];
206  self->databaseNameScheme = aDatabaseName;
207
208  return self;
209
210}
211
212
213- setEnvironment: (id <FTServiceEnvironment>) aServiceEnvironment {
214  if( nil != self->serviceEnvironment ) {
215    [self->serviceEnvironment release];
216  }
217
218  self->serviceEnvironment = [aServiceEnvironment retain];
219
220  return self;
221}
222
223
224- switchToMode: (ft_serviceMode_t) aServiceMode {
225    id <ECIterator> allKeys;
226    id <FTDictionaryService> currentService;
227    id graphId;
228
229  switch( aServiceMode ) {
230    case FT_SERVICE_MODE_ONLINE:
231      [self->graphToServiceImpl release];
232      self->graphToServiceImpl = [[ECCache alloc] init];
233      break;
234    case FT_SERVICE_MODE_SHUTDOWN:
235      /* close all dictionaries: */
236      allKeys = [self->graphToServiceImpl allKeys];
237      while( [allKeys hasNext] ) {
238        graphId = [allKeys next];
239        currentService = [self->graphToServiceImpl
240          objectForKey: [allKeys next]
241          incrementRefCounter: NO];
242        NS_DURING
243          [currentService close];
244        NS_HANDLER
245          [[FTLogging coreLog]
246            error: @"FTDictionaryServiceLoader::switchToMode: Unable to close "\
247              "dictionary identified by: %@", graphId];
248        NS_ENDHANDLER
249      }
250
251      [self->graphToServiceImpl release];
252      self->graphToServiceImpl = nil;
253      break;
254    default:
255      [[FTLogging coreLog]
256        error: @"FTDictionaryServiceLoader::switchToMode: "\
257         "Unknown mode=%u given. Ignoring it.", (unsigned) aServiceMode];
258
259  }
260  return self;
261}
262
263
264@end
265
266
267@implementation FTDictionaryServiceAvailability
268
269- (BOOL) availableForGraph: (id <FTGraph>) aGraph {
270  return nil != aGraph;
271}
272
273
274- (BOOL) availableForNodesOfGraph: (id <FTGraph>) aGraph {
275  return nil != aGraph;
276}
277
278
279- (BOOL) availableForNode: (id <FTNode>) aNode ofGraph: (id <FTGraph>) aGraph {
280  return ((nil != aNode) && (nil != aGraph));
281}
282@end
283
284