Get the style color and number just once
[LibreOffice.git] / extensions / source / macosx / spotlight / OOoMetaDataParser.m
blob1e7cac685b88c6981c371406318f9aad6b9704a0
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     [parser setDelegate:self];
96     [parser setShouldResolveExternalEntities:NO];
97     [parser parse];
99     [parser release];
101     //NSLog(@"finished parsing meta");
104 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
106     (void) parser; // unused
107     (void) namespaceURI; // FIXME this should not be ignored but should be used
108                          // instead of meta: prefix in the comparison below!
109     (void) qualifiedName; // unused
110 //    NSLog(@"<%@>", elementName);
111     if ([singleValueXMLElements containsObject:elementName] == YES) {
112         shouldReadCharacters = YES;
113     } else if ([multiValueXMLElements containsObject:elementName] == YES) {
114         shouldReadCharacters = YES;
115     } else {
116         //we are not interested in this element
117         shouldReadCharacters = NO;
118         return;
119     }
121     if (shouldReadCharacters == YES) {
122         textCurrentElement = [NSMutableString new];
123         isCustom = [elementName isEqualToString:@"meta:user-defined"];
124         if (isCustom == YES) {
125             customAttribute = [[attributeDict objectForKey:@"meta:name"] retain];
126             //NSLog(customAttribute);
127         }
128     }
130     //NSLog(@"start element %@", elementName);
133 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
135     (void) parser; // unused
136     (void) namespaceURI; // unused
137     (void) qName; // unused
138 //    NSLog(@"</%@>", elementName);
139     if (shouldReadCharacters == YES) {
140         NSString *mdiName = nil;
141         if (isCustom == YES) {
142             mdiName = (NSString*)[metaXML2MDIKeys objectForKey:customAttribute];
143         } else {
144             mdiName = (NSString*)[metaXML2MDIKeys objectForKey:elementName];
145         }
146         //NSLog(@"mdiName: %@", mdiName);
148         if (mdiName == nil) {
149             return;
150         }
152         if ([singleValueXMLElements containsObject:elementName] == YES) {
153             [metaValues setObject:textCurrentElement forKey:mdiName];
154         } else {
155             // must be multi-value
156             NSMutableArray *arr = [metaValues objectForKey:mdiName];
157             if (arr == nil) {
158                 // we have no array yet, create it
159                 arr = [[NSMutableArray new] autorelease];
160                 // and store it
161                 [metaValues setObject:arr forKey:mdiName];
162             }
163             // only store an element once, no need for duplicates
164             if ([arr containsObject:textCurrentElement] == NO) {
165                 [arr addObject:textCurrentElement];
166             }
167         }
168         // cleanup part 1
169         [textCurrentElement release];
170         if (isCustom == YES) {
171             [customAttribute release];
172         }
173     }
175     //cleanup part 2
176     shouldReadCharacters = NO;
177     isCustom = NO;
180 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
182     (void) parser; // unused
183 //    NSLog(@"%@", string);
184     if (shouldReadCharacters == NO) {
185         return;
186     }
188     // this delegate method might be called several times for a single element,
189     // so we have to collect the received data
190     [textCurrentElement appendString:string];
192     //NSLog(@"chars read: %@", string);
195 - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
197     //NSLog(@"parsing finished with error");
198     NSLog(@"Error %li, Description: %@, Line: %li, Column: %li", (long) [parseError code],
199           [[parser parserError] localizedDescription], (long) [parser lineNumber],
200           (long) [parser columnNumber]);
203 @end
205 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */