1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 #------------------------------------------------------------------------------- |
|
17 # package: SysDefParser |
|
18 # |
|
19 # usage: Wrapper for an XML parser to dispatch callbacks to a client object which |
|
20 # analyses the parsed XML data. The auxiliary package SysDefParser::Dispatcher |
|
21 # acts as an intermediary between the parser and the client to convert function |
|
22 # callbacks to method callbacks using perl's AUTOLOAD mechanism. |
|
23 # |
|
24 # public methods: |
|
25 # |
|
26 # new(-client => <client reference>, [-parser => <package name>]) : creates a |
|
27 # instance. <client reference> is the instance to which the parser callbacks |
|
28 # are dispatched. <package name> is an optional alternative parser client |
|
29 # package to use instead of the default XML::Parser class. |
|
30 # |
|
31 # parse(<fileh>): parse the XML data from filehandle <fileh> dispatching |
|
32 # callbacks to the client object. |
|
33 # |
|
34 #------------------------------------------------------------------------------- |
|
35 |
|
36 package SysDefParser; |
|
37 use strict; |
|
38 |
|
39 sub new |
|
40 { |
|
41 my ($class, %args) = @_; |
|
42 my $self = bless {}, $class; |
|
43 $self->{client} = delete $args{-client}; |
|
44 |
|
45 if (exists $args{-parser}) |
|
46 { |
|
47 $args{Pkg} = 'SysDefParser::Dispatcher'; |
|
48 require $args{-parser}; |
|
49 $self->{parser} = $args{-parser}->createParser(%args); |
|
50 } |
|
51 else |
|
52 { |
|
53 $self->{parser} = $class->_createParser(%args); |
|
54 } |
|
55 |
|
56 return $self; |
|
57 } |
|
58 |
|
59 sub _createParser |
|
60 { |
|
61 my ($class, %args) = @_; |
|
62 require XML::Parser; |
|
63 return XML::Parser->new |
|
64 ( |
|
65 Style => 'Subs', |
|
66 Pkg => 'SysDefParser::Dispatcher', |
|
67 ErrorContext => 2 |
|
68 ); |
|
69 } |
|
70 |
|
71 my $PARSERCLIENT = undef; |
|
72 |
|
73 sub _client { return $PARSERCLIENT; } |
|
74 |
|
75 sub parse |
|
76 { |
|
77 my ($self, $fileh) = @_; |
|
78 |
|
79 # we can't pass any context down to the underlying parser so that we can work out which |
|
80 # object any callbacks from the parser are associated with so, assuming that the parser will |
|
81 # not be called in a re-entrant fashion, we store the context at this point, so that we can |
|
82 # then dispatch the callbacks from the parsers 'parse' method to those methods of the saved |
|
83 # $PARSERCLIENT instance. |
|
84 |
|
85 die "Fatal: client object not set\n" if ! defined $self->{client}; |
|
86 die "Fatal: parser client object already set\n" if defined $PARSERCLIENT; |
|
87 $PARSERCLIENT = $self->{client}; |
|
88 |
|
89 # call the parser, callbacks will be dispatched to sub AUTOLOAD in SysDefParser::Dispatcher |
|
90 |
|
91 my $rv =$self->{parser}->parse($fileh); |
|
92 |
|
93 # finished parsing, unset the context |
|
94 |
|
95 $PARSERCLIENT = undef; |
|
96 |
|
97 return $rv; |
|
98 } |
|
99 |
|
100 #------------------------------------------------------------------------------- |
|
101 # package SysDefParser::Dispatcher |
|
102 # |
|
103 # usage: Internal package. Uses AUTOLOAD mechanism to receive parser callbacks and |
|
104 # convert them to object method calls on teh client object. |
|
105 # |
|
106 #------------------------------------------------------------------------------- |
|
107 package SysDefParser::Dispatcher; |
|
108 use strict; |
|
109 |
|
110 sub AUTOLOAD |
|
111 { |
|
112 my @ARGS = @_; |
|
113 |
|
114 my $client = SysDefParser::_client(); |
|
115 |
|
116 die "Fatal: parser client object not set\n" if ! defined $client; |
|
117 |
|
118 # translate the called back function name to the client method name |
|
119 my $clientpkg = ref($client); |
|
120 my $method = $SysDefParser::Dispatcher::AUTOLOAD; |
|
121 |
|
122 $method =~ s/^SysDefParser::Dispatcher/$clientpkg/; |
|
123 |
|
124 # dispatch the parser's callback to the client object (if implemented by client) |
|
125 $client->$method(@ARGS) if $client->can($method); |
|
126 } |
|
127 |
|
128 #------------------------------------------------------------------------------- |
|
129 # -EOF- |
|
130 #------------------------------------------------------------------------------- |
|
131 1; |
|