Completed
Push — master ( 331382...9398d4 )
by Olivier
04:19
created

XmlImporter   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 192
Duplicated Lines 18.23 %

Test Coverage

Coverage 42.68%

Importance

Changes 0
Metric Value
dl 35
loc 192
ccs 70
cts 164
cp 0.4268
rs 4.5454
c 0
b 0
f 0
wmc 59

12 Methods

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