|
1 .. _plugin-howto-plugin-interface: |
|
2 |
|
3 Plug-in interface |
|
4 ================= |
|
5 |
|
6 A ConE plug-in has two points for interfacing with ConE: |
|
7 |
|
8 #. Reader classes that derive from ``cone.public.plugin.ReaderBase`` . These classes |
|
9 define supported Implementation Markup Languages (i.e. supported XML namespaces) |
|
10 and other attributes related to them like file extensions. As the name suggests, they are |
|
11 also responsible for reading implementation instances from XML data. |
|
12 #. Implementation classes that derive from ``cone.public.plugin.ImplBase``. These classes |
|
13 supply the actual run-time functionality of the plug-ins. |
|
14 |
|
15 The following UML diagram shows the most important classes and their interdependencies: |
|
16 |
|
17 .. image:: plugin_classes.jpg |
|
18 |
|
19 ConE generation can be seen to consist of two phases, implementation parsing |
|
20 and output generation: |
|
21 |
|
22 Parsing phase: |
|
23 |
|
24 - Implementation file list is filtered based on a user-given file name pattern |
|
25 and supported file extensions |
|
26 - All remaining files are parsed into ``ElementTree`` instances |
|
27 - The ``ElementTree`` instance is scanned for supported ImplML namespaces and |
|
28 implementation instances are created using the correct reader classes |
|
29 (the ``read_impl()`` method) |
|
30 - All implementations are collected into an ``ImplSet`` instance |
|
31 |
|
32 Generation phase: |
|
33 |
|
34 - Implementation instances are further filtered using tags and ConfML references |
|
35 (the ``has_tag()`` and ``has_ref()`` methods) |
|
36 - Implementations instances are divided into separate sets based on their invocation |
|
37 phases |
|
38 - Output is generated using each implementation set. For each implementation set: |
|
39 |
|
40 - The ``generation_context`` variable of each implementation instance is set |
|
41 (this context contains generation-scope information implementations instances may use) |
|
42 - The ``generate()`` method of each instance is called |
|
43 - The ``post_generate()`` method of each instance is called |
|
44 |
|
45 From a plug-in's point of view, the sequence of method calls goes as follows: |
|
46 |
|
47 .. image:: plugin_lifecycle.jpg |
|
48 |
|
49 Explanations of the steps in the diagram: |
|
50 |
|
51 ====== ======================================================================== |
|
52 Step Explanation |
|
53 ====== ======================================================================== |
|
54 1 ``read_impl()`` is called to create an implementation instance based on |
|
55 XML data. |
|
56 2 ``read_impl()`` creates the instance. |
|
57 3-6 Filtering based on ConfML references and implementation tags is done. |
|
58 The implementation instance returns True in all cases, so it is included |
|
59 in the actual generation. |
|
60 7-8 The instance is asked for its invocation phase (here it returns "normal") |
|
61 9 The implementation instance's ``generation_context`` variable is set, so |
|
62 then it can be used in the actual generation. |
|
63 10-11 Output generation methods are called |
|
64 ====== ======================================================================== |
|
65 |
|
66 Plug-in interface class source |
|
67 ------------------------------ |
|
68 |
|
69 The following source listings show the most important parts of the ``ImplReader`` |
|
70 and ``ImplBase`` classes from a plug-in's point of view: |
|
71 |
|
72 .. code-block:: python |
|
73 |
|
74 class ReaderBase(object): |
|
75 """ |
|
76 Base class for implementation readers. |
|
77 |
|
78 Each reader class supports one XML namespace, from which it reads an implementation |
|
79 instance. |
|
80 |
|
81 The method for parsing an implementation (read_impl()) is given an ElementTree |
|
82 XML element as the root from which to parse the implementation. The plug-in |
|
83 machinery handles each XML file so that the correct reader class is used to read |
|
84 the implementations from XML elements based on the namespaces. |
|
85 """ |
|
86 |
|
87 # The XML namespace supported by the implementation reader. |
|
88 # Should be something like "http://www.xyz.org/xml/1". |
|
89 # Can also be None, in which case the reader will not be used |
|
90 # (this can be useful for defining base classes for e.g. readers |
|
91 # for different versions of an implementation). |
|
92 NAMESPACE = None |
|
93 |
|
94 # Any extra XML namespaces that should be ignored by the |
|
95 # implementation parsing machinery. This is useful for specifying |
|
96 # namespaces that are not actual ImplML namespaces, but are used |
|
97 # inside an implementation (e.g. XInclude) |
|
98 IGNORED_NAMESPACES = [] |
|
99 |
|
100 # Supported implementation file extensions. |
|
101 # Sub-classes can override this to add new supported file extensions |
|
102 # if necessary. The file extensions simply control whether implementations |
|
103 # are attempted to be read from a file or not. |
|
104 # Note that the extensions are case-insensitive. |
|
105 FILE_EXTENSIONS = ['implml'] |
|
106 |
|
107 @classmethod |
|
108 def read_impl(cls, resource_ref, configuration, doc_root): |
|
109 """ |
|
110 Read an implementation instance from the given element tree. |
|
111 |
|
112 @param resource_ref: Reference to the resource in the configuration in |
|
113 which the given document root resides. |
|
114 @param configuration: The configuration used. |
|
115 @param doc_root: The document root from which to parse the implementation. |
|
116 @return: The read implementation instance, or None. |
|
117 """ |
|
118 raise exceptions.NotSupportedException() |
|
119 |
|
120 .. code-block:: python |
|
121 |
|
122 class GenerationContext(object): |
|
123 """ |
|
124 Context object that can be used for passing generation-scope |
|
125 data to implementation instances. |
|
126 """ |
|
127 |
|
128 def __init__(self, tags={}): |
|
129 # The tags used in this generation context |
|
130 # (i.e. the tags passed from command line) |
|
131 self.tags = tags |
|
132 |
|
133 # A dictionary that implementation instances can use to |
|
134 # pass any data between each other |
|
135 self.impl_data_dict = {} |
|
136 |
|
137 .. code-block:: python |
|
138 |
|
139 class ImplBase(object): |
|
140 """ |
|
141 Base class for any confml implementation. |
|
142 """ |
|
143 |
|
144 # Identifier for the implementation type, used e.g. in .cfg files. |
|
145 # Should be a string like e.g. 'someml'. |
|
146 IMPL_TYPE_ID = None |
|
147 |
|
148 # Defines the default invocation phase for the implementation. |
|
149 # The default is used if the phase is not explicitly set in the |
|
150 # ImplML file or manually overridden by calling set_invocation_phase() |
|
151 DEFAULT_INVOCATION_PHASE = None |
|
152 |
|
153 def __init__(self,ref, configuration): |
|
154 """ |
|
155 Create a ImplBase object |
|
156 @param ref : the ref to the Implml file resource. |
|
157 @param configuration : the Configuration instance for the |
|
158 configuration data. |
|
159 """ |
|
160 self._settings = None |
|
161 self.ref = ref |
|
162 self.index = None |
|
163 self.configuration = configuration |
|
164 self.output_root = self.settings.get('output_root','output') |
|
165 self.output_subdir = self.settings.get('output_subdir','') |
|
166 self.plugin_output = self.settings.get('plugin_output','') |
|
167 |
|
168 self.generation_context = None |
|
169 self._tags = None |
|
170 self._invocation_phase = None |
|
171 self._tempvar_defs = [] |
|
172 |
|
173 def generate(self): |
|
174 """ |
|
175 Generate the given implementation. |
|
176 @return: |
|
177 """ |
|
178 raise exceptions.NotSupportedException() |
|
179 |
|
180 def post_generate(self): |
|
181 """ |
|
182 Called when all normal generation has been done. |
|
183 |
|
184 @attention: This is a temporary method used for implementing cenrep_rfs.txt generation. |
|
185 """ |
|
186 pass |
|
187 |
|
188 def list_output_files(self): |
|
189 """ |
|
190 Return a list of output files as an array. |
|
191 """ |
|
192 raise exceptions.NotSupportedException() |
|
193 |
|
194 def get_refs(self): |
|
195 """ |
|
196 Return a list of all ConfML setting references that affect this |
|
197 implementation. May also return None if references are not relevant |
|
198 for the implementation. |
|
199 """ |
|
200 return None |