00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "qgsvectorlayerjoinbuffer.h"
00019 #include "qgsmaplayerregistry.h"
00020 #include "qgsvectordataprovider.h"
00021
00022 #include <QDomElement>
00023
00024 QgsVectorLayerJoinBuffer::QgsVectorLayerJoinBuffer()
00025 {
00026 }
00027
00028 QgsVectorLayerJoinBuffer::~QgsVectorLayerJoinBuffer()
00029 {
00030 }
00031
00032 void QgsVectorLayerJoinBuffer::addJoin( QgsVectorJoinInfo joinInfo )
00033 {
00034 mVectorJoins.push_back( joinInfo );
00035
00036
00037 if ( joinInfo.memoryCache )
00038 {
00039 cacheJoinLayer( mVectorJoins.last() );
00040 }
00041 }
00042
00043 void QgsVectorLayerJoinBuffer::removeJoin( const QString& joinLayerId )
00044 {
00045 for ( int i = 0; i < mVectorJoins.size(); ++i )
00046 {
00047 if ( mVectorJoins.at( i ).joinLayerId == joinLayerId )
00048 {
00049 mVectorJoins.removeAt( i );
00050
00051 QgsVectorLayer* joinLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinLayerId ) );
00052 if ( joinLayer )
00053 {
00054 mFetchJoinInfos.remove( joinLayer );
00055 }
00056 }
00057 }
00058 }
00059
00060 void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo )
00061 {
00062
00063 if ( !joinInfo.memoryCache || joinInfo.cachedAttributes.size() > 0 )
00064 {
00065 return;
00066 }
00067
00068 QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
00069 if ( cacheLayer )
00070 {
00071 joinInfo.cachedAttributes.clear();
00072 cacheLayer->select( cacheLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
00073 QgsFeature f;
00074 while ( cacheLayer->nextFeature( f ) )
00075 {
00076 const QgsAttributeMap& map = f.attributeMap();
00077 joinInfo.cachedAttributes.insert( map.value( joinInfo.joinField ).toString(), map );
00078 }
00079 }
00080 }
00081
00082 void QgsVectorLayerJoinBuffer::updateFieldMap( QgsFieldMap& fields, int& maxIndex )
00083 {
00084 int currentMaxIndex = 0;
00085
00086 QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin();
00087 for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
00088 {
00089 QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
00090 if ( !joinLayer )
00091 {
00092 continue;
00093 }
00094
00095 const QgsFieldMap& joinFields = joinLayer->pendingFields();
00096 QgsFieldMap::const_iterator fieldIt = joinFields.constBegin();
00097 for ( ; fieldIt != joinFields.constEnd(); ++fieldIt )
00098 {
00099
00100 if ( fieldIt.key() != joinIt->joinField )
00101 {
00102 fields.insert( maxIndex + 1 + fieldIt.key(), fieldIt.value() );
00103 }
00104 }
00105
00106 if ( maximumIndex( joinFields, currentMaxIndex ) )
00107 {
00108 maxIndex += ( currentMaxIndex + 1 );
00109 }
00110 }
00111 }
00112
00113 void QgsVectorLayerJoinBuffer::createJoinCaches()
00114 {
00115 QList< QgsVectorJoinInfo >::iterator joinIt = mVectorJoins.begin();
00116 for ( ; joinIt != mVectorJoins.end(); ++joinIt )
00117 {
00118 cacheJoinLayer( *joinIt );
00119 }
00120 }
00121
00122 void QgsVectorLayerJoinBuffer::select( const QgsAttributeList& fetchAttributes,
00123 QgsAttributeList& sourceJoinFields, int maxProviderIndex )
00124 {
00125 mFetchJoinInfos.clear();
00126 sourceJoinFields.clear();
00127
00128 QgsAttributeList::const_iterator attIt = fetchAttributes.constBegin();
00129 for ( ; attIt != fetchAttributes.constEnd(); ++attIt )
00130 {
00131 int indexOffset;
00132 const QgsVectorJoinInfo* joinInfo = joinForFieldIndex( *attIt, maxProviderIndex, indexOffset );
00133 if ( joinInfo )
00134 {
00135 QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo->joinLayerId ) );
00136 if ( joinLayer )
00137 {
00138 mFetchJoinInfos[ joinLayer ].joinInfo = joinInfo;
00139 mFetchJoinInfos[ joinLayer].attributes.push_back( *attIt - indexOffset );
00140 mFetchJoinInfos[ joinLayer ].indexOffset = indexOffset;
00141
00142 if ( !fetchAttributes.contains( joinInfo->targetField ) )
00143 {
00144 sourceJoinFields << joinInfo->targetField;
00145 }
00146 }
00147 }
00148 }
00149 }
00150
00151 void QgsVectorLayerJoinBuffer::updateFeatureAttributes( QgsFeature &f, int maxProviderIndex, bool all )
00152 {
00153 if ( all )
00154 {
00155 int index = maxProviderIndex + 1;
00156 int currentMaxIndex;
00157
00158 QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin();
00159 for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
00160 {
00161 QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
00162 if ( !joinLayer )
00163 {
00164 continue;
00165 }
00166
00167 QString joinFieldName = joinLayer->pendingFields().value( joinIt->joinField ).name();
00168 if ( joinFieldName.isEmpty() )
00169 {
00170 continue;
00171 }
00172
00173 QVariant targetFieldValue = f.attributeMap().value( joinIt->targetField );
00174 if ( !targetFieldValue.isValid() )
00175 {
00176 continue;
00177 }
00178
00179 addJoinedFeatureAttributes( f, *joinIt, joinFieldName, targetFieldValue, joinLayer->pendingAllAttributesList(), index );
00180
00181 maximumIndex( joinLayer->pendingFields(), currentMaxIndex );
00182 index += ( currentMaxIndex + 1 );
00183 }
00184 }
00185 else
00186 {
00187 QMap<QgsVectorLayer*, QgsFetchJoinInfo>::const_iterator joinIt = mFetchJoinInfos.constBegin();
00188 for ( ; joinIt != mFetchJoinInfos.constEnd(); ++joinIt )
00189 {
00190 QgsVectorLayer* joinLayer = joinIt.key();
00191 if ( !joinLayer )
00192 {
00193 continue;
00194 }
00195
00196 QString joinFieldName = joinLayer->pendingFields().value( joinIt.value().joinInfo->joinField ).name();
00197 if ( joinFieldName.isEmpty() )
00198 {
00199 continue;
00200 }
00201
00202 QVariant targetFieldValue = f.attributeMap().value( joinIt->joinInfo->targetField );
00203 if ( !targetFieldValue.isValid() )
00204 {
00205 continue;
00206 }
00207
00208 addJoinedFeatureAttributes( f, *( joinIt.value().joinInfo ), joinFieldName, targetFieldValue, joinIt.value().attributes, joinIt.value().indexOffset );
00209 }
00210 }
00211 }
00212
00213 void QgsVectorLayerJoinBuffer::addJoinedFeatureAttributes( QgsFeature& f, const QgsVectorJoinInfo& joinInfo, const QString& joinFieldName,
00214 const QVariant& joinValue, const QgsAttributeList& attributes, int attributeIndexOffset )
00215 {
00216 const QHash< QString, QgsAttributeMap>& memoryCache = joinInfo.cachedAttributes;
00217 if ( !memoryCache.isEmpty() )
00218 {
00219 QgsAttributeMap featureAttributes = memoryCache.value( joinValue.toString() );
00220 bool found = !featureAttributes.isEmpty();
00221 QgsAttributeList::const_iterator attIt = attributes.constBegin();
00222 for ( ; attIt != attributes.constEnd(); ++attIt )
00223 {
00224
00225 if ( *attIt == joinInfo.joinField )
00226 {
00227 continue;
00228 }
00229
00230 if ( found )
00231 {
00232 f.addAttribute( *attIt + attributeIndexOffset, featureAttributes.value( *attIt ) );
00233 }
00234 else
00235 {
00236 f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
00237 }
00238 }
00239 }
00240 else
00241 {
00242 QgsVectorLayer* joinLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
00243 if ( !joinLayer )
00244 {
00245 return;
00246 }
00247
00248
00249 QString subsetString = joinLayer->dataProvider()->subsetString();
00250 QString bkSubsetString = subsetString;
00251 if ( !subsetString.isEmpty() )
00252 {
00253 subsetString.append( " AND " );
00254 }
00255
00256 subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
00257 joinLayer->dataProvider()->setSubsetString( subsetString, false );
00258
00259
00260 joinLayer->select( attributes, QgsRectangle(), false, false );
00261
00262
00263 QgsFeature fet;
00264 if ( joinLayer->nextFeature( fet ) )
00265 {
00266 QgsAttributeMap attMap = fet.attributeMap();
00267 QgsAttributeMap::const_iterator attIt = attMap.constBegin();
00268 for ( ; attIt != attMap.constEnd(); ++attIt )
00269 {
00270 f.addAttribute( attIt.key() + attributeIndexOffset, attIt.value() );
00271 }
00272 }
00273 else
00274 {
00275 QgsAttributeList::const_iterator attIt = attributes.constBegin();
00276 for ( ; attIt != attributes.constEnd(); ++attIt )
00277 {
00278 f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
00279 }
00280 }
00281
00282 joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
00283 }
00284 }
00285
00286 void QgsVectorLayerJoinBuffer::writeXml( QDomNode& layer_node, QDomDocument& document ) const
00287 {
00288 QDomElement vectorJoinsElem = document.createElement( "vectorjoins" );
00289 layer_node.appendChild( vectorJoinsElem );
00290 QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin();
00291 for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
00292 {
00293 QDomElement joinElem = document.createElement( "join" );
00294 joinElem.setAttribute( "targetField", joinIt->targetField );
00295 joinElem.setAttribute( "joinLayerId", joinIt->joinLayerId );
00296 joinElem.setAttribute( "joinField", joinIt->joinField );
00297 joinElem.setAttribute( "memoryCache", !joinIt->cachedAttributes.isEmpty() );
00298 vectorJoinsElem.appendChild( joinElem );
00299 }
00300 }
00301
00302 void QgsVectorLayerJoinBuffer::readXml( const QDomNode& layer_node )
00303 {
00304 mVectorJoins.clear();
00305 QDomElement vectorJoinsElem = layer_node.firstChildElement( "vectorjoins" );
00306 if ( !vectorJoinsElem.isNull() )
00307 {
00308 QDomNodeList joinList = vectorJoinsElem.elementsByTagName( "join" );
00309 for ( int i = 0; i < joinList.size(); ++i )
00310 {
00311 QDomElement infoElem = joinList.at( i ).toElement();
00312 QgsVectorJoinInfo info;
00313 info.joinField = infoElem.attribute( "joinField" ).toInt();
00314 info.joinLayerId = infoElem.attribute( "joinLayerId" );
00315 info.targetField = infoElem.attribute( "targetField" ).toInt();
00316 info.memoryCache = infoElem.attribute( "memoryCache" ).toInt();
00317 addJoin( info );
00318 }
00319 }
00320 }
00321
00322 const QgsVectorJoinInfo* QgsVectorLayerJoinBuffer::joinForFieldIndex( int index, int maxProviderIndex, int& indexOffset ) const
00323 {
00324 int currentMaxIndex = 0;
00325 int totIndex = maxProviderIndex + 1;
00326
00327
00328 QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin();
00329 for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
00330 {
00331 QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
00332 if ( !joinLayer )
00333 {
00334 continue;
00335 }
00336
00337 if ( joinLayer->pendingFields().contains( index - totIndex ) )
00338 {
00339 indexOffset = totIndex;
00340 return &( *joinIt );
00341 }
00342
00343 maximumIndex( joinLayer->pendingFields(), currentMaxIndex );
00344 totIndex += ( currentMaxIndex + 1 );
00345 }
00346
00347
00348 return 0;
00349 }
00350
00351 bool QgsVectorLayerJoinBuffer::maximumIndex( const QgsFieldMap& fMap, int& index )
00352 {
00353 if ( fMap.size() < 1 )
00354 {
00355 return false;
00356 }
00357 QgsFieldMap::const_iterator endIt = fMap.constEnd();
00358 --endIt;
00359 index = endIt.key();
00360 return true;
00361 }