0
|
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
|