bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / macosx / spotlight / OOoMetaDataParser.m
blob4d2b95d72fff71cb38d63376e7356a704d47b4e3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
20 #include <objc/objc-runtime.h>
22 #import "OOoMetaDataParser.h"
24 static NSSet *singleValueXMLElements;
25 static NSSet *multiValueXMLElements;
26 static NSDictionary *metaXML2MDIKeys;
28 @implementation OOoMetaDataParser
30 + (void)initialize
32     static BOOL isInitialized = NO;
34     if (isInitialized == NO) {
35         //set up the meta elements with only one value
36         NSMutableSet *temp = [NSMutableSet new];
37 //FIXME these should use namespace URIs and not prefixes
38         [temp addObject:@"dc:title"];
39         [temp addObject:@"dc:description"];
40         [temp addObject:@"meta:user-defined"];
41         singleValueXMLElements = [[NSSet setWithSet:temp] retain];
43         //set up the meta elements that can have more than one value
44         [temp removeAllObjects];
45         [temp addObject:@"dc:subject"];
46         [temp addObject:@"meta:keyword"];
47         [temp addObject:@"meta:initial-creator"];
48         [temp addObject:@"dc:creator"];
49         multiValueXMLElements = [[NSSet setWithSet:temp] retain];
50         [temp release];
52         //set up the map to store the values with the correct MDI keys
53         NSMutableDictionary *tempDict = [NSMutableDictionary new];
54         [tempDict setObject:(NSString*)kMDItemTitle forKey:@"dc:title"];
55         [tempDict setObject:(NSString*)kMDItemDescription forKey:@"dc:description"];
56         [tempDict setObject:(NSString*)kMDItemKeywords forKey:@"dc:subject"];
57         [tempDict setObject:(NSString*)kMDItemAuthors forKey:@"meta:initial-creator"];
58         [tempDict setObject:(NSString*)kMDItemAuthors forKey:@"dc:creator"];
59         [tempDict setObject:(NSString*)kMDItemKeywords forKey:@"meta:keyword"];
60         [tempDict setObject:@"org_openoffice_opendocument_custominfo1" forKey:@"Info 1"];
61         [tempDict setObject:@"org_openoffice_opendocument_custominfo2" forKey:@"Info 2"];
62         [tempDict setObject:@"org_openoffice_opendocument_custominfo3" forKey:@"Info 3"];
63         [tempDict setObject:@"org_openoffice_opendocument_custominfo4" forKey:@"Info 4"];
64         metaXML2MDIKeys = [[NSDictionary dictionaryWithDictionary:tempDict] retain];
65         [tempDict release];
67         isInitialized = YES;
68     }
71 - (id)init
73     if ((self = [super init]) != nil) {
74         shouldReadCharacters = NO;
75         textCurrentElement = nil;
77         return self;
78     }
80     return nil;
83 - (void)parseXML:(NSData*)data intoDictionary:(NSMutableDictionary*)dict
85     metaValues = dict;
87     //NSLog(@"data: %@ %d", data, [data length]);
89     //init parser settings
90     shouldReadCharacters = NO;
92     NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
94     // class 'OOoMetaDataParser' does not implement the 'NSXMLParserDelegate' protocol
95     // So instead of this:
96     // [parser setDelegate:self];
97     // do this:
98     objc_msgSend(parser, @selector(setDelegate:), self);
100     [parser setShouldResolveExternalEntities:NO];
101     [parser parse];
103     [parser release];
105     //NSLog(@"finished parsing meta");
108 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
110     (void) parser; // unused
111     (void) namespaceURI; // FIXME this should not be ignored but should be used
112                          // instead of meta: prefix in the comparison below!
113     (void) qualifiedName; // unused
114 //    NSLog(@"<%@>", elementName);
115     if ([singleValueXMLElements containsObject:elementName] == YES) {
116         shouldReadCharacters = YES;
117     } else if ([multiValueXMLElements containsObject:elementName] == YES) {
118         shouldReadCharacters = YES;
119     } else {
120         //we are not interested in this element
121         shouldReadCharacters = NO;
122         return;
123     }
125     if (shouldReadCharacters == YES) {
126         textCurrentElement = [NSMutableString new];
127         isCustom = [elementName isEqualToString:@"meta:user-defined"];
128         if (isCustom == YES) {
129             customAttribute = [[attributeDict objectForKey:@"meta:name"] retain];
130             //NSLog(customAttribute);
131         }
132     }
134     //NSLog(@"start element %@", elementName);
137 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
139     (void) parser; // unused
140     (void) namespaceURI; // unused
141     (void) qName; // unused
142 //    NSLog(@"</%@>", elementName);
143     if (shouldReadCharacters == YES) {
144         NSString *mdiName = nil;
145         if (isCustom == YES) {
146             mdiName = (NSString*)[metaXML2MDIKeys objectForKey:customAttribute];
147         } else {
148             mdiName = (NSString*)[metaXML2MDIKeys objectForKey:elementName];
149         }
150         //NSLog(@"mdiName: %@", mdiName);
152         if (mdiName == nil) {
153             return;
154         }
156         if ([singleValueXMLElements containsObject:elementName] == YES) {
157             [metaValues setObject:textCurrentElement forKey:mdiName];
158         } else {
159             // must be multi-value
160             NSMutableArray *arr = [metaValues objectForKey:mdiName];
161             if (arr == nil) {
162                 // we have no array yet, create it
163                 arr = [[NSMutableArray new] autorelease];
164                 // and store it
165                 [metaValues setObject:arr forKey:mdiName];
166             }
167             // only store an element once, no need for duplicates
168             if ([arr containsObject:textCurrentElement] == NO) {
169                 [arr addObject:textCurrentElement];
170             }
171         }
172         // cleanup part 1
173         [textCurrentElement release];
174         if (isCustom == YES) {
175             [customAttribute release];
176         }
177     }
179     //cleanup part 2
180     shouldReadCharacters = NO;
181     isCustom = NO;
184 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
186     (void) parser; // unused
187 //    NSLog(@"%@", string);
188     if (shouldReadCharacters == NO) {
189         return;
190     }
192     // this delegate method might be called several times for a single element,
193     // so we have to collect the received data
194     [textCurrentElement appendString:string];
196     //NSLog(@"chars read: %@", string);
199 - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
201     //NSLog(@"parsing finished with error");
202     NSLog(@"Error %li, Description: %@, Line: %li, Column: %li", (long) [parseError code],
203           [[parser parserError] localizedDescription], (long) [parser lineNumber],
204           (long) [parser columnNumber]);
207 @end
209 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */