1/*---------------------------------------------------------------------------*
2 *  NametagsImpl.c  *
3 *                                                                           *
4 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20#include "ESR_Session.h"
21#include "HashMap.h"
22#include "LCHAR.h"
23#include "plog.h"
24#include "pmemory.h"
25#include "SR_NametagImpl.h"
26#include "SR_NametagsImpl.h"
27
28#define MTAG NULL
29
30ESR_ReturnCode SR_NametagsCreate(SR_Nametags** self)
31{
32  SR_NametagsImpl* impl;
33  ESR_ReturnCode rc;
34
35  if (self == NULL)
36  {
37    PLogError(L("ESR_INVALID_ARGUMENT"));
38    return ESR_INVALID_ARGUMENT;
39  }
40  impl = NEW(SR_NametagsImpl, MTAG);
41  if (impl == NULL)
42  {
43    PLogError(L("ESR_OUT_OF_MEMORY"));
44    return ESR_OUT_OF_MEMORY;
45  }
46
47  impl->Interface.load = &SR_NametagsLoadImpl;
48  impl->Interface.save = &SR_NametagsSaveImpl;
49  impl->Interface.add = &SR_NametagsAddImpl;
50  impl->Interface.remove = &SR_NametagsRemoveImpl;
51  impl->Interface.getSize = &SR_NametagsGetSizeImpl;
52  impl->Interface.get = &SR_NametagsGetImpl;
53  impl->Interface.getAtIndex = &SR_NametagsGetAtIndexImpl;
54  impl->Interface.contains = &SR_NametagsContainsImpl;
55  impl->Interface.destroy = &SR_NametagsDestroyImpl;
56  impl->value = NULL;
57  impl->eventLog = NULL;
58
59  CHKLOG(rc, HashMapCreate(&impl->value));
60  CHKLOG(rc, ESR_SessionGetSize_t(L("SREC.Recognizer.osi_log_level"), &impl->logLevel));
61  if (impl->logLevel > 0)
62    CHKLOG(rc, ESR_SessionGetProperty(L("eventlog"), (void **)&impl->eventLog, TYPES_SR_EVENTLOG));
63  CHKLOG(rc, SR_EventLogTokenPointer_BASIC(impl->eventLog, impl->logLevel, L("pointer"), self));
64  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsCreate")));
65  *self = (SR_Nametags*) impl;
66  return ESR_SUCCESS;
67CLEANUP:
68  impl->Interface.destroy(&impl->Interface);
69  return rc;
70}
71
72ESR_ReturnCode SR_NametagsLoadImpl(SR_Nametags* self, const LCHAR* filename)
73{
74  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
75  ESR_ReturnCode rc;
76  PFile* file = NULL;
77  LCHAR line[256];
78  LCHAR* result = NULL;
79  LCHAR* id;
80  LCHAR* value;
81  SR_Nametag* newNametag = NULL;
82  SR_Nametag* oldNametag;
83  HashMap* nametags = impl->value;
84  size_t size, len, i;
85  LCHAR devicePath[P_PATH_MAX];
86  LCHAR number[MAX_UINT_DIGITS+1];
87#define NAMETAGID_LENGTH 20
88  /* strlen("token\0") == 6 */
89#define TOKEN_LENGTH 6 + NAMETAGID_LENGTH
90  LCHAR tokenName[TOKEN_LENGTH];
91
92  if (filename == NULL)
93  {
94    rc = ESR_INVALID_STATE;
95    PLogError(ESR_rc2str(rc));
96    goto CLEANUP;
97  }
98  size = P_PATH_MAX;
99  CHKLOG(rc, ESR_SessionGetLCHAR(L("cmdline.nametagPath"), devicePath, &size));
100  /* check if the filename has the path */
101  if (LSTRNCMP(filename, devicePath, LSTRLEN(devicePath)) != 0)
102    LSTRCAT(devicePath, filename);
103  else
104    LSTRCPY(devicePath, filename);
105  file = pfopen ( devicePath, L("r"));
106/*  CHKLOG(rc, PFileSystemCreatePFile(devicePath, ESR_TRUE, &file));
107  CHKLOG(rc, file->open(file, L("r")));*/
108
109  if ( file == NULL )
110    goto CLEANUP;
111
112  /* Flush collection */
113  CHKLOG(rc, nametags->getSize(nametags, &size));
114  for (i = 0; i < size; ++i)
115  {
116    CHKLOG(rc, nametags->getValueAtIndex(nametags, 0, (void **)&oldNametag));
117    CHKLOG(rc, nametags->removeAtIndex(nametags, 0));
118    CHKLOG(rc, oldNametag->destroy(oldNametag));
119  }
120  len = MAX_UINT_DIGITS + 1;
121  CHKLOG(rc, lultostr(size, number, &len, 10));
122  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("removeCount"), number));
123
124  while (ESR_TRUE)
125  {
126    result = pfgets ( line, 256, file );
127    if (result == NULL)
128      break;
129    if (LSTRLEN(line) == 255)
130    {
131      rc = ESR_BUFFER_OVERFLOW;
132      PLogError(ESR_rc2str(rc));
133      goto CLEANUP;
134    }
135    lstrtrim(line);
136
137    /* Get the Nametag ID */
138    id = line;
139
140    /* Find next whitespace */
141    for (value = id + 1; *value != L('\0') && !LISSPACE(*value); ++value);
142    if (*value == L('\0'))
143    {
144      rc = ESR_INVALID_STATE;
145      PLogError(L("%s: Cannot find end of Nametag id"), ESR_rc2str(rc));
146      goto CLEANUP;
147    }
148    /* Delimit end of nametag ID */
149    *value = L('\0');
150
151    /* Find next non-whitespace */
152    for (++value; *value != L('\0') && LISSPACE(*value); ++value);
153    if (*value == L('\0'))
154    {
155      rc = ESR_INVALID_STATE;
156      PLogError(L("%s: Cannot find Nametag value"), ESR_rc2str(rc));
157      goto CLEANUP;
158    }
159
160    /* We now have both the Nametag ID and value */
161	len = (LSTRLEN(value)+1) * sizeof(LCHAR) ;
162    CHKLOG(rc, SR_NametagCreateFromValue(id, (const char*)value, len, &newNametag));
163    /* Add Nametag to collection */
164    CHKLOG(rc, impl->value->put(impl->value, id, newNametag));
165
166    if (LSTRLEN(id) > NAMETAGID_LENGTH)
167    {
168      rc = ESR_BUFFER_OVERFLOW;
169      PLogError(ESR_rc2str(rc));
170      goto CLEANUP;
171    }
172    psprintf(tokenName, L("nametag[%s]"), id);
173    CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, tokenName, value));
174    newNametag = NULL;
175  }
176  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("filename"), filename));
177  CHKLOG(rc, nametags->getSize(nametags, &size));
178  len = MAX_UINT_DIGITS + 1;
179  CHKLOG(rc, lultostr(size, number, &len, 10));
180  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("addCount"), number));
181  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsLoad")));
182  pfclose (file);
183  return ESR_SUCCESS;
184CLEANUP:
185  if (file != NULL)
186    pfclose (file);
187  if (newNametag != NULL)
188    newNametag->destroy(newNametag);
189  return rc;
190}
191
192ESR_ReturnCode SR_NametagsSaveImpl(SR_Nametags* self, const LCHAR* filename)
193{
194  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
195  ESR_ReturnCode rc;
196  PFile* file = NULL;
197  size_t size, i;
198  HashMap* nametags = impl->value;
199  SR_NametagImpl* nametag;
200  LCHAR* id;
201  size_t len;
202  LCHAR devicePath[P_PATH_MAX];
203#define NAMETAG_LENGTH 200
204  LCHAR nametagBuffer[NAMETAG_LENGTH];
205  LCHAR number[MAX_UINT_DIGITS+1];
206#define NAMETAGID_LENGTH 20
207  /* "token\0" == 6 */
208#define TOKEN_LENGTH 6 + NAMETAGID_LENGTH
209  LCHAR tokenName[TOKEN_LENGTH];
210  size_t num_written;
211
212  if (filename == NULL)
213  {
214    rc = ESR_INVALID_STATE;
215    PLogError(ESR_rc2str(rc));
216    goto CLEANUP;
217  }
218  size = P_PATH_MAX;
219  CHKLOG(rc, ESR_SessionGetLCHAR(L("cmdline.nametagPath"), devicePath, &size));
220
221  if (LSTRNCMP(filename, devicePath, LSTRLEN(devicePath)) != 0)
222    LSTRCAT(devicePath, filename);
223  else
224    LSTRCPY(devicePath, filename);
225
226  file = pfopen ( devicePath, L("w"));
227/*  CHKLOG(rc, PFileSystemCreatePFile(devicePath, ESR_TRUE, &file));
228  CHKLOG(rc, file->open(file, L("w")));*/
229  CHKLOG(rc, nametags->getSize(nametags, &size));
230
231  if ( file == NULL )
232    goto CLEANUP;
233
234  for (i = 0; i < size; ++i)
235  {
236    CHKLOG(rc, nametags->getValueAtIndex(nametags, i, (void **)&nametag));
237
238    CHKLOG(rc, nametag->Interface.getID(&nametag->Interface, &id));
239
240    if (LSTRLEN(id) + 1 + LSTRLEN(nametag->value) + 2 >= NAMETAG_LENGTH)
241    {
242      rc = ESR_BUFFER_OVERFLOW;
243      PLogError(ESR_rc2str(rc));
244      goto CLEANUP;
245    }
246    psprintf(nametagBuffer, L("%s %s\n"), id, nametag->value);
247    len = LSTRLEN(nametagBuffer);
248/*    CHKLOG(rc, file->write(file, nametagBuffer, sizeof(LCHAR), &len));*/
249    num_written = pfwrite ( nametagBuffer, sizeof ( LCHAR ), len, file );
250
251    if ( num_written != len )
252        goto CLEANUP;
253
254    if (LSTRLEN(id) > NAMETAGID_LENGTH)
255    {
256      rc = ESR_BUFFER_OVERFLOW;
257      PLogError(ESR_rc2str(rc));
258      goto CLEANUP;
259    }
260    psprintf(tokenName, L("nametag[%s]"), id);
261    CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, tokenName, nametag->value));
262  }
263  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("filename"), filename));
264  len = MAX_UINT_DIGITS + 1;
265  CHKLOG(rc, lultostr(size, (LCHAR*) &number, &len, 10));
266  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("saveCount"), number));
267  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsSave")));
268  pfclose (file);
269  return ESR_SUCCESS;
270CLEANUP:
271  if (file != NULL)
272    pfclose (file);
273  return rc;
274}
275
276ESR_ReturnCode SR_NametagsAddImpl(SR_Nametags* self, SR_Nametag* nametag)
277{
278  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
279  HashMap* nametags = impl->value;
280  LCHAR* id;
281  ESR_BOOL exists;
282  ESR_ReturnCode rc;
283
284  CHKLOG(rc, nametag->getID(nametag, &id));
285  CHKLOG(rc, nametags->containsKey(nametags, id, &exists));
286  if (exists)
287  {
288    CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("id"), id));
289    rc = ESR_IDENTIFIER_COLLISION;
290    CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("rc"), ESR_rc2str(rc)));
291    CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsAdd")));
292    rc = ESR_IDENTIFIER_COLLISION;
293    PLogError(ESR_rc2str(rc));
294    goto CLEANUP;
295  }
296  CHKLOG(rc, nametags->put(nametags, id, nametag));
297
298  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("id"), id));
299  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsAdd")));
300  return ESR_SUCCESS;
301CLEANUP:
302  return rc;
303}
304
305ESR_ReturnCode SR_NametagsRemoveImpl(SR_Nametags* self, const LCHAR* id)
306{
307  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
308  HashMap* nametags = impl->value;
309  ESR_ReturnCode rc;
310
311  CHKLOG(rc, nametags->remove(nametags, id));
312
313  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("id"), id));
314  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsRemove")));
315  return ESR_SUCCESS;
316CLEANUP:
317  return rc;
318}
319
320ESR_ReturnCode SR_NametagsGetSizeImpl(SR_Nametags* self, size_t* result)
321{
322  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
323  HashMap* nametags = impl->value;
324  ESR_ReturnCode rc;
325
326  CHKLOG(rc, nametags->getSize(nametags, result));
327  return ESR_SUCCESS;
328CLEANUP:
329  return rc;
330}
331
332ESR_ReturnCode SR_NametagsGetImpl(SR_Nametags* self, const LCHAR* id, SR_Nametag** nametag)
333{
334  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
335  HashMap* nametags = impl->value;
336  ESR_ReturnCode rc;
337
338  CHKLOG(rc, nametags->get(nametags, id, (void **)nametag));
339
340  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("id"), id));
341  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsGet")));
342  return ESR_SUCCESS;
343CLEANUP:
344  return rc;
345}
346
347ESR_ReturnCode SR_NametagsGetAtIndexImpl(SR_Nametags* self, size_t index, SR_Nametag** nametag)
348{
349  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
350  HashMap* nametags = impl->value;
351  LCHAR* id;
352  ESR_ReturnCode rc;
353
354  CHKLOG(rc, nametags->getValueAtIndex(nametags, index, (void **)nametag));
355
356  CHKLOG(rc, (*nametag)->getID(*nametag, &id));
357  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("id"), id));
358  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsGetAtIndex")));
359  return ESR_SUCCESS;
360CLEANUP:
361  return rc;
362}
363
364ESR_ReturnCode SR_NametagsContainsImpl(SR_Nametags* self, const LCHAR* id, ESR_BOOL* result)
365{
366  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
367  HashMap* nametags = impl->value;
368  ESR_ReturnCode rc;
369
370  CHKLOG(rc, nametags->containsKey(nametags, id, result));
371  return ESR_SUCCESS;
372CLEANUP:
373  return rc;
374}
375
376ESR_ReturnCode SR_NametagsDestroyImpl(SR_Nametags* self)
377{
378  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
379  LCHAR number[MAX_UINT_DIGITS+1];
380  ESR_ReturnCode rc;
381
382  if (impl->value != NULL)
383  {
384    size_t size, i, len;
385    HashMap* list = impl->value;
386    SR_Nametag* nametag;
387
388    CHKLOG(rc, list->getSize(list, &size));
389    for (i = 0; i < size; ++i)
390    {
391      CHKLOG(rc, list->getValueAtIndex(list, 0, (void **)&nametag));
392      CHKLOG(rc, list->removeAtIndex(list, 0));
393      CHKLOG(rc, nametag->destroy(nametag));
394    }
395
396    len = MAX_UINT_DIGITS + 1;
397    CHKLOG(rc, lultostr(size, (LCHAR*) &number, &len, 10));
398    CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("removeCount"), number));
399    CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsDestroy")));
400    list->destroy(list);
401    impl->value = NULL;
402  }
403  CHKLOG(rc, SR_EventLogTokenPointer_BASIC(impl->eventLog, impl->logLevel, L("pointer"), self));
404  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsDestroy")));
405  impl->eventLog = NULL;
406  FREE(self);
407  return ESR_SUCCESS;
408CLEANUP:
409  return rc;
410}
411