| 402 | ==== Selecting Annotation Text Objects Through FDO ==== |
| 403 | |
| 404 | Annotation Text instances owned by FDO features will be queryable and selectable through a new FDO Interface FdoIAnnotation. The FdoIAnnotation type will be considered a primary data type that can be accessed when reading FDO features, in the same manner that Raster, Association and Geometry are currently exposed. This will allow complex Annotation objects to be associated to logical features such as roads, pipes, etc. |
| 405 | |
| 406 | The FdoIAnnotation Interface allows clients that interact with and maintain Annotation text to do so through a single interface. Whereas the data that completely defines the set of Text Elements may be spread across several logical classes, accessing the Annotation will be managed through a more linear mechanism that allows users to manage data with worrying where that data is stored. |
| 407 | |
| 408 | {{{ |
| 409 | class FdoIAnnotation : public FdoIDisposable |
| 410 | { |
| 411 | public: |
| 412 | FdoIEnvelope* TextEnvelope; |
| 413 | FdoString* DefaultBaseMapScale; |
| 414 | FdoExpression* DefaultTextValue; |
| 415 | FdoString* DefaultTextAttributesAsXml; |
| 416 | FdoAnnotationTextElementCollection* TextElements; |
| 417 | }; |
| 418 | }}} |
| 419 | |
| 420 | In this simplified view of FdoIAnnotation, we see how the Annotation’s text envelope, map scale, default values, and text elements are all available through a single interface. |
| 421 | |
| 422 | From FdoIAnnotation, users are able to retrieve the collection of text attributes associated to the annotation. This is possible by accessing the TextElements property and iterating over the returned !FdoAnnotationTextElement Collection. Each object in the collection represents a piece of individual Annotation text. |
| 423 | |
| 424 | {{{ |
| 425 | class FdoAnnotationTextElement : public FdoIDisposable |
| 426 | { |
| 427 | public: |
| 428 | FdoByteArray* Location; |
| 429 | FdoByteArray* LeaderLine; |
| 430 | FdoExpression* TextValue; |
| 431 | FdoString* TextAttributesAsXml; |
| 432 | }; |
| 433 | }}} |
| 434 | |
| 435 | In order to access the above example data through the FDO logical model The FDO API’s !FdoFeatureReader class will be extended to allow Annotation properties to be queried by name and by index, in the same manner as Geometry and Raster properties are today queried. |
| 436 | |
| 437 | {{{ |
| 438 | class FdoIFeatureReader: public FdoIReader |
| 439 | { |
| 440 | public: |
| 441 | … |
| 442 | … |
| 443 | FdoIAnnotation* GetAnnotation(FdoString* propertyName); |
| 444 | FdoIAnnotation* GetAnnotation(FdoInt32 index); |
| 445 | }; |
| 446 | }}} |
| 447 | |
| 448 | |
| 449 | ===== Querying Features with Annotation Properties ===== |
| 450 | |
| 451 | Using the above Road/!RoadAnnotation Example, here is an example of how Annotation properties would be queried from an FDO data store. |
| 452 | |
| 453 | {{{ |
| 454 | // Create a select command to retrieve Road features and its associated Annotations |
| 455 | FdoISelectP selectCmd = (FdoISelect*)conn->CreateCommand(FdoCommandType_Select); |
| 456 | selectCmd->SetFeatureClassName(L"Road"); |
| 457 | |
| 458 | // Add the class properties to the selection set, including the Annotation property |
| 459 | FdoIdentifierCollectionP props = selectCmd->GetPropertyNames(); |
| 460 | props->Add(FdoIdentifierP(FdoIdentifier::Create(L"FeatId"))); |
| 461 | props->Add(FdoIdentifierP(FdoIdentifier::Create(L"Geometry"))); |
| 462 | props->Add(FdoIdentifierP(FdoIdentifier::Create(L"Name"))); |
| 463 | props->Add(FdoIdentifierP(FdoIdentifier::Create(L"Width"))); |
| 464 | props->Add(FdoIdentifierP(FdoIdentifier::Create(L"Annotation"))); |
| 465 | |
| 466 | // The selection can be arbitrarily filtered against |
| 467 | FdoFilterP filter = FdoFilter::Parse(L"FeatId > 100"); |
| 468 | selectCmd->SetFilter(filter); |
| 469 | |
| 470 | // Execute the command and get a feature reader that points to the retrieved records |
| 471 | FdoIFeatureReaderP reader = selectCmd->Execute(); |
| 472 | while (reader->ReadNext()) |
| 473 | { |
| 474 | // Get the Annotation property by name |
| 475 | FdoPtr<FdoIAnnotation> annotation = reader->GetAnnotation(L"Annotation"); |
| 476 | |
| 477 | // The annotation will have an envelope and default properties, some |
| 478 | // or all of which may be NULL. Envelope is a Geometry ByteArray. The |
| 479 | // Default Text will be an expression that can be evaluated as any |
| 480 | // database value |
| 481 | FdoByteArrayP envelope = annotation->GetEnvelope(); |
| 482 | FdoExpressionP defaultText = annotation->GetDefaultTextValue(); |
| 483 | FdoStringP defaultTextAttributes = annotation->GetDefaultTextAttibutesAsXml(); |
| 484 | const char* charArray = (const char*)textAttributes; |
| 485 | |
| 486 | // The TextAttributes would be an XML string that needs to be streamed into memory |
| 487 | // and then Read into the XML API class FdoTextElementAttributes |
| 488 | FdoIoMemoryStreamP stream = FdoIoMemoryStream::Create(); |
| 489 | stream->Write( (FdoByte*) charArray, strlen(charArray) ); |
| 490 | stream->Reset(); |
| 491 | |
| 492 | // Create the XML API class that allows programatic access to the XML properties |
| 493 | // and read the XML stream into the corresponding classes. |
| 494 | FdoTextElementAttributesP defaultAttributes = FdoTextElementAttributes::Create(); |
| 495 | defaultAttributes->ReadXml(stream); |
| 496 | |
| 497 | // Each Annotation has 0...n Text Elements that are the actual text values |
| 498 | FdoAnnotationTextElementCollectionP textElements = annotation->GetTextElements(); |
| 499 | for (FdoInt32 i=0; i<textElements->GetCount(); i++) |
| 500 | { |
| 501 | // Get the nth Text Element and read its values |
| 502 | FdoAnnotationTextElementP textElement = textElements->GetItem(i); |
| 503 | FdoExpressionP textValue = textElement->GetTextValue(); |
| 504 | FdoByteArrayP location = textElement->GetLocation(); |
| 505 | FdoByteArrayP leader = textElement->GetLeaderLine(); |
| 506 | |
| 507 | // As seen above, the XML text will need to be parsed into its API clases |
| 508 | FdoStringP textAttributes = textElement->GetTextAttributesAsXml(); |
| 509 | if (textAttributes != L"") |
| 510 | { |
| 511 | const char* charArrayA = (const char*)textAttributes; |
| 512 | FdoIoMemoryStreamP streamA = FdoIoMemoryStream::Create(); |
| 513 | streamA->Write( (FdoByte*) charArrayA, strlen(charArrayA) ); |
| 514 | streamA->Reset(); |
| 515 | |
| 516 | FdoTextElementAttributesP attributes = FdoTextElementAttributes::Create(); |
| 517 | attributes->ReadXml(streamA); |
| 518 | } |
| 519 | } |
| 520 | } |
| 521 | }}} |
| 522 | |