From 22ae0fa8c302d22071116abca27d2add3a0af991 Mon Sep 17 00:00:00 2001 From: Bibiko Date: Tue, 16 Feb 2010 11:23:45 +0000 Subject: =?UTF-8?q?=E2=80=A2=20re-factored=20and=20outsourced=20the=20enti?= =?UTF-8?q?re=20CSV=20import=20field=20mapper=20sheet=20-=20changed=20the?= =?UTF-8?q?=20way=20to=20choose=20whether=20a=20source=20field=20should=20?= =?UTF-8?q?be=20imported=20or=20not=20by=20introducing=20a=20new=20table?= =?UTF-8?q?=20column=20'operators'=20-=20clicking=20at=20the=20'operator's?= =?UTF-8?q?=20header=20toggles=20all=20operators=20to=20'Import'=20or=20'D?= =?UTF-8?q?o=20not=20import'=20-=20added=20tooltips=20for=20each=20table?= =?UTF-8?q?=20cell;=20if=20file's=20first=20line=20are=20the=20headers=20s?= =?UTF-8?q?how=20them=20in=20the=20tooltips=20as=20well=20-=20added=20chec?= =?UTF-8?q?kbox=20"First=20line=20contains=20fields=20names"=20since=20it'?= =?UTF-8?q?ll=20be=20clear=20in=20this=20pane=20whether=20a=20file=20has?= =?UTF-8?q?=20a=20header=20line=20or=20not=20(will=20be=20sync=20with=20pr?= =?UTF-8?q?efs)=20-=20added=20the=20possibility=20to=20choose=20the=20impo?= =?UTF-8?q?rt=20method:=20INSERT=20INTO=20or=20REPLACE=20INTO=20=E2=80=A2?= =?UTF-8?q?=20deleted=20all=20old=20field=20mapper=20stuff=20from=20TableD?= =?UTF-8?q?ump=20and=20DBView.xib?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notes: - tests are needed to be sure that this change does not cause mismatches while importing - symbols for Do (not) import are tendative - maybe use images - a further import method UPDATE plus an operator '=' will be added soon - chance to add a new global source variable will come soon - displaying of source field types will come soon - semi-automatically matching of source field names and header names will come soon - the GUI needs some improvements afterwards --- Source/TableDump.m | 220 ++++++++++------------------------------------------- 1 file changed, 41 insertions(+), 179 deletions(-) (limited to 'Source/TableDump.m') diff --git a/Source/TableDump.m b/Source/TableDump.m index 2e055f94..33118738 100644 --- a/Source/TableDump.m +++ b/Source/TableDump.m @@ -108,11 +108,6 @@ [exportMultipleXMLTableView reloadData]; } -- (IBAction)closeFieldMapperSheet:(id)sender -{ - [NSApp endSheet:fieldMappingSheet returnCode:[sender tag]]; -} - /** * Common method for ending modal sessions */ @@ -513,39 +508,6 @@ [importCSVBox setHidden:![[[importFormatPopup selectedItem] title] isEqualToString:@"CSV"]]; } -/** - * When the table in the CSV field mapping sheet is changed, retrieve - * the columns from the new table and reset the field mapping array. - */ -- (IBAction)changeTable:(id)sender -{ - - // Remove all the current columns - [fieldMappingTableColumnNames removeAllObjects]; - - // Retrieve the information for the newly selected table using a SPTableData instance - SPTableData *selectedTableData = [[SPTableData alloc] init]; - [selectedTableData setConnection:mySQLConnection]; - NSDictionary *tableDetails = [selectedTableData informationForTable:[fieldMappingPopup titleOfSelectedItem]]; - if (tableDetails) { - for (NSDictionary *column in [tableDetails objectForKey:@"columns"]) { - [fieldMappingTableColumnNames addObject:[NSString stringWithString:[column objectForKey:@"name"]]]; - } - } - [selectedTableData release]; - - // Update the table view - fieldMappingCurrentRow = 0; - if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil; - [self setupFieldMappingArray]; - [rowDownButton setEnabled:NO]; - [rowUpButton setEnabled:([fieldMappingImportArray count] > 1)]; - [recordCountLabel setStringValue:[NSString stringWithFormat:@"%ld of %@%lu records", (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]]; - - [self updateFieldMappingButtonCell]; - [fieldMappingTableView reloadData]; -} - - (void)importBackgroundProcess:(NSString*)filename { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -822,7 +784,7 @@ BOOL allDataRead = NO; BOOL insertBaseStringHasEntries; NSStringEncoding csvEncoding = [MCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]; - if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil; + fieldMappingArray = nil; // Start the notification timer to allow notifications to be shown even if frontmost for long queries [[SPGrowlController sharedGrowlController] setVisibilityForNotificationName:@"Import Finished"]; @@ -975,7 +937,7 @@ && ([parsedRows count] >= 100 || (!csvRowArray && allDataRead))) { [self closeAndStopProgressSheet]; - if (![self buildFieldMappingArrayWithData:parsedRows isPreview:!allDataRead]) { + if (![self buildFieldMappingArrayWithData:parsedRows isPreview:!allDataRead ofSoureFile:filename]) { [csvParser release]; [csvDataBuffer release]; [parsedRows release]; @@ -992,13 +954,13 @@ [NSApp beginSheet:singleProgressSheet modalForWindow:tableWindow modalDelegate:self didEndSelector:nil contextInfo:nil]; [singleProgressSheet makeKeyWindow]; - // Set up the field names import string - [insertBaseString appendString:@"INSERT INTO "]; - [insertBaseString appendString:[[fieldMappingPopup titleOfSelectedItem] backtickQuotedString]]; + // Set up the field names import string for INSERT or REPLACE INTO + [insertBaseString appendFormat:@"%@ INTO ", selectedImportMethod]; + [insertBaseString appendString:[selectedTableTarget backtickQuotedString]]; [insertBaseString appendString:@" ("]; insertBaseStringHasEntries = NO; for (i = 0; i < [fieldMappingArray count]; i++) { - if ([NSArrayObjectAtIndex(fieldMappingArray, i) integerValue] > 0) { + if ([NSArrayObjectAtIndex(fieldMapperOperator, i) integerValue] == 0) { if (insertBaseStringHasEntries) [insertBaseString appendString:@","]; else insertBaseStringHasEntries = YES; [insertBaseString appendString:[NSArrayObjectAtIndex(fieldMappingTableColumnNames, i) backtickQuotedString]]; @@ -1079,7 +1041,7 @@ [csvDataBuffer release]; [parsedRows release]; [parsePositions release]; - if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil; + fieldMappingArray = nil; [importPool drain]; [tableDocumentInstance setQueryMode:SPInterfaceQueryMode]; @@ -1103,7 +1065,7 @@ // If the table selected for import is also selected in the content view, // update the content view - on the main thread to avoid crashes. - if ([tablesListInstance tableName] && [[fieldMappingPopup titleOfSelectedItem] isEqualToString:[tablesListInstance tableName]]) { + if ([tablesListInstance tableName] && [selectedTableTarget isEqualToString:[tablesListInstance tableName]]) { if ([[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableContent]) { [tableContentInstance performSelectorOnMainThread:@selector(reloadTable:) withObject:nil waitUntilDone:YES]; } else { @@ -1142,7 +1104,7 @@ * Takes an array of data to show when selecting the field mapping, and an indicator of whether * that dataset is complete or a preview of the full data set. */ -- (BOOL) buildFieldMappingArrayWithData:(NSArray *)importData isPreview:(BOOL)dataIsPreviewData +- (BOOL) buildFieldMappingArrayWithData:(NSArray *)importData isPreview:(BOOL)dataIsPreviewData ofSoureFile:(NSString*)filename { // Ensure data was provided, or alert than an import error occurred and return false. @@ -1172,12 +1134,8 @@ } fieldMappingImportArrayIsPreview = dataIsPreviewData; - // Get the list of tables (not views) to display in the field mapping interface - [fieldMappingPopup removeAllItems]; - [fieldMappingPopup addItemsWithTitles:[tablesListInstance allTableNames]]; - // If there's no tables to select, error - if (![[fieldMappingPopup itemArray] count]) { + if (![[tablesListInstance allTableNames] count]) { [self closeAndStopProgressSheet]; SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), @@ -1189,46 +1147,41 @@ return FALSE; } - // Set up tableView buttons - NSPopUpButtonCell *buttonCell = [[NSPopUpButtonCell alloc] init]; - [buttonCell setControlSize:NSSmallControlSize]; - [buttonCell setFont:[NSFont labelFontOfSize:[NSFont smallSystemFontSize]]]; - [buttonCell setBordered:NO]; - [[fieldMappingTableView tableColumnWithIdentifier:@"value"] setDataCell:buttonCell]; - [buttonCell release]; - - // Select either the currently selected table, or the first item in the list - if ([tableDocumentInstance table] != nil && ![[tablesListInstance tableName] isEqualToString:@""]) { - [fieldMappingPopup selectItemWithTitle:[tablesListInstance tableName]]; - } else { - [fieldMappingPopup selectItemAtIndex:0]; - } - // Set the import array if (fieldMappingImportArray) [fieldMappingImportArray release]; fieldMappingImportArray = [[NSArray alloc] initWithArray:importData]; - - // Trigger a table selection and setup - [self changeTable:self]; fieldMapperSheetStatus = 1; - // if(fieldMapperController) [fieldMapperController release]; - // fieldMapperController = [[SPFieldMapperController alloc] initWithDelegate:self]; + // Init the field mapper controller + fieldMapperController = [[SPFieldMapperController alloc] initWithDelegate:self]; + [fieldMapperController setConnection:mySQLConnection]; + [fieldMapperController setSourcePath:filename]; + [fieldMapperController setImportDataArray:fieldMappingImportArray hasHeader:[importFieldNamesSwitch state]]; - // Show fieldMapping sheet - // [NSApp beginSheet:[fieldMapperController window] - [NSApp beginSheet:fieldMappingSheet + // Show field mapper sheet and set the focus to it + [NSApp beginSheet:[fieldMapperController window] modalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(fieldMapperDidEndSheet:returnCode:contextInfo:) contextInfo:nil]; - // Wait for fieldMappingSheet + [[fieldMapperController window] makeKeyWindow]; + + // Wait for field mapper sheet while (fieldMapperSheetStatus == 1) usleep(100000); - // if(fieldMapperController) [fieldMapperController release]; + // Get mapping settings + fieldMapperOperator = [NSArray arrayWithArray:[fieldMapperController fieldMapperOperator]]; + fieldMappingArray = [NSArray arrayWithArray:[fieldMapperController fieldMappingArray]]; + selectedTableTarget = [NSString stringWithString:[fieldMapperController selectedTableTarget]]; + selectedImportMethod = [NSString stringWithString:[fieldMapperController selectedImportMethod]]; + fieldMappingTableColumnNames = [NSArray arrayWithArray:[fieldMapperController fieldMappingTableColumnNames]]; + [importFieldNamesSwitch setState:[fieldMapperController importFieldNamesHeader]]; + [prefs setBool:[importFieldNamesSwitch state] forKey:SPCSVImportFirstLineIsHeader]; + + if(fieldMapperController) [fieldMapperController release]; if(fieldMapperSheetStatus == 2) return YES; @@ -1242,69 +1195,6 @@ fieldMapperSheetStatus = (returnCode) ? 2 : 3; } -/* - * Sets up the fieldMapping array to be shown in the tableView - */ -- (void)setupFieldMappingArray -{ - NSInteger i, value; - - if (!fieldMappingArray) { - fieldMappingArray = [[NSMutableArray alloc] init]; - - for (i = 0; i < [fieldMappingTableColumnNames count]; i++) { - if (i < [NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow) count] && ![NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), i) isKindOfClass:[NSNull class]]) { - value = i + 1; - } else { - value = 0; - } - - [fieldMappingArray addObject:[NSNumber numberWithInteger:value]]; - } - } - - [fieldMappingTableView reloadData]; -} - -/* - * Update the NSButtonCell items for use in the field mapping display - */ -- (void)updateFieldMappingButtonCell -{ - int i; - - [fieldMappingButtonOptions setArray:[fieldMappingImportArray objectAtIndex:fieldMappingCurrentRow]]; - for (i = 0; i < [fieldMappingButtonOptions count]; i++) { - if ([[fieldMappingButtonOptions objectAtIndex:i] isNSNull]) { - [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, [prefs objectForKey:SPNullValue]]]; - } else { - [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, NSArrayObjectAtIndex(fieldMappingButtonOptions, i)]]; - } - } -} - -- (IBAction)stepRow:(id)sender -/* - displays next/previous row in fieldMapping tableView - */ -{ - if ( [sender tag] == 0 ) { - fieldMappingCurrentRow--; - } else { - fieldMappingCurrentRow++; - } - [self updateFieldMappingButtonCell]; - - //-----------[self setupFieldMappingArray]; - [fieldMappingTableView reloadData]; - - [recordCountLabel setStringValue:[NSString stringWithFormat:@"%ld of %@%lu records", (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]]; - - // enable/disable buttons - [rowDownButton setEnabled:(fieldMappingCurrentRow != 0)]; - [rowUpButton setEnabled:(fieldMappingCurrentRow != ([fieldMappingImportArray count]-1))]; -} - /* * Construct the VALUES string for a CSV row, based on the field mapping array - including * surrounding brackets but not including the VALUES keyword. @@ -1318,15 +1208,16 @@ NSInteger mappingArrayCount = [fieldMappingArray count]; for (i = 0; i < mappingArrayCount; i++) { - mapColumn = [NSArrayObjectAtIndex(fieldMappingArray, i) integerValue]; // Skip unmapped columns - if (!mapColumn) continue; + if ([NSArrayObjectAtIndex(fieldMapperOperator, i) integerValue] > 0) continue; + + mapColumn = [NSArrayObjectAtIndex(fieldMappingArray, i) integerValue]; if ([valueString length] > 1) [valueString appendString:@","]; // Append the data - cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn - 1); + cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn); if (cellData == [NSNull null]) { [valueString appendString:@"NULL"]; @@ -2794,8 +2685,6 @@ setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]]; [[[exportMultipleXMLTableView tableColumnWithIdentifier:@"tables"] dataCell] setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]]; - [[[fieldMappingTableView tableColumnWithIdentifier:@"0"] dataCell] - setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]]; [errorsView setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]]; } else { [[[exportDumpTableView tableColumnWithIdentifier:@"tables"] dataCell] @@ -2804,8 +2693,6 @@ setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; [[[exportMultipleXMLTableView tableColumnWithIdentifier:@"tables"] dataCell] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - [[[fieldMappingTableView tableColumnWithIdentifier:@"0"] dataCell] - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; [errorsView setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; } } @@ -2815,7 +2702,7 @@ - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView; { - return (aTableView == fieldMappingTableView) ? [fieldMappingTableColumnNames count] : [tables count]; + return [tables count]; } - (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex @@ -2826,39 +2713,19 @@ - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { id returnObject = nil; - - if ( aTableView == fieldMappingTableView ) { - if ([[aTableColumn identifier] isEqualToString:@"field"]) { - returnObject = [fieldMappingTableColumnNames objectAtIndex:rowIndex]; - - } else if ([[aTableColumn identifier] isEqualToString:@"value"]) { - if ([[[aTableColumn dataCell] class] isEqualTo:[NSPopUpButtonCell class]]) { - [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems]; - [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemWithTitle:NSLocalizedString(@"Do not import", @"text for csv import drop downs")]; - [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingButtonOptions]; - } - - returnObject = [fieldMappingArray objectAtIndex:rowIndex]; - } + + if ( [[aTableColumn identifier] isEqualToString:@"switch"] ) { + returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:0]; } else { - if ( [[aTableColumn identifier] isEqualToString:@"switch"] ) { - returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:0]; - } else { - returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:1]; - } + returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:1]; } - + return returnObject; } - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { - if ( aTableView == fieldMappingTableView ) { - [fieldMappingArray replaceObjectAtIndex:rowIndex withObject:anObject]; - } - else { - [[tables objectAtIndex:rowIndex] replaceObjectAtIndex:0 withObject:anObject]; - } + [[tables objectAtIndex:rowIndex] replaceObjectAtIndex:0 withObject:anObject]; } @@ -2925,8 +2792,6 @@ self = [super init]; tables = [[NSMutableArray alloc] init]; - fieldMappingTableColumnNames = [[NSMutableArray alloc] init]; - fieldMappingButtonOptions = [[NSMutableArray alloc] init]; fieldMappingArray = nil; fieldMappingImportArray = nil; fieldMappingImportArrayIsPreview = NO; @@ -2938,10 +2803,7 @@ - (void)dealloc { [tables release]; - [fieldMappingTableColumnNames release]; - [fieldMappingButtonOptions release]; if (fieldMappingImportArray) [fieldMappingImportArray release]; - if (fieldMappingArray) [fieldMappingArray release]; if (prefs) [prefs release]; [super dealloc]; -- cgit v1.2.3