Example #1
0
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;
      }
    }
  }

}