CatNiP prefinal
Sähköinen nuottikirja, HY-TKTKL-OHTUPROJ KESÄ11
|
00001 00011 #import "MediaWikiPageQuery.h" 00012 00013 00014 @implementation MediaWikiPageQuery 00015 @synthesize parameters; 00016 @synthesize pageDelegate; 00017 @synthesize composerName; 00018 00019 -(void)setWikiAction:(NSString *)wikiAction { 00020 [self.parameters setValue:[NSString stringWithString:wikiAction] forKey:@"action"]; 00021 } 00022 -(NSString *)wikiAction { 00023 return [self.parameters valueForKey:@"action"]; 00024 } 00025 -(void)setWikiTitle:(NSString *)wikiTitle { 00026 [self.parameters setValue:[NSString stringWithString:wikiTitle] forKey:@"title"]; 00027 } 00028 -(NSString *)wikiTitle { 00029 return [self.parameters valueForKey:@"title"]; 00030 } 00039 + (MediaWikiPageQuery*) newPageQuery:(NSString*)URL delegate:(id <MediaWikiPageQueryDelegate>)qDelegate { 00040 00041 if(qDelegate == nil) { 00042 return nil; 00043 } 00044 MediaWikiPageQuery* cQuery = [MediaWikiPageQuery alloc]; 00045 cQuery = [cQuery initWithDelegate:cQuery mediaWikiURL:URL]; 00046 cQuery.pageDelegate = qDelegate; 00047 return cQuery; 00048 } 00049 00051 -init { 00052 if((self = [super init])) { 00053 self.parameters = [[[NSMutableDictionary alloc] init] autorelease]; 00054 00055 return self; 00056 } 00057 return nil; 00058 } 00060 - (NSString*) buildQueryURL { 00061 return [NSString stringWithFormat: @"%@?%@", self.mediaWikiURLString, [self _buildGetParams]]; 00062 } 00063 00069 -(void)didReceiveMediaWikiData:(NSData *)data { 00070 //data contains the whole raw page in wikitext format 00071 NSString* fullString = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding]; 00072 CompositionData* comp = [[CompositionData alloc] init]; 00073 /*NSLog(@"received data, size is %d and string length is %d",[data length], 00074 [fullString length]); */ 00075 00076 /* We could theoretically parse this from the wikiTitle, but it's better 00077 to use the one passed to us. */ 00078 comp.composerName = self.composerName; 00079 comp.compositionName = self.wikiTitle; 00080 /* An array for all the score files we find in the wiki page */ 00081 NSMutableArray* scores = [[NSMutableArray alloc] init]; 00082 ScoreData* score; 00083 00084 /* An error object for catching regexp errors. If we were smart we'd 00085 actually check this... Oh well, ACTION POINT!*/ 00086 NSError* error = NULL; 00087 /* Finds every imslpfile template block in the wikitext */ 00088 NSRegularExpression* imslpFileRegexp = [NSRegularExpression regularExpressionWithPattern:@"(\\n=+([^=]*?)=+\\n)?\\{\\{#fte:imslpfile(.*?)^\\}\\}$" options:(NSRegularExpressionCaseInsensitive | NSRegularExpressionDotMatchesLineSeparators | NSRegularExpressionAnchorsMatchLines) error:&error]; 00089 if(error) { 00090 [[CatNiPErrorManager sharedManager] reportError:error]; 00091 } 00092 /* Checks whether a string contains a wikitext header */ 00093 NSRegularExpression* imslpFileHeaderRegexp = [NSRegularExpression regularExpressionWithPattern:@"\\n?=+(.*?)=+\\n" options:0 error:&error]; 00094 if(error) { 00095 [[CatNiPErrorManager sharedManager] reportError:error]; 00096 } 00097 /* Reads every name=value pair found in a imslp file template block. */ 00098 NSRegularExpression* imslpPropertiesRegexp = 00099 [NSRegularExpression regularExpressionWithPattern:@"^\\|+(.*)=(.*)$" options:(NSRegularExpressionAnchorsMatchLines) error:&error]; 00100 if(error) { 00101 [[CatNiPErrorManager sharedManager] reportError:error]; 00102 } 00103 /* Checks whether the name of a property contains a discrete number as the last character(s) */ 00104 NSRegularExpression* imslpPropNameRegexp = 00105 [NSRegularExpression regularExpressionWithPattern:@"(\\D+)\\s(\\d+)" options:0 error:&error]; 00106 if(error) { 00107 [[CatNiPErrorManager sharedManager] reportError:error]; 00108 } 00109 00110 00111 NSString* propName; 00112 NSString* propValue; 00113 // NSUInteger numMatches = [imslpFileRegexp numberOfMatchesInString:fullString options:0 range:NSMakeRange(0, [fullString length])]; 00114 //NSLog(@"number of file template matches in full string is %d",numMatches); 00115 00116 NSArray* fileMatches = [imslpFileRegexp matchesInString:fullString options:0 range:NSMakeRange(0, [fullString length])]; 00117 for(NSTextCheckingResult *match in fileMatches) { 00118 /* We're going to start by creating a new string which represents 00119 the single file template block we're currently looking at */ 00120 NSString* fileEntry = [fullString substringWithRange:[match range]]; 00121 /* Each file block should contain at least one File Name #=something 00122 name/value pair, where the # is a number (eg. File Name 1=what.pdf) 00123 and we're interested in these; each one defines one score file. */ 00124 NSMutableDictionary* fileData = [[NSMutableDictionary alloc] init ]; 00125 NSMutableDictionary* commonData = [[NSMutableDictionary alloc] init]; 00126 /* First though, we check if we caught a header for this template. */ 00127 NSTextCheckingResult* headerResult = [imslpFileHeaderRegexp firstMatchInString:fileEntry options:0 range:NSMakeRange(0, [fileEntry length])]; 00128 NSString* fileHeader = @""; 00129 if(headerResult) { 00130 fileHeader = [fileEntry substringWithRange:[headerResult rangeAtIndex:1]]; 00131 } 00132 NSLog(@"File header: %@",fileHeader); 00133 00134 // numMatches = [imslpPropertiesRegexp numberOfMatchesInString:fileEntry options:0 range:NSMakeRange(0, [fileEntry length])]; 00135 // NSLog(@" + number of property row matches in file string (len %d) is %d",[fileEntry length], numMatches); 00136 NSArray* propMatches = [imslpPropertiesRegexp matchesInString:fileEntry options:0 range:NSMakeRange(0, [fileEntry length])]; 00137 00138 /* We now check each property found in the block */ 00139 for(NSTextCheckingResult *propMatch in propMatches) { 00140 /* The propName is the first parenthesized value in the 00141 imslPropertiesRegexp expression, propName the second, and 00142 we get them with rangeAtIndex. rangeAtIndex:0 would give us 00143 the whole "|Ladedah=Whatever" string. 00144 */ 00145 propName = [fileEntry substringWithRange:[propMatch rangeAtIndex:1]]; 00146 propValue = [fileEntry substringWithRange:[propMatch rangeAtIndex:2]]; 00147 /* We now see if this property is one of the "number indexed" ones 00148 ie. basically one of the multifile properties. Note that 00149 even if there is only one file in the block it will have a 00150 number index, and all it's properties (eg. page count) will 00151 be indexed to it as well 00152 */ 00153 NSTextCheckingResult* indexResult = [imslpPropNameRegexp firstMatchInString:propName options:0 range:NSMakeRange(0, [propName length])]; 00154 if(indexResult) { 00155 // We have a Blah blah 5=Somethingsomething result 00156 // Blah blah is in rangeAtIndex:1 and the number is in 00157 // rangeAtIndex:2 00158 // NSInteger idx = [[propName substringWithRange:[indexResult rangeAtIndex:2]] integerValue]; 00159 NSString* idxString = [propName substringWithRange:[indexResult rangeAtIndex:2]]; 00160 NSString* nameString = [propName substringWithRange:[indexResult rangeAtIndex:1]]; 00161 /* All properties with a number index of x are for the file 00162 defined by File Name x=whatever.pdf so we save them 00163 all in a nice little dictionary for later. */ 00164 if(![fileData objectForKey:idxString]) { 00165 NSMutableDictionary* specificFileData = [[[NSMutableDictionary alloc] init] autorelease]; 00166 [fileData setObject:specificFileData forKey:idxString]; 00167 00168 } 00169 [[fileData objectForKey:idxString] setObject:propValue forKey:nameString]; 00170 00171 // NSLog(@" - indexed match found, [%d] %@",idx,propName); 00172 00173 } 00174 else { 00175 /* non-indexed properties are for every file found in the block */ 00176 [commonData setObject:propValue forKey:propName]; 00177 } 00178 // NSLog(@" - match found as %@ is %@",propName, propValue); 00179 } 00180 00181 /* We've read all the properties in the block. Now we need to create 00182 a score data object for every file in the block and apply the common 00183 data to each one */ 00184 NSEnumerator* fileEntriesEnumerator = [fileData keyEnumerator]; 00185 id key; 00186 while((key = [fileEntriesEnumerator nextObject])) { 00187 score = [[ScoreData alloc] init]; 00188 NSMutableDictionary* combinedDictionary = [[NSMutableDictionary alloc] initWithDictionary:[fileData objectForKey:key]]; 00189 [combinedDictionary addEntriesFromDictionary:commonData]; 00190 NSEnumerator* dataEnumerator = [combinedDictionary keyEnumerator]; 00191 id dataKey; 00192 NSMutableString* metaDataString = [[NSMutableString alloc] init]; 00193 NSMutableDictionary* resultDictionary = [[NSMutableDictionary alloc] init]; 00194 // Default description if no other is read 00195 score.description = @"(No description)"; 00196 while((dataKey = [dataEnumerator nextObject])) { 00197 if([dataKey caseInsensitiveCompare:@"File Name"] == NSOrderedSame) { 00198 score.pdf = [combinedDictionary objectForKey:dataKey]; 00199 } 00200 else if([dataKey caseInsensitiveCompare:@"File Description"] == NSOrderedSame) { 00201 score.description = [NSString stringWithFormat:@"%@ %@", [combinedDictionary objectForKey:dataKey], fileHeader]; 00202 } 00203 00204 else { 00205 [metaDataString appendFormat:@"%@ = %@\n",dataKey,[combinedDictionary objectForKey:dataKey]]; 00206 [resultDictionary setObject:[combinedDictionary objectForKey:dataKey] forKey:dataKey]; 00207 } 00208 } 00209 00210 00211 score.fullMetaData = [NSString stringWithString:metaDataString]; 00212 score.metaDataDict = resultDictionary; 00213 /* Release some objects ... */ 00214 [combinedDictionary removeAllObjects]; 00215 [combinedDictionary release]; 00216 [resultDictionary release]; //not emptying it because we gave it away to score 00217 [metaDataString release]; 00218 00219 00220 /* finally add the build scoredata object into the list of all 00221 scores found on this page */ 00222 if (score.pdf) [scores addObject:score]; 00223 [score release]; 00224 } 00225 [fileData removeAllObjects]; 00226 [commonData removeAllObjects]; 00227 [fileData release]; 00228 [commonData release]; 00229 00230 //NSLog(@"result range: %@", match); 00231 } 00232 comp.musicScores = [[[NSArray alloc] initWithArray:scores] autorelease]; 00233 [scores removeAllObjects]; 00234 [scores release]; 00235 [fullString release]; 00236 /* Tell the delegate that we've read all the scores from the page */ 00237 [self.pageDelegate didReceiveCompositionData:[comp autorelease]]; 00238 } 00239 @end 00240 00241 @implementation MediaWikiPageQuery(Private) 00242 00244 - (NSString*)_buildGetParams { 00245 NSMutableString* qString=[[[NSMutableString alloc] init] autorelease]; 00246 NSEnumerator *enumerator = [self.parameters keyEnumerator]; 00247 id key; 00248 00249 while ((key = [enumerator nextObject])) { 00250 [qString appendString: key]; 00251 [qString appendString:@"="]; 00252 [qString appendString: [self.parameters valueForKey:key]]; 00253 [qString appendString:@"&"]; 00254 } 00255 00256 return [[[NSString alloc] initWithString:qString] autorelease]; 00257 } 00258 00259 @end