void MgHtmlController::WriteSelectedFeatureAttributes(MgResourceService* resourceService, MgSelection* selectionSet, MgBatchPropertyCollection* attributes, REFSTRING xmlOut) { //Rather than doing a verbatim xml dump of MgBatchPropertyCollection, let's output something //that is more intuitive for client applications using this service operation to understand. //We could assume sorted layers in the MgBatchPropertyCollection, but play safe //and store our per-layer XML fragments in a bucket (keyed on layer name) and return //the merged bucket result at the end std::map<STRING, STRING> bucket; MgAgfReaderWriter agfRw; MgWktReaderWriter wktRw; Ptr<MgReadOnlyLayerCollection> selLayers = selectionSet->GetLayers(); if (NULL != selLayers.p) { // Our structure is as follows // // [0...n] <SelectedLayer> - A layer containing selected features // [1] <LayerMetadata> - Describing properties, its display name and its property type. Due to how QueryFeatureProperties works, display names // are used for property names for each feature. This element provides a reverse lookup table to ascertain the FDO system // property name for each attribute for client applications that require such information // [0...n] <Feature> - Each selected feature in the layer // [1] <Bounds> - The feature's bounding box [minx miny maxx maxy] // [0...n] <Property> - Property value for current feature for (INT32 i = 0; i < selLayers->GetCount(); i++) { Ptr<MgLayerBase> selLayer = selLayers->GetItem(i); STRING layerName = selLayer->GetName(); if (bucket.find(layerName) == bucket.end()) { STRING xml = L"<SelectedLayer id=\""; xml.append(selLayer->GetObjectId()); xml.append(L"\" name=\""); xml.append(selLayer->GetName()); xml.append(L"\">\n"); xml.append(L"<LayerMetadata>\n"); Ptr<MgClassDefinition> clsDef = selLayer->GetClassDefinition(); Ptr<MgPropertyDefinitionCollection> clsProps = clsDef->GetProperties(); Ptr<MgResourceIdentifier> layerId = selLayer->GetLayerDefinition(); //We need the property mappings of the source layer definition to compile our layer metadata std::auto_ptr<MdfModel::LayerDefinition> ldf(MgLayerBase::GetLayerDefinition(resourceService, layerId)); if (ldf.get() != NULL) { MdfModel::VectorLayerDefinition* vl = dynamic_cast<MdfModel::VectorLayerDefinition*>(ldf.get()); if(vl != NULL) { MdfModel::NameStringPairCollection* pmappings = vl->GetPropertyMappings(); for (int j=0; j<pmappings->GetCount(); j++) { STRING pTypeStr; MdfModel::NameStringPair* m = pmappings->GetAt(j); INT32 pidx = clsProps->IndexOf(m->GetName()); if (pidx >= 0) { Ptr<MgPropertyDefinition> propDef = clsProps->GetItem(pidx); INT32 pdType = propDef->GetPropertyType(); INT32 pType = MgPropertyType::Null; if (pdType == MgFeaturePropertyType::DataProperty) { pType = ((MgDataPropertyDefinition*)propDef.p)->GetDataType(); } else if (pdType == MgFeaturePropertyType::GeometricProperty) { pType = MgPropertyType::Geometry; } MgUtil::Int32ToString(pType, pTypeStr); xml.append(L"<Property>\n"); xml.append(L"<Name>"); xml.append(m->GetName()); xml.append(L"</Name>\n"); xml.append(L"<Type>"); xml.append(pTypeStr); xml.append(L"</Type>\n"); xml.append(L"<DisplayName>"); xml.append(m->GetValue()); xml.append(L"</DisplayName>\n"); xml.append(L"</Property>\n"); } } } } xml += L"</LayerMetadata>\n"; bucket[layerName] = xml; } } for (INT32 i = 0; i < attributes->GetCount(); i++) { Ptr<MgPropertyCollection> featProps = attributes->GetItem(i); INT32 lidx = featProps->IndexOf(L"_MgLayerName"); INT32 fidx = featProps->IndexOf(L"_MgFeatureBoundingBox"); //Must have both the _MgLayerName and _MgFeatureBoundingBox if (lidx < 0 || fidx < 0) continue; Ptr<MgStringProperty> layerNameProp = (MgStringProperty*)featProps->GetItem(lidx); Ptr<MgStringProperty> boundsProp = (MgStringProperty*)featProps->GetItem(fidx); //Locate the matching bucketed fragment to append to STRING layerName = layerNameProp->GetValue(); if (bucket.find(layerName) != bucket.end()) { //Good to go, write our feature to this bucketed fragment REFSTRING xml = bucket[layerName]; xml.append(L"<Feature>\n"); xml.append(L"<Bounds>"); xml.append(boundsProp->GetValue()); xml.append(L"</Bounds>\n"); for (INT32 p = 0; p < featProps->GetCount(); p++) { //Skip special properties if (p == lidx || p == fidx) continue; Ptr<MgNullableProperty> prop = dynamic_cast<MgNullableProperty*>(featProps->GetItem(p)); if (NULL != prop.p) { xml.append(L"<Property>\n"); xml.append(L"<Name>"); xml.append(prop->GetName()); xml.append(L"</Name>\n"); //We'll follow MgProperty spec. Null is represented by omission of <Value> if (!prop->IsNull()) { INT32 ptype = prop->GetPropertyType(); switch(ptype) { //case MgPropertyType::Blob: case MgPropertyType::Boolean: { xml.append(L"<Value>"); xml.append(((MgBooleanProperty*)prop.p)->GetValue() ? L"true" : L"false"); xml.append(L"</Value>\n"); } break; case MgPropertyType::Byte: { STRING sVal; MgUtil::Int32ToString((INT32)((MgByteProperty*)prop.p)->GetValue(), sVal); xml.append(L"<Value>"); xml.append(sVal); xml.append(L"</Value>\n"); } break; //case MgPropertyType::Clob: case MgPropertyType::DateTime: { Ptr<MgDateTime> dt = ((MgDateTimeProperty*)prop.p)->GetValue(); xml.append(L"<Value>"); xml.append(dt->ToXmlString()); xml.append(L"</Value>\n"); } break; case MgPropertyType::Decimal: case MgPropertyType::Double: { STRING sVal; MgUtil::DoubleToString(((MgDoubleProperty*)prop.p)->GetValue(), sVal); xml.append(L"<Value>"); xml.append(sVal); xml.append(L"</Value>\n"); } break; case MgPropertyType::Geometry: { try { Ptr<MgByteReader> agf = ((MgGeometryProperty*)prop.p)->GetValue(); Ptr<MgGeometry> geom = agfRw.Read(agf); STRING wkt = wktRw.Write(geom); xml.append(L"<Value>"); xml.append(wkt); xml.append(L"</Value>\n"); } catch (MgException* ex) //Bad geom maybe { SAFE_RELEASE(ex); } } break; case MgPropertyType::Int16: { STRING sVal; MgUtil::Int32ToString((INT32)((MgInt16Property*)prop.p)->GetValue(), sVal); xml.append(L"<Value>"); xml.append(sVal); xml.append(L"</Value>\n"); } break; case MgPropertyType::Int32: { STRING sVal; MgUtil::Int32ToString(((MgInt32Property*)prop.p)->GetValue(), sVal); xml.append(L"<Value>"); xml.append(sVal); xml.append(L"</Value>\n"); } break; case MgPropertyType::Int64: { STRING sVal; MgUtil::Int64ToString(((MgInt64Property*)prop.p)->GetValue(), sVal); xml.append(L"<Value>"); xml.append(sVal); xml.append(L"</Value>\n"); } break; case MgPropertyType::Single: { STRING sVal; MgUtil::SingleToString(((MgSingleProperty*)prop.p)->GetValue(), sVal); xml.append(L"<Value>"); xml.append(sVal); xml.append(L"</Value>\n"); } break; case MgPropertyType::String: { xml.append(L"<Value>"); xml.append(MgUtil::ReplaceEscapeCharInXml(((MgStringProperty*)prop.p)->GetValue())); xml.append(L"</Value>\n"); } break; } } xml.append(L"</Property>\n"); } } xml.append(L"</Feature>\n"); } } //Now merge the bucketed fragments for (std::map<STRING, STRING>::iterator it = bucket.begin(); it != bucket.end(); it++) { //Close off the <SelectedLayer> elements STRING xml = it->second; xml.append(L"</SelectedLayer>"); //Good to append to the final result xmlOut.append(xml); } } }
void FillDictionary(ctemplate::TemplateDictionary* Dict,const std::string& NamePrefix, c_RestDataReader* FeatureReader) { int count = FeatureReader->GetPropertyCount(); for(int ind=0;ind<count;ind++) { STRING propname = FeatureReader->GetPropertyName(ind); if( !FeatureReader->IsNull(propname) ) { string dictkey = NamePrefix + MgUtil::WideCharToMultiByte(propname); ReplaceSpaces(dictkey); // google ctemplate doesn't allow spaces int ptype = FeatureReader->GetPropertyType(propname); switch( ptype ) { case MgPropertyType::Geometry: { /* int geomlength; BYTE_ARRAY_OUT geombytes = FeatureReader->GetGeometry(propname,geomlength); Ptr<MgByteReader> bytes = new MgByteReader( geombytes,geomlength,L"" ); */ try { Ptr<MgByteReader> bytes = FeatureReader->GetGeometry(propname); MgAgfReaderWriter agfReader; Ptr<MgGeometry> fgfgeom = agfReader.Read(bytes); MgWktReaderWriter wktReader; STRING wktstring = wktReader.Write(fgfgeom); string mb_wktstring = MgUtil::WideCharToMultiByte(wktstring); Dict->SetValue(dictkey,mb_wktstring); string kmlgeometry,kmlcentroid,kml_multi_centroid_polygon; double cent_x,cent_y; c_KmlUtil::ToKml(fgfgeom,kmlgeometry,kmlcentroid,cent_x,cent_y,kml_multi_centroid_polygon); Dict->SetValue(dictkey+"_KML",kmlgeometry); Dict->SetValue(dictkey+"_KML_CENTROID",kmlcentroid); Dict->SetValue(dictkey+"_KML_MULTI",kml_multi_centroid_polygon); string georsssimple; c_GeoRssUtil::ToGeoRssSimple(fgfgeom,georsssimple); Dict->SetValue(dictkey+"_GEORSS",georsssimple); string gml; c_GmlUtil::ToGML(fgfgeom,gml,c_GmlUtil::e_GmlFormat::GML311); Dict->SetValue(dictkey+"_GML",gml); char buff[4*64+6]; ::sprintf(buff, "%.7g", cent_x); Dict->SetValue(dictkey+"_CENTROID_X",buff); ::sprintf(buff, "%.7g", cent_y); Dict->SetValue(dictkey+"_CENTROID_Y",buff); Ptr<MgEnvelope> e2 = fgfgeom->Envelope(); Ptr<MgCoordinate> ll = e2->GetLowerLeftCoordinate(); Ptr<MgCoordinate> ur = e2->GetUpperRightCoordinate(); ::sprintf(buff, "%.7g,%.7g,%.7g,%.7g", ll->GetX(),ll->GetY(),ur->GetX(),ur->GetY()); Dict->SetValue(NamePrefix + "REST_ENVELOPE",buff); // set same value for BBOX Dict->SetValue(dictkey+"_BBOX",buff); ::sprintf(buff, "%.7g", ll->GetX()); Dict->SetValue(dictkey+"_BBOX_MIN_X",buff); ::sprintf(buff, "%.7g", ur->GetX()); Dict->SetValue(dictkey+"_BBOX_MAX_X",buff); ::sprintf(buff, "%.7g", (ll->GetX()+ur->GetX())/2.0); Dict->SetValue(dictkey+"_BBOX_MID_X",buff); ::sprintf(buff, "%.7g", ll->GetY()); Dict->SetValue(dictkey+"_BBOX_MIN_Y",buff); ::sprintf(buff, "%.7g", ur->GetY()); Dict->SetValue(dictkey+"_BBOX_MAX_Y",buff); ::sprintf(buff, "%.7g", (ll->GetY()+ur->GetY())/2.0); Dict->SetValue(dictkey+"_BBOX_MID_Y",buff); } catch (MgException *ex) // just ignore in case of invalid geometries { ex->Release(); } } break; case MgPropertyType::Int64: { INT64 val = FeatureReader->GetInt64(propname); std::string tmp = ""; MgUtil::Int64ToString(val, tmp); Dict->SetValue(dictkey,tmp); } break; case MgPropertyType::Int32: { long val = FeatureReader->GetInt32(propname); Dict->SetFormattedValue(dictkey,"%ld",val); } break; case MgPropertyType::Int16: { int val = FeatureReader->GetInt16(propname); Dict->SetIntValue(dictkey,val); } break; case MgPropertyType::Double: { double val = FeatureReader->GetDouble(propname); Dict->SetFormattedValue(dictkey,"%.5g",val); } break; case MgPropertyType::Single: { float val = FeatureReader->GetSingle(propname); Dict->SetFormattedValue(dictkey,"%.5f",val); } break; case MgPropertyType::Boolean: { bool val = FeatureReader->GetBoolean(propname); Dict->SetValue(dictkey,val ? "TRUE" : "FALSE"); } break; case MgPropertyType::Byte: { BYTE val = FeatureReader->GetByte(propname); Dict->SetIntValue(dictkey,val ); } break; case MgPropertyType::DateTime: { Ptr<MgDateTime> date = FeatureReader->GetDateTime(propname); string val; MgDateTimeToString(date,val); Dict->SetValue(dictkey,val ); // set date as Atom string Poco::DateTime dt(date->GetYear(), date->GetMonth(), date->GetDay(), date->GetHour(), date->GetMinute(), date->GetSecond()); std::string str = Poco::DateTimeFormatter::format(dt, Poco::DateTimeFormat::ISO8601_FORMAT); Dict->SetValue(dictkey+"_ATOM_DATE",str); } break; case MgPropertyType::String: { string val = MgUtil::WideCharToMultiByte(FeatureReader->GetString(propname)); Dict->SetValue(dictkey,val); } break; } } } }