Developer Area

root/apps/iphone/my.tel/trunk/Classes/KeywordViewController.m @ 622

Revision 622, 13.5 kB (checked in by henri, 5 years ago)

First commit of the complete refactoring of keyword management.

Line 
1//
2//  KeywordViewController.m
3//  My.tel
4//
5//  Created by Henri Asseily on 11/18/08.
6//  Copyright 2008 Telnic Ltd.. All rights reserved.
7//
8
9// TODO: Implement new/edit
10// TODO: Implement deletion of records (in edit table mode)
11// TODO: Implement deletion of a record in swipe mode
12
13#import "KeywordViewController.h"
14
15#define kKRowHeight 54.0
16#define kKRowLineHeightIncrease 20.0
17
18@interface KeywordViewController (PrivateMethods)
19- (void)setDidPreload:(BOOL)preload;
20@end;
21
22@implementation KeywordViewController
23
24@synthesize keywordTypesNames;
25@synthesize keywordTypes;
26
27@synthesize keywordsArray;
28@synthesize uiArray;
29
30@synthesize delegate;
31
32#pragma mark -
33#pragma mark Designated initializer
34
35+ (KeywordViewController *)controllerWithDelegate:(id <TelControllerDelegate>)aDelegate preload:(BOOL)preload {
36        KeywordViewController *theC = [[[KeywordViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
37        theC.delegate = aDelegate;
38        theC.keywordsArray = [NSMutableArray arrayWithCapacity:20];
39        theC.uiArray = [NSMutableArray arrayWithCapacity:20];
40        if (preload) {
41                [theC getValidKeywords:FALSE];
42                [theC getKeywords];
43        }
44        [theC setDidPreload:preload];
45        theC.navigationItem.rightBarButtonItem = [theC editButtonItem];
46        return theC;   
47}
48
49- (void)setDidPreload:(BOOL)preload {
50        didPreload = preload;
51}
52
53#pragma mark ------ Standard View Controller Methods
54
55- (void)viewDidLoad {
56    [super viewDidLoad];
57        keywordTableHeight = kKRowHeight;
58        self.title = @"Keywords";
59}
60
61- (void)viewWillAppear:(BOOL)animated {
62        [super viewWillAppear:animated];
63        // Don't get the data if we preloaded
64        if (didPreload) {
65                didPreload = NO;
66        } else {
67                [self getValidKeywords:FALSE];
68                [self getKeywords];
69        }
70}
71
72- (void)dealloc {
73        [keywordTypesNames release];
74        [keywordTypes release];
75    [super dealloc];
76}
77
78#pragma mark ------ TableView Delegate and DataSource Methods
79
80- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
81    return 1;
82}
83
84- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
85        return nil;
86}
87
88- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
89    return [uiArray count];
90}
91
92
93- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
94        // Keyword entry in uiArray:
95        //  {id: 12, field: "pa", value: "my postal address",
96        //              secondaryKeywords: [ {id: 15, field: "a1",
97        //              value: "my street"} ]}
98       
99    static NSString *CellIdentifier = @"KeywordCellIdentifier";
100   
101    KeywordCell *cell = (KeywordCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
102    if (cell == nil) {
103                cell = [[[KeywordCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
104                cell.editingAccessoryType = UITableViewCellAccessoryNone;
105                cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
106    }
107        NSDictionary *uiItem = [[uiArray objectAtIndex:indexPath.row] retain];
108#ifdef DEBUG
109        NSLog(@"UI ITEM IS: %@", uiItem);
110#endif
111        cell.labelPrimaryType.text = [uiItem objectForKey:@"primaryLongName"];
112        if ([[uiItem objectForKey:@"secondaryString"] isEqualToString:@""]) {
113                // No secondaries, put the primary value in the larger secondary field
114                cell.labelPrimaryValue.text = @"";
115                cell.labelSecondaryText.text = [uiItem objectForKey:@"value"];
116        } else {
117                cell.labelPrimaryValue.text = [uiItem objectForKey:@"value"];
118                cell.labelSecondaryText.text = [uiItem objectForKey:@"secondaryString"];
119        }
120        [uiItem release];
121    return cell;
122}
123
124- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
125        [tableView deselectRowAtIndexPath:indexPath animated:NO];
126        KeywordEditController *editC = [KeywordEditController controllerForKeyword:[uiArray objectAtIndex:indexPath.row]];
127        editC.delegate = self;
128        [self.navigationController pushViewController:editC animated:YES];
129}
130
131- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
132   
133        if (editingStyle == UITableViewCellEditingStyleDelete) {
134                if (tableView.editing) {
135                        // delete immediately, do not cache deletion because we can't tell a single row swipe from multiple deletes
136                        [self deleteKeywords:[uiArray objectAtIndex:indexPath.row]];
137                }
138                [uiArray removeObjectAtIndex:indexPath.row];
139                [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
140        }
141}
142
143- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
144        // Disable swipe-to-delete: don't allow row edit if table not in edit mode
145        return (tableView.editing);
146}
147
148- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
149                   editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
150        return UITableViewCellEditingStyleDelete;
151}
152
153- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
154        [super setEditing:editing animated:animated];
155        if (editing) {
156                self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
157                                                                                                                                                                                           target:self
158                                                                                                                                                                                           action:@selector(addRecord)] autorelease];
159        } else {
160                self.navigationItem.leftBarButtonItem = nil;
161        }
162}
163
164- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
165        // Primary keywords don't have an order
166    return NO;
167}
168
169- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
170        //      NSDictionary *uiItem = [[uiArray objectAtIndex:indexPath.row] retain];
171        //      NSString *secondaryString = [uiItem objectForKey:@"secondaryString"];
172        //      CGSize constrainedSize = CGSizeMake([UIScreen mainScreen].bounds.size.width - 40, 200);
173        //      CGSize expectedSize = [secondaryString sizeWithFont:[UIFont systemFontOfSize:12]
174        //                                                                        constrainedToSize:constrainedSize
175        //                                                                                lineBreakMode:UILineBreakModeWordWrap];
176        //      return expectedSize.height+26;
177        CGFloat sizeForFiveLines = ([[KeywordCell labelFont] pointSize] + 4) * 7;
178        return sizeForFiveLines;
179}
180
181#pragma mark ------ KeywordEditDelegate Methods
182
183- (void)dataDidChangeInController:(UIViewController *)controller {
184        [self getKeywords];
185}
186
187- (NSString *)domain {
188        return ([self.delegate domain]);
189}
190
191- (NSString *)longNameForKeyword:(NSString *)shortName {
192        // Try to get the mapped keyword type. If it fails, use the incoming string
193        if (shortName == nil) return nil;
194        NSString *longName = [keywordTypesNames objectForKey:shortName];
195        if (longName) {
196                return longName;
197        } else {
198                return shortName;
199        }
200}
201
202- (NSArray *)typesForKeyword:(NSString *)shortName {
203        if (shortName == nil) return nil;
204        NSArray *secondaryTypes = [keywordTypes objectForKey:shortName];
205        return secondaryTypes;
206}
207
208#pragma mark ------ UI Methods and Json Delegates
209
210- (void)addRecord {
211        KeywordEditController *editC = [KeywordEditController controllerForKeyword:nil];
212        editC.delegate = self;
213        [self.navigationController pushViewController:editC animated:YES];
214}
215
216- (NSDictionary *)selectRecordInSetUsingId:(NSString *)anId {
217        // selects the correct full record in the set from an id
218        for (NSDictionary *theRec in keywordsArray) {
219                if ([[theRec valueForKey:@"id"] integerValue] == [anId integerValue]) {
220                        return theRec;
221                }
222        }
223        return nil;
224}
225
226
227- (void)updateUITableWithJson:(NSDictionary *)parsedJson {
228#ifdef DEBUG
229        NSLog(@"%@", [parsedJson descriptionInStringsFileFormat]);
230#endif
231       
232        [self.keywordsArray removeAllObjects];
233        [self.uiArray removeAllObjects];
234        if ([[parsedJson valueForKey:@"success"] integerValue] == 1) {
235                [self.keywordsArray setArray:(NSArray *)[parsedJson valueForKey:@"keywordList"]];
236                for (NSDictionary *aRec in self.keywordsArray) {
237                        [self.uiArray addObject:[self uiItemFromJsonItem:aRec]];
238                }
239                [self.delegate dataDidChangeInController:self];
240                [self.tableView reloadData];
241        } else {
242                [self.tableView reloadData];
243                [Keyword throwJsonErrorAlert:parsedJson];
244        }
245       
246}
247
248- (NSMutableDictionary *)uiItemFromJsonItem:(NSDictionary *)jsonItem {
249        // Method that creates a dictionary to display in a cell row
250        // Sample jsonItem:
251                //      {id: 12,
252                //      field: "pa",
253                //      value: "my postal address",
254                //      secondaryKeywords: [ {id: 15, field: "a1", value: "my street"}]}
255       
256//#ifdef DEBUG
257//      NSLog(@"Naptr Rec in JSON: %@", [jsonItem descriptionInStringsFileFormat]);
258//#endif
259
260        NSMutableDictionary *uiItem;
261        if (!jsonItem) {
262                return NULL;
263        }
264        uiItem = [NSMutableDictionary dictionaryWithDictionary:jsonItem];
265       
266        // set field string
267        NSString *primaryLongName;
268        primaryLongName = [self longNameForKeyword:[jsonItem objectForKey:@"field"]];
269        [uiItem setObject:primaryLongName forKey:@"primaryLongName"];
270
271        // set value if nonexistent
272        if (![uiItem objectForKey:@"value"])
273                [uiItem setObject:@"" forKey:@"value"];
274
275        // Generate the basic display string
276        NSInteger i=0;
277        NSMutableString *theSecText = [NSMutableString stringWithCapacity:300];
278        NSDictionary *theSec;
279        for (theSec in [uiItem objectForKey:@"secondaryKeywords"]) {
280                if (i == 0) {
281                        [theSecText appendFormat:@"%@: %@", [self longNameForKeyword:[theSec objectForKey:@"field"]], [theSec objectForKey:@"value"]];
282                } else {
283                        [theSecText appendFormat:@"\n%@: %@", [self longNameForKeyword:[theSec objectForKey:@"field"]], [theSec objectForKey:@"value"]];
284                }
285                i++;
286        }
287        [uiItem setObject:theSecText forKey:@"secondaryString"];
288       
289        return uiItem;
290}
291
292- (void)fillKeywordNamesDict:(NSDictionary *)parsedJson {
293        // We'll both get the mappings and the keyword structures here
294        // Start by getting the short->long name mapping
295        if (keywordTypesNames)
296                [keywordTypesNames release];
297        if (!parsedJson) {
298                // We're loading the data statically (not from the network)
299                keywordTypesNames = [[NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle]
300                                                                                                                                                                pathForResource:@"KeywordTypesLongNames"
301                                                                                                                                                                ofType:@"plist"]] retain];
302        } else {
303                keywordTypesNames = [[NSMutableDictionary dictionaryWithCapacity:20] retain];
304                if ([[parsedJson valueForKey:@"success"] integerValue] == 1) {
305                        NSArray *keyTypeList = (NSArray *)[parsedJson valueForKey:@"validKeywordList"];
306                        NSDictionary *aKeyType;
307                        for (aKeyType in keyTypeList) {
308                                [keywordTypesNames setObject:(NSString *)[aKeyType objectForKey:@"displayText"]
309                                 forKey:(NSString *)[aKeyType objectForKey:@"shortForm"]];
310                        }
311                } else {
312                        [Keyword throwJsonErrorAlert:parsedJson];
313                }
314        }
315       
316        // Now grab the keyword structure, which is loaded from a local plist
317        if (keywordTypes)
318                [keywordTypes release];
319        keywordTypes = [[NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle]
320                                                                                                                                           pathForResource:@"KeywordTypes"
321                                                                                                                                           ofType:@"plist"]] retain];
322}
323
324
325#pragma mark ------ Data management
326
327- (void)getKeywords {
328        //      inputKeyword = {
329        //              domainName: "cartman.tel",
330        //      };
331        //      successResult = {
332        //      success: true,
333        //      actionMessages: ["keywords retrieved",
334        //                                       "2nd message here"],
335        //             
336        //              keywordList = [ {id: 12, field: "pa", value: "my postal address",
337        //              secondaryKeywords: [ {id: 15, field: "a1",
338        //              value: "my street"} ]},
339        //              {id: 13, field: "fn", value: "cart",
340        //              secondaryKewords: []} ]
341        //      };
342       
343        Keyword *conn = [[[Keyword alloc] init] autorelease];
344        [conn setTheDelegate:self];
345        [conn setActionSel:@selector(updateUITableWithJson:)];
346        [conn setConnectionUrl:[conn urlFromAction:@"getkeywords"]];
347       
348        NSMutableDictionary *requestData = [[NSMutableDictionary dictionaryWithCapacity:2] retain];
349        [requestData setObject:[self.delegate domain] forKey:@"domain"];
350       
351        [conn setPayload:requestData];
352        [conn performLookup:TRUE];
353        [requestData release];
354}
355
356- (void)deleteKeywords:(NSDictionary *)aRec {
357        //      keywords = {
358        //      domain: "cartman.tel",
359        //      idList: [23, 2, 22]
360        //      };
361        //     
362        //      successResult = {
363        //      success: true,
364        //      actionMessages: ["keywords deleted"
365        //                                       "2nd message here"]
366        //      };
367       
368        if (!aRec)
369                return;
370        NSArray *idsToDelete;
371        idsToDelete = [NSMutableArray arrayWithObject:[aRec objectForKey:@"id"]];
372        if ([idsToDelete count] == 0)   // Nothing to delete
373                return;
374        [idsToDelete retain];
375        Keyword *conn = [[[Keyword alloc] init] autorelease];
376        [conn setTheDelegate:[MyTelConnect sharedInstance]];
377        [conn setActionSel:@selector(doNothing:)];
378        [conn setConnectionUrl:[conn urlFromAction:@"deletekeywords"]];
379       
380        NSMutableDictionary *requestData = [[NSMutableDictionary dictionaryWithCapacity:2] retain];
381        [requestData setObject:[self.delegate domain] forKey:@"domain"];
382        [requestData setObject:idsToDelete forKey:@"idList"];
383       
384        [conn setPayload:requestData];
385        NSDictionary *parsedJson = [conn performLookup:FALSE];
386        [requestData release];
387        [idsToDelete release];
388        if ([[parsedJson valueForKey:@"success"] integerValue] == 0) {
389                [Keyword throwJsonErrorAlert:parsedJson];
390        }
391        [self getKeywords];
392}
393
394- (void)getValidKeywords:(BOOL)fromNetwork {
395        //      successResult = {
396        //      success: true,
397        //      actionMessages: ["valid keywords retrieved",
398        //                                       "2nd message here"],
399        //              validKeywordList = [ {shortForm: "pa", displayText: "Postal address",
400        //              canHaveSecondaries: true, canBeSecondary: false},
401        //              {shortForm: "a1", displayText: "Address line 1",
402        //              canHaveSecondaries: false, canBeSecondary: true}
403        //              ]
404        //             
405        //      };
406       
407        if (fromNetwork) {
408                Keyword *conn = [[[Keyword alloc] init] autorelease];
409                [conn setTheDelegate:[MyTelConnect sharedInstance]];
410                [conn setActionSel:@selector(doNothing:)];
411                [conn setConnectionUrl:[conn urlFromAction:@"getvalidkeywords"]];
412               
413                NSMutableDictionary *requestData = [[NSMutableDictionary dictionaryWithCapacity:1] retain];
414                [requestData setObject:[self.delegate domain] forKey:@"domain"];
415               
416                [conn setPayload:requestData];
417                NSDictionary *parsedJson = [conn performLookup:FALSE];
418                [self fillKeywordNamesDict:parsedJson];
419                [requestData release];
420        } else {
421                [self fillKeywordNamesDict:nil];
422        }
423}
424
425
426@end
427
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us