Completed
Push — master ( eb5e78...c75f71 )
by Olivier
04:30
created

XmlImporter   F

Complexity

Total Complexity 62

Size/Duplication

Total Lines 221
Duplicated Lines 32.13 %

Test Coverage

Coverage 42.68%

Importance

Changes 0
Metric Value
dl 71
loc 221
ccs 70
cts 164
cp 0.4268
rs 3.8461
c 0
b 0
f 0
wmc 62

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 4 1
B to_nodeid() 0 13 5
D add_variable() 0 24 8
B add_reference() 0 15 5
B add_variable_type() 19 19 7
A add_datatype() 12 12 3
A _add_refs() 0 13 3
C _add_variable_value() 0 28 7
A _get_node() 0 12 4
A add_object_type() 11 11 2
A add_object() 11 11 2
F import_xml() 0 26 9
B add_method() 18 18 6

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like XmlImporter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
2
add node defined in XML to address space
3
format is the one from opc-ua specification
4
"""
5 1
import logging
6
7
8 1
from opcua import ua
9 1
from opcua.common import xmlparser
10
11
12 1
class XmlImporter(object):
13
14 1
    def __init__(self, server):
15 1
        self.logger = logging.getLogger(__name__)
16 1
        self.parser = None
17 1
        self.server = server
18
19 1
    def import_xml(self, xmlpath, act_server):
20 1
        """
21 1
        import xml and return added nodes
22 1
        """
23 1
        self.logger.info("Importing XML file %s", xmlpath)
24 1
        self.parser = xmlparser.XMLParser(xmlpath, act_server)
25 1
        nodes = []
26
        for node in self.parser:
27 1
            if node.nodetype == 'UAObject':
28 1
                node = self.add_object(node)
29
            elif node.nodetype == 'UAObjectType':
30
                node = self.add_object_type(node)
31
            elif node.nodetype == 'UAVariable':
32
                node = self.add_variable(node)
33
            elif node.nodetype == 'UAVariableType':
34
                node = self.add_variable_type(node)
35
            elif node.nodetype == 'UAReferenceType':
36
                node = self.add_reference(node)
37
            elif node.nodetype == 'UADataType':
38
                node = self.add_datatype(node)
39
            elif node.nodetype == 'UAMethod':
40 1
                node = self.add_method(node)
41 1
            else:
42 1
                self.logger.info("Not implemented node type: %s ", node.nodetype)
43 1
            nodes.append(node)
44 1
        return nodes
45 1
46 1
    def _get_node(self, obj):
47 1
        node = ua.AddNodesItem()
48 1
        node.RequestedNewNodeId = ua.NodeId.from_string(obj.nodeid)
49 1
        node.BrowseName = ua.QualifiedName.from_string(obj.browsename)
50 1
        node.NodeClass = getattr(ua.NodeClass, obj.nodetype[2:])
51 1
        if obj.parent:
52
            node.ParentNodeId = ua.NodeId.from_string(obj.parent)
53 1
        if obj.parentlink:
54 1
            node.ReferenceTypeId = self.to_nodeid(obj.parentlink)
55
        if obj.typedef:
56 1
            node.TypeDefinition = ua.NodeId.from_string(obj.typedef)
57
        return node
58
59 1
    def to_nodeid(self, nodeid):
60
        if not nodeid:
61 1
            return ua.NodeId(ua.ObjectIds.String)
62 1
        elif "=" in nodeid:
63 1
            return ua.NodeId.from_string(nodeid)
64
        elif hasattr(ua.ObjectIds, nodeid):
65
            return ua.NodeId(getattr(ua.ObjectIds, nodeid))
66 1
        else:
67
            if nodeid in self.parser.aliases:
68 1
                nodeid = self.parser.aliases[nodeid]
69
            else:
70 1
                nodeid = "i={}".format(getattr(ua.ObjectIds, nodeid))
71 1
            return ua.NodeId.from_string(nodeid)
72 1
73 1 View Code Duplication
    def add_object(self, obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
74 1
        node = self._get_node(obj)
75 1
        attrs = ua.ObjectAttributes()
76 1
        if obj.desc:
77 1
            attrs.Description = ua.LocalizedText(obj.desc)
78 1
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
79 1
        attrs.EventNotifier = obj.eventnotifier
80
        node.NodeAttributes = attrs
81 1
        res = self.server.add_nodes([node])
82
        self._add_refs(obj)
83
        return res[0].AddedNodeId
84
85 View Code Duplication
    def add_object_type(self, obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
86
        node = self._get_node(obj)
87
        attrs = ua.ObjectTypeAttributes()
88
        if obj.desc:
89
            attrs.Description = ua.LocalizedText(obj.desc)
90
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
91
        attrs.IsAbstract = obj.abstract
92 1
        node.NodeAttributes = attrs
93 1
        res = self.server.add_nodes([node])
94 1
        self._add_refs(obj)
95 1
        return res[0].AddedNodeId
96
97 1
    def add_variable(self, obj):
98 1
        node = self._get_node(obj)
99
        attrs = ua.VariableAttributes()
100 1
        if obj.desc:
101 1
            attrs.Description = ua.LocalizedText(obj.desc)
102 1
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
103 1
        attrs.DataType = self.to_nodeid(obj.datatype)
104 1
        # if obj.value and len(obj.value) == 1:
105
        if obj.value is not None:
106 1
            attrs.Value = self._add_variable_value(obj, )
107
        if obj.rank:
108 1
            attrs.ValueRank = obj.rank
109
        if obj.accesslevel:
110 1
            attrs.AccessLevel = obj.accesslevel
111
        if obj.useraccesslevel:
112 1
            attrs.UserAccessLevel = obj.useraccesslevel
113 1
        if obj.minsample:
114 1
            attrs.MinimumSamplingInterval = obj.minsample
115
        if obj.dimensions:
116 1
            attrs.ArrayDimensions = obj.dimensions
117
        node.NodeAttributes = attrs
118
        res = self.server.add_nodes([node])
119
        self._add_refs(obj)
120
        return res[0].AddedNodeId
121
122
    def _add_variable_value(self, obj):
123
        """
124
        Returns the value for a Variable based on the objects valuetype. 
125
        """
126
        if obj.valuetype == 'ListOfLocalizedText':
127
            return ua.Variant([ua.LocalizedText(txt) for txt in obj.value], None)
128
        elif obj.valuetype == 'EnumValueType':
129
            values = []
130
            for ev in obj.value:
131
                enum_value = ua.EnumValueType()
132
                enum_value.DisplayName = ua.LocalizedText(ev['DisplayName'])
133
                enum_value.Description = ua.LocalizedText(ev['Description'])
134
                enum_value.Value = int(ev['Value'])
135 1
                values.append(enum_value)
136
            return values
137
        elif obj.valuetype == 'Argument':
138
            values = []
139
            for arg in obj.value:
140
                argument = ua.Argument()
141
                argument.Name = arg['Name']
142
                argument.Description = ua.LocalizedText(arg['Description'])
143
                argument.DataType = self.to_nodeid(arg['DataType'])
144
                argument.ValueRank = int(arg['ValueRank'])
145
                argument.ArrayDimensions = arg['ArrayDimensions']
146
                values.append(argument)
147
            return values
148
149
        return ua.Variant(obj.value, getattr(ua.VariantType, obj.valuetype))
150
151
152 View Code Duplication
    def add_variable_type(self, obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
153 1
        node = self._get_node(obj)
154
        attrs = ua.VariableTypeAttributes()
155
        if obj.desc:
156
            attrs.Description = ua.LocalizedText(obj.desc)
157
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
158
        attrs.DataType = self.to_nodeid(obj.datatype)
159
        if obj.value and len(obj.value) == 1:
160
            attrs.Value = obj.value[0]
161
        if obj.rank:
162
            attrs.ValueRank = obj.rank
163
        if obj.abstract:
164
            attrs.IsAbstract = obj.abstract
165
        if obj.dimensions:
166
            attrs.ArrayDimensions = obj.dimensions
167
        node.NodeAttributes = attrs
168
        res = self.server.add_nodes([node])
169 1
        self._add_refs(obj)
170
        return res[0].AddedNodeId
171
172 View Code Duplication
    def add_method(self, obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
173
        node = self._get_node(obj)
174
        attrs = ua.MethodAttributes()
175
        if obj.desc:
176
            attrs.Description = ua.LocalizedText(obj.desc)
177
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
178
        if obj.accesslevel:
179
            attrs.AccessLevel = obj.accesslevel
180
        if obj.useraccesslevel:
181 1
            attrs.UserAccessLevel = obj.useraccesslevel
182 1
        if obj.minsample:
183 1
            attrs.MinimumSamplingInterval = obj.minsample
184
        if obj.dimensions:
185
            attrs.ArrayDimensions = obj.dimensions
186
        node.NodeAttributes = attrs
187
        res = self.server.add_nodes([node])
188
        self._add_refs(obj)
189
        return res[0].AddedNodeId
190
191
    def add_reference(self, obj):
192
        node = self._get_node(obj)
193
        attrs = ua.ReferenceTypeAttributes()
194
        if obj.desc:
195
            attrs.Description = ua.LocalizedText(obj.desc)
196
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
197
        if obj. inversename:
198
            attrs.InverseName = ua.LocalizedText(obj.inversename)
199
        if obj.abstract:
200
            attrs.IsAbstract = obj.abstract
201
        if obj.symmetric:
202
            attrs.Symmetric = obj.symmetric
203
        node.NodeAttributes = attrs
204
        res = self.server.add_nodes([node])
205
        self._add_refs(obj)
206
207 View Code Duplication
    def add_datatype(self, obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
208
        node = self._get_node(obj)
209
        attrs = ua.DataTypeAttributes()
210
        if obj.desc:
211
            attrs.Description = ua.LocalizedText(obj.desc)
212
        attrs.DisplayName = ua.LocalizedText(obj.displayname)
213
        if obj.abstract:
214
            attrs.IsAbstract = obj.abstract
215
        node.NodeAttributes = attrs
216
        res = self.server.add_nodes([node])
217
        self._add_refs(obj)
218
        return res[0].AddedNodeId
219
220
    def _add_refs(self, obj):
221
        if not obj.refs:
222
            return
223
        refs = []
224
        for data in obj.refs:
225
            ref = ua.AddReferencesItem()
226
            ref.IsForward = True
227
            ref.ReferenceTypeId = self.to_nodeid(data.reftype)
228
            ref.SourceNodeId = ua.NodeId.from_string(obj.nodeid)
229
            ref.TargetNodeClass = ua.NodeClass.DataType
230
            ref.TargetNodeId = ua.NodeId.from_string(data.target)
231
            refs.append(ref)
232
        self.server.add_references(refs)
233