1/************************************************************************* 2* 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26*************************************************************************/ 27 28#import "OOoMetaDataParser.h" 29 30static NSSet *singleValueXMLElements; 31static NSSet *multiValueXMLElements; 32static NSDictionary *metaXML2MDIKeys; 33 34@implementation OOoMetaDataParser 35 36+ (void)initialize 37{ 38 static BOOL isInitialized = NO; 39 40 if (isInitialized == NO) { 41 //set up the meta elements with only one value 42 NSMutableSet *temp = [NSMutableSet new]; 43 [temp addObject:@"dc:title"]; 44 [temp addObject:@"dc:description"]; 45 [temp addObject:@"meta:user-defined"]; 46 singleValueXMLElements = [[NSSet setWithSet:temp] retain]; 47 48 //set up the meta elements that can have more than one value 49 [temp removeAllObjects]; 50 [temp addObject:@"dc:subject"]; 51 [temp addObject:@"meta:keyword"]; 52 [temp addObject:@"meta:initial-creator"]; 53 [temp addObject:@"dc:creator"]; 54 multiValueXMLElements = [[NSSet setWithSet:temp] retain]; 55 [temp release]; 56 57 //set up the map to store the values with the correct MDI keys 58 NSMutableDictionary *tempDict = [NSMutableDictionary new]; 59 [tempDict setObject:(NSString*)kMDItemTitle forKey:@"dc:title"]; 60 [tempDict setObject:(NSString*)kMDItemDescription forKey:@"dc:description"]; 61 [tempDict setObject:(NSString*)kMDItemKeywords forKey:@"dc:subject"]; 62 [tempDict setObject:(NSString*)kMDItemAuthors forKey:@"meta:initial-creator"]; 63 [tempDict setObject:(NSString*)kMDItemAuthors forKey:@"dc:creator"]; 64 [tempDict setObject:(NSString*)kMDItemKeywords forKey:@"meta:keyword"]; 65 [tempDict setObject:@"org_openoffice_opendocument_custominfo1" forKey:@"Info 1"]; 66 [tempDict setObject:@"org_openoffice_opendocument_custominfo2" forKey:@"Info 2"]; 67 [tempDict setObject:@"org_openoffice_opendocument_custominfo3" forKey:@"Info 3"]; 68 [tempDict setObject:@"org_openoffice_opendocument_custominfo4" forKey:@"Info 4"]; 69 metaXML2MDIKeys = [[NSDictionary dictionaryWithDictionary:tempDict] retain]; 70 [tempDict release]; 71 72 isInitialized = YES; 73 } 74} 75 76- (id)init 77{ 78 if ((self = [super init]) != nil) { 79 shouldReadCharacters = NO; 80// currentElement = nil; 81 textCurrentElement = nil; 82 83 return self; 84 } 85 86 return nil; 87} 88 89- (void)parseXML:(NSData*)data intoDictionary:(NSMutableDictionary*)dict 90{ 91 metaValues = dict; 92 93 //NSLog(@"data: %@ %d", data, [data length]); 94 95 //init parser settings 96 shouldReadCharacters = NO; 97 98 NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 99 100 [parser setDelegate:self]; 101 [parser setShouldResolveExternalEntities:NO]; 102 [parser parse]; 103 104 [parser release]; 105 106 //NSLog(@"finished parsing meta"); 107} 108 109- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict 110{ 111// NSLog(@"<%@>", elementName); 112 if ([singleValueXMLElements containsObject:elementName] == YES) { 113 shouldReadCharacters = YES; 114 } else if ([multiValueXMLElements containsObject:elementName] == YES) { 115 shouldReadCharacters = YES; 116 } else { 117 //we are not interested in this element 118 shouldReadCharacters = NO; 119 return; 120 } 121 122 if (shouldReadCharacters == YES) { 123 textCurrentElement = [NSMutableString new]; 124 isCustom = [elementName isEqualToString:@"meta:user-defined"]; 125 if (isCustom == YES) { 126 customAttribute = [[attributeDict objectForKey:@"meta:name"] retain]; 127 //NSLog(customAttribute); 128 } 129 } 130 131 //NSLog(@"start element %@", elementName); 132} 133 134- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 135{ 136// NSLog(@"</%@>", elementName); 137 if (shouldReadCharacters == YES) { 138 NSString *mdiName = nil; 139 if (isCustom == YES) { 140 mdiName = (NSString*)[metaXML2MDIKeys objectForKey:customAttribute]; 141 } else { 142 mdiName = (NSString*)[metaXML2MDIKeys objectForKey:elementName]; 143 } 144 //NSLog(@"mdiName: %@", mdiName); 145 146 if (mdiName == nil) { 147 return; 148 } 149 150 if ([singleValueXMLElements containsObject:elementName] == YES) { 151 [metaValues setObject:textCurrentElement forKey:mdiName]; 152 } else { 153 // must be multi-value 154 NSMutableArray *arr = [metaValues objectForKey:mdiName]; 155 if (arr == nil) { 156 // we have no array yet, create it 157 arr = [[NSMutableArray new] autorelease]; 158 // and store it 159 [metaValues setObject:arr forKey:mdiName]; 160 } 161 // only store an element once, no need for duplicates 162 if ([arr containsObject:textCurrentElement] == NO) { 163 [arr addObject:textCurrentElement]; 164 } 165 } 166 // cleanup part 1 167 [textCurrentElement release]; 168 if (customAttribute != nil) { 169 [customAttribute release]; 170 } 171 } 172 173 //cleanup part 2 174 shouldReadCharacters = NO; 175 isCustom = NO; 176} 177 178- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 179{ 180// NSLog(@"%@", string); 181 if (shouldReadCharacters == NO) { 182 return; 183 } 184 185 // this delegate method might be called several times for a single element, 186 // so we have to collect the received data 187 [textCurrentElement appendString:string]; 188 189 //NSLog(@"chars read: %@", string); 190} 191 192- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 193{ 194 //NSLog(@"parsing finished with error"); 195 NSLog([NSString stringWithFormat:@"Error %i, Description: %@, Line: %i, Column: %i", [parseError code], 196 [[parser parserError] localizedDescription], [parser lineNumber], 197 [parser columnNumber]]); 198} 199 200@end 201