Class used to parse the dim file (xml format) and get relevant properties from it.
        /// <summary>
        /// Create the function raster dataset from the source images.
        /// </summary>
        /// <param name="dimPar">Parser for the dimap file.</param>
        /// <param name="pItemURI">ItemURi to use.</param>
        /// <returns>Function raster dataset created.</returns>
        private IFunctionRasterDataset GetFRD(DiMapParser dimPar, IItemURI pItemURI)
        {
            IFunctionRasterDataset opFrd = null;
            try
            {
                Type factoryType = Type.GetTypeFromProgID("esriDataSourcesRaster.RasterWorkspaceFactory");
                IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
                IWorkspace workspace = workspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(pItemURI.Key), 0);
                IRasterWorkspace rasterWorkspace = (IRasterWorkspace)workspace;
                // Open the tif file associated with the .dim file as a raster dataset.
                string imagePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(pItemURI.Key),
                    pItemURI.Group + ".tif");
                string rpcPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(pItemURI.Key),
                    pItemURI.Group + ".rpc");
                IRasterDataset inputRasterDataset = null;
                if (File.Exists(imagePath))
                    inputRasterDataset = rasterWorkspace.OpenRasterDataset(pItemURI.Group + ".tif");
                else
                    return null;

                IFunctionRasterDataset intermedFrd = null;
                // If the file opes successfully, add a RasterInfo function on top.
                if (inputRasterDataset != null)
                {
                    // Create an Identity function dataset to get the raster info.
                    IRasterFunction identityFunction = new IdentityFunctionClass();
                    IFunctionRasterDataset idFrd = new FunctionRasterDatasetClass();
                    idFrd.Init(identityFunction, inputRasterDataset);
                    // Create a raster info function dataset.
                    IRasterFunction rasterInfoFunction = new RasterInfoFunctionClass();
                    IRasterInfoFunctionArguments rasterInfoFuncArgs = new RasterInfoFunctionArgumentsClass();
                    rasterInfoFuncArgs.Raster = inputRasterDataset;
                    rasterInfoFuncArgs.RasterInfo = idFrd.RasterInfo;
                    intermedFrd = new FunctionRasterDatasetClass();
                    intermedFrd.Init(rasterInfoFunction, rasterInfoFuncArgs);
                }
                else
                    return null;
                // Check if there is an RPC file associated with the image. If so
                // then add a geometric function to apply the rpc xform.
                if (File.Exists(rpcPath))
                    opFrd = ApplyRPC(rpcPath, (IRasterDataset)intermedFrd);

                // If no rpc pars exist or applying rpc fails, use the intermediate 
                // function raster dataset created.
                if (opFrd == null)
                    opFrd = intermedFrd;
                
                //IRasterFunction ebFunction = new ExtractBandFunctionClass();
                //IRasterFunctionArguments ebFuncArgs = new ExtractBandFunctionArgumentsClass();
                //ILongArray bandIDs = new LongArrayClass();
                //bandIDs.Add(2);
                //bandIDs.Add(1);
                //bandIDs.Add(0);
                ////bandIDs.Add(4);
                //((IExtractBandFunctionArguments)ebFuncArgs).BandIDs = bandIDs;
                //((IExtractBandFunctionArguments)ebFuncArgs).Raster = inputRasterDataset;
                //opFrd = new FunctionRasterDatasetClass();
                //opFrd.Init(ebFunction, ebFuncArgs);

                //if (opFrd == null)
                //{
                //    IRasterFunction identityFunction = new IdentityFunctionClass();
                //    opFrd = new FunctionRasterDatasetClass();
                //    opFrd.Init(identityFunction, inputRasterDataset);
                //}
            }
            catch (Exception exc)
            {
                string error = exc.Message;
            }
            return opFrd;
        }
        //private IGeometry GetFootprint(DiMapParser dimParser)
        //{
        //    IGeometry currFootprint = null;
        //    dimParser.ResetVertexCount();
        //    string xs = "";
        //    string ys = "";
        //    string rows = "";
        //    string cols = "";
        //    double minX = 10000000000.0;
        //    double maxX = -1000000000.00;
        //    double minY = 1000000000.00;
        //    double maxY = -1000000000.00;
        //    double minRow = 1000000000.00;
        //    double maxRow = -1000000000.0;
        //    double minCol = 1000000000.00;
        //    double maxCol = -1000000000.0;
        //    double x = 0.0;
        //    double y = 0.0;
        //    double row = 0.0;
        //    double col = 0.0;

        //    while (dimParser.GetNextVertex(out xs, out ys, out rows, out cols))
        //    {
        //        x = Convert.ToDouble(xs);
        //        y = Convert.ToDouble(ys);
        //        row = Convert.ToDouble(rows);
        //        col = Convert.ToDouble(cols);

        //        if (x < minX)
        //            minX = x;
        //        if (x > maxX)
        //            maxX = x;

        //        if (y < minY)
        //            minY = y;
        //        if (y > maxY)
        //            maxY = y;

        //        if (row < minRow)
        //            minRow = row;
        //        if (row > maxRow)
        //            maxRow = row;

        //        if (col < minCol)
        //            minCol = col;
        //        if (col > maxCol)
        //            maxCol = col;

        //        x = 0.0;
        //        y = 0.0;
        //        row = 0.0;
        //        col = 0.0;
        //        xs = "";
        //        ys = "";
        //        rows = "";
        //        cols = "";
        //    }
        //    x = Convert.ToDouble(xs);
        //    y = Convert.ToDouble(ys);
        //    row = Convert.ToDouble(rows);
        //    col = Convert.ToDouble(cols);

        //    if (x < minX)
        //        minX = x;
        //    if (x > maxX)
        //        maxX = x;

        //    if (y < minY)
        //        minY = y;
        //    if (y > maxY)
        //        maxY = y;

        //    if (row < minRow)
        //        minRow = row;
        //    if (row > maxRow)
        //        maxRow = row;

        //    if (col < minCol)
        //        minCol = col;
        //    if (col > maxCol)
        //        maxCol = col;

        //    currFootprint = new PolygonClass();
        //    IPointCollection currPointColl = (IPointCollection)currFootprint;
        //    IEnvelope rectEnvelope = new EnvelopeClass();
        //    rectEnvelope.PutCoords(minX, minY, maxX, maxY);
        //    ISegmentCollection segmentCollection = (ISegmentCollection)currFootprint;
        //    segmentCollection.SetRectangle(rectEnvelope);

        //    // Get Srs
        //    int epsgcode = Convert.ToInt32((dimParser.SrsCode.Split(':'))[1]);
        //    ISpatialReferenceFactory3 srsfactory = new SpatialReferenceEnvironmentClass();
        //    ISpatialReference dimSrs = srsfactory.CreateSpatialReference(epsgcode);
        //    ISpatialReferenceResolution srsRes = (ISpatialReferenceResolution)dimSrs;
        //    srsRes.ConstructFromHorizon();
        //    srsRes.SetDefaultXYResolution();
        //    ((ISpatialReferenceTolerance)dimSrs).SetDefaultXYTolerance();
        //    currFootprint.SpatialReference = dimSrs;

        //    #region Commented
        //    //IEnvelope extent = new EnvelopeClass();
        //    //extent.XMin = geoDset.Extent.XMin;
        //    //extent.XMax = geoDset.Extent.XMax;
        //    //extent.YMin = geoDset.Extent.YMin;
        //    //extent.YMax = geoDset.Extent.YMax;
        //    //extent.SpatialReference = geoDset.SpatialReference;
        //    //extent.Width = inputFrd.RasterInfo.Extent.Width;
        //    //extent.Height = inputFrd.RasterInfo.Extent.Height;
        //    //currItem.Footprint = (IGeometry)extent;

        //    //myDimParser.ResetVertexCount();
        //    //string x = "";
        //    //string y = "";
        //    //string row = "";
        //    //string col = "";
        //    //IGeometry currFootprint = new PolygonClass();
        //    //IPointCollection currPointColl = (IPointCollection)currFootprint;

        //    // Creating a polygon!!!

        //    ////Build a polygon from a sequence of points. 
        //    ////Add arrays of points to a geometry using the IGeometryBridge2 interface on the 
        //    ////GeometryEnvironment singleton object.
        //    //IGeometryBridge2 geometryBridge2 = new GeometryEnvironmentClass();
        //    //IPointCollection4 pointCollection4 = new PolygonClass();

        //    ////TODO:
        //    ////pointCollection4.SpatialReference = 'Define the spatial reference of the new polygon.

        //    //WKSPoint[] aWKSPointBuffer = null;
        //    //long cPoints = 4; //The number of points in the first part.
        //    //aWKSPointBuffer = new WKSPoint[System.Convert.ToInt32(cPoints - 1) + 1];

        //    ////TODO:
        //    ////aWKSPointBuffer = 'Read cPoints into the point buffer.

        //    //geometryBridge2.SetWKSPoints(pointCollection4, ref aWKSPointBuffer);

        //    //myDimParser.GetNextVertex(out x, out y, out col, out row);
        //    //IPoint currPoint1 = new PointClass();
        //    //currPoint1.X = Convert.ToDouble(x);
        //    //currPoint1.Y = Convert.ToDouble(y);
        //    //myDimParser.GetNextVertex(out x, out y, out col, out row);
        //    //IPoint currPoint2 = new PointClass();
        //    //currPoint1.X = Convert.ToDouble(x);
        //    //currPoint1.Y = Convert.ToDouble(y);
        //    //myDimParser.GetNextVertex(out x, out y, out col, out row);
        //    //IPoint currPoint3 = new PointClass();
        //    //currPoint1.X = Convert.ToDouble(x);
        //    //currPoint1.Y = Convert.ToDouble(y);
        //    //myDimParser.GetNextVertex(out x, out y, out col, out row);
        //    //IPoint currPoint4 = new PointClass();
        //    //currPoint1.X = Convert.ToDouble(x);
        //    //currPoint1.Y = Convert.ToDouble(y);
        //    //object refPoint1 = (object)currPoint1;
        //    //object refPoint2 = (object)currPoint2;
        //    //object refPoint3 = (object)currPoint3;
        //    //object refPoint4 = (object)currPoint4;
        //    //currPointColl.AddPoint(currPoint1, ref refPoint4, ref refPoint2);
        //    //currPointColl.AddPoint(currPoint2, ref refPoint1, ref refPoint3);
        //    //currPointColl.AddPoint(currPoint3, ref refPoint2, ref refPoint4);
        //    //currPointColl.AddPoint(currPoint4, ref refPoint3, ref refPoint1);
        //    //((IPolygon)currFootprint).Close();
        //    //currFootprint.SpatialReference = dimSrs;
        //    #endregion
        //    return currFootprint;
        //}

        /// <summary>
        /// Get the footprint from the dimap file if it exists.
        /// </summary>
        /// <param name="dimParser">Dimap file parser.</param>
        /// <returns>Footprint geomtry.</returns>
        private IGeometry GetFootprint(DiMapParser dimParser)
        {
            IGeometry currFootprint = null;
            dimParser.ResetVertexCount();
            string xs = "";
            string ys = "";
            double minX = 10000000000.0;
            double maxX = -1000000000.00;
            double minY = 1000000000.00;
            double maxY = -1000000000.00;
            double x = 0.0;
            double y = 0.0;
            string units = dimParser.ProductType;
            if (units.ToLower() == "L1T".ToLower())
                units = "M";
            else if (units.ToLower() == "L1R".ToLower())
                units = "Deg";
            // Get vertices from the dimap file and figure out the min,max.
            while (dimParser.GetNextVertex2(out xs, out ys, units))
            {
                x = Convert.ToDouble(xs);
                y = Convert.ToDouble(ys);

                if (x < minX)
                    minX = x;
                if (x > maxX)
                    maxX = x;

                if (y < minY)
                    minY = y;
                if (y > maxY)
                    maxY = y;

                x = 0.0;
                y = 0.0;
                xs = "";
                ys = "";
            }
            x = Convert.ToDouble(xs);
            y = Convert.ToDouble(ys);

            if (x < minX)
                minX = x;
            if (x > maxX)
                maxX = x;

            if (y < minY)
                minY = y;
            if (y > maxY)
                maxY = y;

            // create a new polygon and fill it using the vertices calculated.
            currFootprint = new PolygonClass();
            IPointCollection currPointColl = (IPointCollection)currFootprint;
            IEnvelope rectEnvelope = new EnvelopeClass();
            rectEnvelope.PutCoords(minX, minY, maxX, maxY);
            ISegmentCollection segmentCollection = (ISegmentCollection)currFootprint;
            segmentCollection.SetRectangle(rectEnvelope);

            // Get Srs from the dim file and set it on the footprint.
            int epsgcode = Convert.ToInt32((dimParser.SrsCode.Split(':'))[1]);
            ISpatialReferenceFactory3 srsfactory = new SpatialReferenceEnvironmentClass();
            ISpatialReference dimSrs = srsfactory.CreateSpatialReference(epsgcode);
            ISpatialReferenceResolution srsRes = (ISpatialReferenceResolution)dimSrs;
            srsRes.ConstructFromHorizon();
            srsRes.SetDefaultXYResolution();
            ((ISpatialReferenceTolerance)dimSrs).SetDefaultXYTolerance();
            currFootprint.SpatialReference = dimSrs;
            return currFootprint;
        }
 /// <summary>
 /// Sets band properties on a given dataset including stats, band names and wavelengths.
 /// </summary>
 /// <param name="dataset">The dataset to set properties on.</param>
 /// <param name="dimParser">Dimap parser to read properties from.</param>
 private void SetBandProperties(IDataset dataset, DiMapParser dimParser)
 {
     try
     {
         // Set band band props.
         IRasterKeyProperties rasterKeyProps = (IRasterKeyProperties)dataset;
         IRasterBandCollection rasterBandColl = (IRasterBandCollection)dataset;
         int imageNumBands = ((IFunctionRasterDataset)dataset).RasterInfo.BandCount;
         int dinNumBands = dimParser.NumBands;
         int[] bandIndexes = new int[dinNumBands];
         IStringArray bandNames = new StrArrayClass();
         for (int i = 0; i < dinNumBands; ++i)
         {
             // Get band index for the first band.
             bandIndexes[i] = Convert.ToInt16(dimParser.GetBandIndex(i));
             // Validate band index.
             if (bandIndexes[i] > 0 && bandIndexes[i] <= imageNumBands)
             {
                 // Get Band Name for the index.
                 bandNames.Add(dimParser.GetBandDesc(bandIndexes[i]));
                 // Get Band stats for the index.
                 IRasterStatistics bandStats = new RasterStatisticsClass();
                 bandStats.Minimum = Convert.ToDouble(dimParser.GetBandStatMin(bandIndexes[i]));
                 bandStats.Maximum = Convert.ToDouble(dimParser.GetBandStatMax(bandIndexes[i]));
                 bandStats.Mean = Convert.ToDouble(dimParser.GetBandStatMean(bandIndexes[i]));
                 bandStats.StandardDeviation = Convert.ToDouble(dimParser.GetBandStatStdDev(bandIndexes[i]));
                 // Set stats on the dataset.
                 ((IRasterBandEdit2)rasterBandColl.Item(bandIndexes[i] - 1)).AlterStatistics(bandStats);
                 // Set Band Name and wavelengths according to the name.
                 rasterKeyProps.SetBandProperty("BandName", (bandIndexes[i] - 1), bandNames.get_Element(i));
                 SetBandWavelengths(dataset, (bandIndexes[i] - 1));
                 // Refresh dataset so changes are saved.
                 ((IRasterDataset3)dataset).Refresh();
             }
         }
     }
     catch (Exception exc)
     {
         string error = exc.Message;
     }
 }
        /// <summary>
        /// Build the Builder Item which includes the function raster dataset and its footprint 
        /// given the ItemURI.
        /// </summary>
        /// <param name="pItemURI">ItemURi to use to build the Builder Item.</param>
        /// <returns>The builder item.</returns>
        public IBuilderItem Build(IItemURI pItemURI)
        {
            try
            {
                // Create a new parser object and builder item.
                DiMapParser myDimParser = new DiMapParser(pItemURI.Key);
                IBuilderItem currItem = new BuilderItemClass();

                // Set Category and URI
                currItem.Category = esriRasterCatalogItemCategory.esriRasterCatalogItemCategoryPrimary;
                currItem.URI = pItemURI;

                // Set FunctionRasterDataset
                IFunctionRasterDataset inputFrd = GetFRD(myDimParser, pItemURI);
                currItem.Dataset = inputFrd;
                // Set band information for the function dataset including names, wavelengths and stats if available.
                SetBandProperties((IDataset)inputFrd, myDimParser);

                // Set Footprint
                IGeoDataset geoDset = (IGeoDataset)inputFrd;
                // Set it to the current raster extent first. If the raster has no 
                // spatial reference, the extents will be in pixel space.
                currItem.Footprint = (IGeometry)geoDset.Extent;
                // The get the footprint from the dim file is it exists.
                currItem.Footprint = GetFootprint(myDimParser);

                // Set Properties. These properties are used to fill the Auxiliary Fields 
                // defined earlier and also key properties if the names are correct.
                IPropertySet propSet = currItem.Dataset.Properties;
                if (null == propSet)
                    propSet = new PropertySetClass();
                double sunAzimuth = Convert.ToDouble(myDimParser.SunAzimuth);
                double sunElevation = Convert.ToDouble(myDimParser.SunElevation);
                double sensorAzimuth = Convert.ToDouble(myDimParser.SensorAzimuth);
                double sensorElevation = 180 - Convert.ToDouble(myDimParser.IncidenceAngle);
                string acqDate = myDimParser.AcquisitionDate;
                string acqTime = myDimParser.AcquisitionTime;
                // Create a time object from the provided date and time.
                ITime acqDateTimeObj = new TimeClass();
                acqDateTimeObj.SetFromTimeString(esriTimeStringFormat.esriTSFYearThruSubSecondWithDash,
                    acqDate + " " + acqTime);
                // and obtain a DateTime object to set as value of the property. This ensures the 
                // field displays the value correctly.
                DateTime acqDateTimeFieldVal = acqDateTimeObj.QueryOleTime();

                propSet.SetProperty("AcquisitionDate", acqDateTimeFieldVal);
                propSet.SetProperty("SensorName", myDimParser.MetadataProfile);
                propSet.SetProperty("SunAzimuth", sunAzimuth);
                propSet.SetProperty("SunElevation", sunElevation);
                propSet.SetProperty("SatAzimuth", sensorAzimuth);
                propSet.SetProperty("SatElevation", sensorElevation);
                currItem.Dataset.Properties = propSet;

                return currItem;
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }
        /// <summary>
        /// Generate the next URI.
        /// </summary>
        /// <returns>The URI generated.</returns>
        public IItemURI GetNextURI()
        {
            IItemURI newURI = null;
            try
            {
                // Check to see if the item cralwed is a .dim file.
                if (myCurrentDimFile != "" && myCurrentDimFile != null && myCurrentDimFile.EndsWith(".dim"))
                {
                    // Create a new Dimap Parser obect and item uri.
                    DiMapParser myDimParser = new DiMapParser(myCurrentDimFile);
                    newURI = new ItemURIClass();
                    // Set the display name, Group, Product Name, Tag and Key.
                    newURI.DisplayName = System.IO.Path.GetFileName(myCurrentDimFile);
                    newURI.Group = System.IO.Path.GetFileNameWithoutExtension(myCurrentDimFile);
                    newURI.Key = myCurrentDimFile;
                    newURI.ProductName = myDimParser.ProductType;
                    newURI.Tag = "MS";
                    // Set the timestamp of the dimfile as source time stamp. This helps 
                    // with synchronization later.
                    IRasterTypeEnvironment myEnv = new RasterTypeEnvironmentClass();
                    DateTime dimTS = myEnv.GetTimeStamp(myCurrentDimFile);
                    newURI.SourceTimeStamp = dimTS;

                    myDimParser = null;
                    myCurrentDimFile = "";
                    myURIArray.Add(newURI);
                }
            }
            catch (Exception)
            {
                throw;
            }
            return newURI;
        }
 /// <summary>
 /// Check if the data source provided is a valid data source for the builder.
 /// </summary>
 /// <param name="vtDataSource">Data source (usually the path to a metadta file)</param>
 /// <returns>Flag to specify whether it is  valid source.</returns>
 public bool CanBuild(object vtDataSource)
 {
     if (!(vtDataSource is string))
         return false;
     string dimFilePath = (string)vtDataSource;
     if (!dimFilePath.ToLower().EndsWith(".dim"))
         return false;
     DiMapParser myDimParser = null;
     try
     {
         myDimParser = new DiMapParser(dimFilePath);
         if (myDimParser.MetadataProfile.ToLower() == "DMCII".ToLower())
         {
             myDimParser = null;
             return true;
         }
         else
         {
             myDimParser = null;
             return false;
         }
     }
     catch (Exception exc)
     {
         myDimParser = null;
         string error = exc.Message;
         return false;
     }
 }