summaryrefslogtreecommitdiff
path: root/XMPCore/source/StructureNodeImpl.cpp
blob: 3c91cedf2e43cf243ecf136888a980b346d088d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// =================================================================================================
// Copyright Adobe
// Copyright 2014 Adobe
// All Rights Reserved
//
// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it. 
// =================================================================================================

#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1
	#include "XMPCore/ImplHeaders/StructureNodeImpl.h"
	#include "XMPCore/ImplHeaders/TNodeIteratorImpl.h"
#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED

#include "XMPCommon/Interfaces/IError_I.h"
#include "XMPCore/XMPCoreErrorCodes.h"
#include "XMPCommon/Interfaces/IUTF8String_I.h"
#include "XMPCommon/Utilities/AutoSharedLock.h"
#include "XMPCore/Interfaces/INodeIterator_I.h"
#include "XMPCommon/Utilities/TSmartPointers_I.h"

namespace AdobeXMPCore_Int {

	// All virtual functions
	
	StructureNodeImpl::StructureNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength )
		: NodeImpl( nameSpace, nameSpaceLength, name, nameLength ) { }

	spINode APICALL StructureNodeImpl::GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) {
		if ( nameSpace->size() == 0 || name->size() == 0 )
			return spINode();
		QualifiedName qName( nameSpace, name );
		AutoSharedLock lock( mSharedMutex );
		auto it = mChildrenMap.find( qName );
		if ( it != mChildrenMap.end() )
			return MakeUncheckedSharedPointer( it->second.get(), __FILE__, __LINE__ );
		return spINode();
	}

	spINode APICALL StructureNodeImpl::GetNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) {
		spIUTF8String nameSpaceStr( IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ) );
		spIUTF8String nameStr( IUTF8String_I::CreateUTF8String( name, nameLength ) );
		return GetNode( nameSpaceStr, nameStr );
	}

	spINode APICALL StructureNodeImpl::RemoveNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) {
		if ( nameSpace->size() == 0 || name->size() == 0 )
			return spINode();
		QualifiedName qName( nameSpace, name );
		AutoSharedLock lock( mSharedMutex, true );
		auto it = mChildrenMap.find( qName );
		if ( it == mChildrenMap.end() ) {
			return spINode();
		} else {
			spINode node = it->second;
			mChildrenMap.erase( it );
			node->GetINode_I()->ChangeParent( NULL );
			return node;
		}
	}

	spINode APICALL StructureNodeImpl::RemoveNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) {
		spIUTF8String nameSpaceStr( IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ) );
		spIUTF8String nameStr( IUTF8String_I::CreateUTF8String( name, nameLength ) );
		return RemoveNode( nameSpaceStr, nameStr );
	}

	INode_v1::eNodeType APICALL StructureNodeImpl::GetChildNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) const {
		auto node = GetNode( nameSpace, nameSpaceLength, name, nameLength );
		if ( node )
			return node->GetNodeType();
		return INode::kNTNone;
	}

	INode_v1::eNodeType APICALL StructureNodeImpl::GetNodeType() const {
		return INode_v1::kNTStructure;
	}

	void APICALL StructureNodeImpl::InsertNode( const spINode & node ) {
		if ( !CheckSuitabilityToBeUsedAsChildNode( node ) )
			return;
		QualifiedName qName( node->GetNameSpace(), node->GetName() );
		AutoSharedLock lock( mSharedMutex, true );
		auto it = mChildrenMap.find( qName );
		if ( it == mChildrenMap.end() ) {
			mChildrenMap[ qName ] = MakeUncheckedSharedPointer( node.get(), __FILE__, __LINE__ );
			node->GetINode_I()->ChangeParent( this );
		} else {
			NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNodeAlreadyExists,
				"a node already exists with the same qualified name", IError_v1::kESOperationFatal,
				true, node->GetNameSpace(), true, node->GetName() );
		}
	}

	spINode APICALL StructureNodeImpl::ReplaceNode( const spINode & node ) {
		if ( CheckSuitabilityToBeUsedAsChildNode( node ) && GetNode( node->GetNameSpace(), node->GetName() ) ) {
			auto retValue = RemoveNode( node->GetNameSpace(), node->GetName() );
			InsertNode( node );
			return retValue;
		} else {
			NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNoSuchNodeExists,
				"no such node exists with the specified qualified name", IError_v1::kESOperationFatal,
				true, node->GetNameSpace(), true, node->GetName() );
		}
		return spINode();
	}

	void APICALL StructureNodeImpl::AppendNode( const spINode & node ) {
		InsertNode( node );
	}

	spINodeIterator APICALL StructureNodeImpl::Iterator() {
		AutoSharedLock lock( mSharedMutex );
		auto beginIt = mChildrenMap.begin(), endIt = mChildrenMap.end();
		if ( beginIt == endIt )
			return spINodeIterator();
		else
			return MakeUncheckedSharedPointer( new TNodeIteratorImpl< QualifiedNameNodeMap::iterator >( beginIt, endIt ), __FILE__, __LINE__, true );
	}

	sizet APICALL StructureNodeImpl::ChildCount() const __NOTHROW__ {
		AutoSharedLock lock( mSharedMutex );
		return mChildrenMap.size();
	}

	spIStructureNode APICALL StructureNodeImpl::ConvertToStructureNode() {
		return MakeUncheckedSharedPointer( this, __FILE__, __LINE__ );
	}

	bool APICALL StructureNodeImpl::HasContent() const {
		AutoSharedLock lock( mSharedMutex );
		return mChildrenMap.size() > 0;
	}

	bool StructureNodeImpl::ValidateNameOrNameSpaceChangeForAChild( const spcIUTF8String & currentNameSpace, const spcIUTF8String & currentName, const spcIUTF8String & newNameSpace, const spcIUTF8String & newName ) {
		auto node = GetNode( newNameSpace, newNameSpace );
		if ( node ) {
			return false;
		} else {
			node = RemoveNode( currentNameSpace, currentName );
			AutoSharedLock( mSharedMutex, true );
			mChildrenMap[ QualifiedName( newNameSpace, newName ) ] = node;
			return true;
		}
	}

	void APICALL StructureNodeImpl::ClearContents() {
		AutoSharedLock lock( mSharedMutex, true );
		for ( auto it = mChildrenMap.begin(), itEnd = mChildrenMap.end(); it != itEnd; ++it ) {
			it->second->GetINode_I()->ChangeParent( NULL );
		}
		mChildrenMap.clear();
	}

	spINode APICALL StructureNodeImpl::CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const {
		AutoSharedLock lock( mSharedMutex );
		spIStructureNode newNode;
		if ( ignoreEmptyNodes && mChildrenMap.size() == 0 ) {
			if ( ignoreNodesWithOnlyQualifiers )
				return newNode;
			else if ( !ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 )
				return newNode;
		}

		newNode = IStructureNode_I::CreateStructureNode( mNameSpace, mName );

		auto endIt = mChildrenMap.end();
		for ( auto it = mChildrenMap.begin(); it != endIt; ++it ) {
			spINode childNode = it->second->Clone( ignoreEmptyNodes, ignoreNodesWithOnlyQualifiers );
			if ( childNode ) {
				newNode->AppendNode( childNode );
			}
		}

		if ( ignoreEmptyNodes && newNode->ChildCount() == 0 ) {
			if ( ignoreNodesWithOnlyQualifiers )
				return spINode();
			else if ( !ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 )
				return spINode();
		}

		return newNode;
	}

	void StructureNodeImpl::resetChangesForChildren() const {
		AutoSharedLock lock( mSharedMutex );
		for ( auto it = mChildrenMap.begin(), itEnd = mChildrenMap.end(); it != itEnd; ++it ) {
			it->second->AcknowledgeChanges();
		}
	}

	bool StructureNodeImpl::CompareQualifiedName::operator()( const QualifiedName & key1, const QualifiedName & key2 ) const {
		int result = key1.mNameSpace->compare( key2.mNameSpace );

		if ( result < 0 ) {
			return true;
		} else if ( result == 0 ) {
			result = key1.mName->compare( key2.mName );
			if ( result < 0 )
				return true;
		}
		return false;
	}

	spIStructureNode IStructureNode_I::CreateStructureNode( const spcIUTF8String & nameSpace, const spcIUTF8String name ) {
		return MakeUncheckedSharedPointer( new StructureNodeImpl( 
			nameSpace ? nameSpace->c_str() : NULL, nameSpace ? nameSpace->size() : 0,
			name ? name->c_str() : NULL, name ? name->size(): 0 ), __FILE__, __LINE__ );
	}

	template<>
	spINode TNodeIteratorImpl< StructureNodeImpl::QualifiedNameNodeMap::iterator >::GetNodeFromIterator( const StructureNodeImpl::QualifiedNameNodeMap::iterator & it ) const {
		return MakeUncheckedSharedPointer( it->second.get(), __FILE__, __LINE__, false );
	}
}

#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB
namespace AdobeXMPCore {
	using namespace AdobeXMPCore_Int;

	spIStructureNode IStructureNode_v1::MakeShared( pIStructureNode_base ptr ) {
		if ( !ptr ) return spIStructureNode();
		pIStructureNode p = IStructureNode::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IStructureNode >() : ptr;
		return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false );
	}

	spIStructureNode IStructureNode_v1::CreateStructureNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) {
		return MakeUncheckedSharedPointer( new StructureNodeImpl( nameSpace, nameSpaceLength, name, nameLength ), __FILE__, __LINE__, true );
	}
}
#endif  // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB