a
    û#¢jQ  ã                   @   sð   d dl mZ d dlZd dlm  mZ d dlZd dlZd dlZd dl	m
Z
mZ d dlT d dlmZ d dlmZ d dlZd dlZd dlZddgZe e¡Zejd  d	kr´d
d„ ZeZneZe
dƒZg fdd„Zdd„ Zdd„ ZG dd„ de ƒZ!dS )é    )Úprint_functionN)ÚNodeIdÚvalueIsInternalType)Ú*)Úopaque_type_mapping)ÚCSVBSDTypeParserÚNodeSetÚgetSubTypesOfé   c                 C   s   | S ©N© )Úsr   r   úa/mnt/data/dev_pub/qqyu/v2.12.x/application/opensource/open62541/tools/nodeset_compiler/nodeset.pyÚunicode!   s    r   z	ns=0;i=45c                 C   s®   ||v rg S t ƒ }| |¡ |jD ]†}|jtkr"t ƒ }| |¡ | |¡ |j|jkrz|jrz| t	| | j
|j |d�¡ q"|j|jkr"|js"| t	| | j
|j |d�¡ q"|S )N)Ú	skipNodes)ÚsetÚaddÚ
referencesÚreferenceTypeÚ
hassubtypeÚupdateÚsourceÚidÚ	isForwardr	   ÚnodesÚtarget)ÚnodesetÚnoder   ÚreÚrefZskipAllr   r   r   r	   -   s    




c                 C   sÀ   dg}t j| jdd�}d}d}|D ]:}d| ¡ v r8d}nd| ¡ v rP|| } q^|r"|| }q"t|ƒd	kr´t |¡ d
¡}|d	 jD ].}|j	|j
kr–q„|jj|v r¤q„| |jj¡ q„| ¡  |S )Núhttp://opcfoundation.org/UA/úutf-8)ÚencodingFÚ z<namespaceuris>Tz</namespaceuris>r   ZNamespaceUris)ÚcodecsÚopenÚnameÚlowerÚlenÚdomÚparseStringÚgetElementsByTagNameÚ
childNodesÚnodeTypeÚELEMENT_NODEÚ
firstChildÚdataÚappendÚclose)ÚxmlfileÚ
namespacesZinfileZ	foundURIsZnslineÚlineÚnsÚurir   r   r   ÚextractNamespaces=   s,    
r8   c                 C   sH   i }| j D ]8}|j|jkr
| d¡r
| d¡}t|jjƒ}|||< q
|S )zÕParses the <Alias> XML Element present in must XML NodeSet definitions.
       Contents the Alias element are stored in a dictionary for further
       dereferencing during pointer linkage (see linkOpenPointer()).ZAlias)r,   r-   r.   ÚhasAttributeÚgetAttributer   r/   r0   )Ú
xmlelementÚaliasesZalZaliasstZaliasndr   r   r   ÚbuildAliasList]   s    



r=   c                   @   s¾   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	d0dd„Z
d1dd„Zdd„ Zdd„ Zdd„ Zd2dd„Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/S )3r   aÈ   This class handles parsing XML description of namespaces, instantiating
        nodes, linking references, graphing the namespace and compiling a binary
        representation.

        Note that nodes assigned to this class are not restricted to having a
        single namespace ID. This class represents the entire physical address
        space of the binary representation and all nodes that are to be included
        in that segment of memory.
    c                 C   s   i | _ i | _dg| _i | _d S )Nr    )r   r<   r4   ÚnamespaceMapping©Úselfr   r   r   Ú__init__u   s    zNodeSet.__init__c                 C   s¶   | j  ¡ D ] }| ¡ dkr
tdt|ƒ ƒ‚q
| j  ¡ D ]z}|jD ]n}|j|jksdtdt|ƒ d ƒ‚|j| j vr„tdt|ƒ d ƒ‚|j	| j vr@t
| jƒ tdt|ƒ d ƒ‚q@q6d S )NFzFailed to sanitize node z
Reference z has an invalid sourcez has an unknown reference typez has an unknown target)r   ÚvaluesÚsanitizeÚ	ExceptionÚstrr   r   r   r   r   Úprintr4   )r@   Únr   r   r   r   rC   {   s    

zNodeSet.sanitizec                 C   s   || j vr| j  |¡ d S r   )r4   r1   )r@   ZnsURLr   r   r   ÚaddNamespace‹   s    
zNodeSet.addNamespacec                 C   s.   i | _ t|ƒD ]\}}| j |¡| j |< qdS )zsCreates a dict that maps from the nsindex in the original nodeset to the
           nsindex in the combined nodesetN)r>   Ú	enumerater4   Úindex)r@   Úorig_namespacesrJ   r&   r   r   r   ÚcreateNamespaceMapping�   s    zNodeSet.createNamespaceMappingc                    s   t ‡ fdd„| j ¡ D ƒd ƒS )Nc                 3   s   | ]}ˆ |j jkr|V  qd S r   )Ú
browseNamer&   )Ú.0rG   ©Úidstringr   r   Ú	<genexpr>—   ó    z.NodeSet.getNodeByBrowseName.<locals>.<genexpr>)Únextr   rB   )r@   rP   r   rO   r   ÚgetNodeByBrowseName–   s    zNodeSet.getNodeByBrowseNamec                 C   s
   |   d¡S )NZRoot)rT   r?   r   r   r   ÚgetRoot™   s    zNodeSet.getRootFc                 C   sÆ   |j  ¡ }|d d… dkr&|dd … }d }|dkr:t|ƒ}|dkrJt|ƒ}|dkrZt|ƒ}|dkrjt|ƒ}|dkrzt|ƒ}|dkrŠt|ƒ}|d	kršt|ƒ}|d
krªt|ƒ}|d u r¶d S ||_	||_
|S )Né   ZuaZvariableÚobjectÚmethodZ
objecttypeZvariabletypeZ
methodtypeZdatatypeZreferencetype)Ú	localNamer'   ÚVariableNodeÚ
ObjectNodeÚ
MethodNodeÚObjectTypeNodeÚVariableTypeNodeÚDataTypeNodeÚReferenceTypeNodeÚmodelUriÚhidden)r@   r;   ra   rb   Úndtyper   r   r   r   Ú
createNodeœ   s2    
zNodeSet.createNodeTc                 C   s"   || j vrdS | j | }||_dS )NFT)r   rb   )r@   ÚnodeIdrb   r   r   r   r   Ú	hide_nodeº   s
    

zNodeSet.hide_nodec                 G   s   i }|D ]}|  |¡ q|S )z�
        Given any number of dicts, shallow copy and merge into a new dict,
        precedence goes to key value pairs in latter dicts.
        )r   )r@   Ú	dict_argsÚresultÚ
dictionaryr   r   r   Úmerge_dictsÁ   s    zNodeSet.merge_dictsc                 C   sn   t  d|¡}|rN| d¡}| ¡ sN|| jvr0d S | j |¡}d || d¡¡}t|ƒ}|| jvrdd S | j| S )Nzns=([^;]+);(.*)é   zns={};{}rV   )	r   ÚmatchÚgroupÚisdigitr4   rJ   Úformatr   r   )r@   ZidStrÚmr6   re   r   r   r   ÚgetNodeByIDStringË   s    


zNodeSet.getNodeByIDStringc                    s¼   ‡fdd„‰ ˆj D ]š‰ˆjˆjkrbˆj| jvr0qtt‡ ‡fdd„| jˆj j  ¡ ƒƒ| jˆj _ qˆjˆjkrˆj| jvr|qtt‡ ‡fdd„| jˆj j  ¡ ƒƒ| jˆj _ q| jˆj= d S )Nc                    s&   | j |j kp$|jˆ jkp"|jˆ jk S r   )r   r   r   r   )ÚrÚrt)r   r   r   Ú	filterRefÝ   s    ÿz&NodeSet.remove_node.<locals>.filterRefc                    s   ˆ ˆ| d ƒS ©Nr   r   ©rs   ©rt   rr   r   r   Ú<lambda>ç   rR   z%NodeSet.remove_node.<locals>.<lambda>c                    s   ˆ ˆ| d ƒS ru   r   rv   rw   r   r   rx   î   rR   )r   r   r   r   r   ÚdictÚfilterÚitems)r@   r   r   )rt   r   rr   r   Úremove_nodeÛ   s"    
þþzNodeSet.remove_nodeÚUA_TYPESc                 C   s&  |  ¡ }| tj¡r | tj¡}tjdkr4| d¡}t 	dd|¡}t
 |¡ d¡}t|ƒdksjt|ƒdkrzt| | jd ƒ‚|d }z(| d	¡d  d
¡d }|jd j}W n tyÀ   d }Y n0 t|ƒ}	|d u ræt|	ƒdkræ|	d }|d u rþt| | jd ƒ‚|	D ]}
|  |
¡ �q|  |	¡ |jD ]@}|j|jk�r:�q$|j ¡ }d|v �r$|  | jt|ƒ¡| _�q$i }|jD ]„}|j|jk�r†�qp|  |||¡}|�sž�qp| | j¡ | | j ¡ ||_!|j"| j#v �rÜtdt$|j"ƒ ƒ‚|| j#|j"< |||j"< �qp| %¡ D ]"}t&|t'ƒ�rþ|j(| | j d� �qþd S )N©r
   r   r!   ú<([/]?)uax:(.+?)([/]?)>ú<\g<1>\g<2>\g<3>>Ú	UANodeSetr   rk   z# contains no or more then 1 nodesetZModelsZModelZModelUrizQ does not define the nodeset URI in Models/Model/ModelUri or NamespaceUris array.r<   zXMLElement with duplicate ID )r>   ))ÚreadÚ
startswithr$   ÚBOM_UTF8ÚlstripÚsysÚversion_infoÚdecoder   Úsubr)   r*   r+   r(   rD   Z	originXMLÚ
attributesÚ	nodeValuer8   rH   rL   r,   r-   r.   rY   r'   rj   r<   r=   rd   ZreplaceAliasesZreplaceNamespacesr>   Ú
typesArrayr   r   rE   rB   Ú
isinstancer_   ZbuildEncoding)r@   r3   rb   rŒ   ÚfileContentÚnodesetsr   ZmodelTagra   rK   r6   Úndrc   Znewnodesr   rG   r   r   r   Ú
addNodeSetô   s\    







zNodeSet.addNodeSetc                 C   sd   | j | }|jD ]>}|jjdkr|jjdkr| j |j }|jjdkr|j  S qtdt	|ƒ ƒ‚dS )a  
        The node should have a 'HasEncoding' forward reference which points to the encoding ids.
        These can be XML Encoding or Binary Encoding. Therefore we also need to check if the SymbolicName
        of the target node is "DefaultBinary"
        r   é&   ZDefaultBinaryz+No DefaultBinary encoding defined for node N)
r   r   r   r6   Úir   ÚsymbolicNameÚvaluerD   rE   )r@   re   r   r   ZrefNoder   r   r   ÚgetBinaryEncodingIdForNode?  s    

z"NodeSet.getBinaryEncodingIdForNodec                 C   s(   | j  ¡ D ]}t|tƒr
| | ¡ q
d S r   )r   rB   r�   rZ   ZallocateValue)r@   rG   r   r   r   ÚallocateVariablesM  s    
zNodeSet.allocateVariablesc                 C   sV   |d u rd S |j jtvr|S |jD ].}|jr.q"|jjdkr"|  | j|j	 ¡  S q"|S )Né-   )
rM   r&   r   r   r   r   r“   ÚgetBaseDataTyper   r   ©r@   r   r   r   r   r   r™   R  s    
zNodeSet.getBaseDataTypec                 C   s2   |j D ]&}|jjdkr|jr| j|j   S qd S )Né(   )r   r   r“   r   r   r   rš   r   r   r   ÚgetNodeTypeDefinition^  s    
zNodeSet.getNodeTypeDefinitionc                 C   s†   t |tƒr8t|ƒs$t d| ¡ d S | jt| j| ƒ S t |tƒr‚|jdkrPd S | j| }t |t	ƒs~t dt
|ƒ d ¡ d S |S d S )NzNot a valid dataType string: r   zNode id z# is not reference a valid dataType.)r�   Ústring_typesr   ÚloggerÚerrorr   r   r<   r“   r_   rE   )r@   ÚdataTypeZdataTypeNoder   r   r   ÚgetDataTypeNodee  s    




zNodeSet.getDataTypeNodec                 C   s`   t ƒ }| t| |  d¡g ƒ¡ | t| |  d¡g ƒ¡ | t| |  d¡g ƒ¡ ttdd„ |ƒƒS )NÚHierarchicalReferencesZHasEncodingZHasTypeDefinitionc                 S   s   | j S r   ©r   ©Úxr   r   r   rx   z  rR   z7NodeSet.getRelevantOrderingReferences.<locals>.<lambda>)r   r   r	   rT   ÚlistÚmap)r@   Zrelevant_typesr   r   r   ÚgetRelevantOrderingReferencesu  s
    z%NodeSet.getRelevantOrderingReferencesc                 C   sN   | j  ¡ D ]>}|j ¡ D ].}t|j|j|j|j ƒ}d | j |j j|< qq
d S r   )	r   rB   r   ÚcopyZ	Referencer   r   r   r   )r@   Úur   Zbackr   r   r   ÚaddInverseReferences|  s    zNodeSet.addInverseReferencesc                 C   s˜   t | |  d¡ƒ}ttdd„ |ƒƒ}| j ¡ D ]f}|jjdkrJ|jjdv rJq,| 	|¡}|d ur,| j|j
 |_|js„td t|jƒ¡ƒ‚| j|j |_q,d S )Nr¢   c                 S   s   | j S r   r£   r¤   r   r   r   rx   …  rR   z'NodeSet.setNodeParent.<locals>.<lambda>r   )éN   éP   éT   z#Node {}: Did not find parent node: )r	   rT   r¦   r§   r   rB   r   r6   r“   ZgetParentReferencer   ÚparentÚRuntimeErrorro   rE   r   ZparentReference)r@   Zparentreftypesr   Z	parentrefr   r   r   ÚsetNodeParentƒ  s    
zNodeSet.setNodeParentc              
   C   s|  g | _ g }g }|D �]p}|jdkr$qt|jdƒ}| ¡ }| tj¡rP| tj¡}tj	dkrd| 
d¡}t dd|¡}t |¡ d¡}	t|	ƒdksšt|	ƒd	kr¢td
ƒ‚|	d }
|
 d¡}|D ]Ê}| d¡rît d|jd j¡�s|jd jdk�s| d¡r¸| d¡s¸t d|jd j¡r¸| d¡d  d¡d }tjddd�}| t |jj¡¡ | ¡  | j  |j¡ | ¡  d|j }| |¡ q¸q|D �]Ž}t|jdƒ}| ¡ }| tj¡�r¾| tj¡}tj	dk�rÔ| 
d¡}t dd|¡}t |¡ d¡}	t|	ƒdk�st|	ƒd	k�rtd
ƒ‚|	d }
|
 d¡}|D ]ê}| d¡�rdt d|jd j¡�s’|jd jdk�s’| d¡�r,| d¡�s,t d|jd j¡�r,| d¡d  d¡d }tjdd�}| t |jj¡¡ | ¡  |  d¡ t! "|¡}| j  |j¡ t!j#|ddd�}d|_$| |¡ �q,�qŠg }g }g }g }d}d}|D ]}| |¡ �q8t%||||||||| j&ƒ	| _'| j' (¡  | ¡  d S )Nz)deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xmlÚrbr~   r!   r   r€   r�   r   rk   z"contains no or more then 1 nodesetZ
UAVariableÚSymbolicNamez.*_BinarySchemaZTypeDictionary_BinarySchemaZParentNodeIdzi=93ÚValueÚ
ByteStringFz.bsd)ÚdeleteÚsuffixz	UA_TYPES#)r·   zUTF-8Ú
)Únewlinerr   TÚoutname))Z	all_filesr&   r%   r‚   rƒ   r$   r„   r…   r†   r‡   rˆ   r   r‰   r)   r*   r+   r(   rD   r9   rl   rŠ   r‹   Ú	fullmatchÚtempfileZNamedTemporaryFileÚwriteÚbase64Ú	b64decoder/   Úflushr1   r2   ÚseekÚioÚBufferedReaderÚTextIOWrapperÚmoder   r4   ÚparserÚcreate_types)r@   ÚexistingÚinfilesÚbsdFileZ
import_bsdÚtype_bsdr3   Únodeset_baserŽ   r�   r   ZvariableNodesr�   Ztype_contentÚfZbsdZbfÚtmpÚ
opaque_mapÚselected_typesÚtype_csvÚtype_xmlÚ
no_builtinrº   r   r   r   ÚgenerateParser–  s„    




Z



b


ÿ
zNodeSet.generateParserN)F)T)Fr}   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rA   rC   rH   rL   rT   rU   rd   rf   rj   rq   r|   r‘   r–   r—   r™   rœ   r¡   r¨   r«   r±   rÔ   r   r   r   r   r   j   s,   




K)"Z
__future__r   r†   Úxml.dom.minidomr)   ÚminidomÚloggingr$   r   Ú	datatypesr   r   r   r   Útype_parserr   rÂ   r¼   r¾   Ú__all__Ú	getLoggerrÕ   rž   r‡   r   rE   r�   Z
basestringr   r	   r8   r=   rW   r   r   r   r   r   Ú<module>   s.   
 