Esempio n. 1
0
        public void TestCloneProperty()
        {
            DataPropertyDefinition dp = new DataPropertyDefinition("Foo", "Bar");

            dp.DataType        = DataType.DataType_String;
            dp.DefaultValue    = "Whatever";
            dp.IsAutoGenerated = false;
            dp.Length          = 45;
            dp.Nullable        = true;
            dp.ReadOnly        = false;
            PropertyValueConstraintList list = new PropertyValueConstraintList();

            list.ConstraintList.Add(new StringValue("A"));
            list.ConstraintList.Add(new StringValue("B"));
            list.ConstraintList.Add(new StringValue("C"));
            dp.ValueConstraint = list;

            DataPropertyDefinition dp2 = FdoSchemaUtil.CloneProperty(dp) as DataPropertyDefinition;

            AssertHelper.EqualProperty(dp, dp2);

            GeometricPropertyDefinition gp = new GeometricPropertyDefinition("Sna", "Fu");

            gp.GeometryTypes             = (int)(GeometryType.GeometryType_LineString | GeometryType.GeometryType_MultiLineString | GeometryType.GeometryType_Polygon);
            gp.HasElevation              = true;
            gp.HasMeasure                = false;
            gp.ReadOnly                  = false;
            gp.SpatialContextAssociation = "LL84";

            GeometricPropertyDefinition gp2 = FdoSchemaUtil.CloneProperty(gp) as GeometricPropertyDefinition;

            AssertHelper.EqualProperty(gp, gp2);
        }
            public override IEnumerable <FdoRow> Execute(IEnumerable <FdoRow> rows)
            {
                if (_counter < 1) //Shouldn't be reentrant, but just play it safe.
                {
                    /*
                     * Check and apply the following rules for all geometry properties to be created
                     *
                     * Target supports multiple spatial contexts:
                     * -------------------------------------------
                     * If there is no spatial contexts of the specified (source) name. Create a copy of the source spatial context.
                     * If there is a spatial context of the same name, using the same WKT. Do nothing
                     * If there is a spatial context of the same name, but using a different WKT. Create a new spatial context using the source WKT, but use a different name.
                     *
                     * Target only supports one spatial context:
                     * If there is no spatial context already. Create a copy of the source spatial context.
                     * If there is a spatial context of the same WKT. Change the association to match the name of this spatial context.
                     * If there is a spatial context not using the source WKT. Change the association to match the name of this spatial context. This may not be ideal, but there is no other option at this point.
                     *
                     * The regular schema compatibility fixes will handle the other properties
                     */
                    bool targetSupportsMultipleSpatialContexts      = _target.Capability.GetBooleanCapability(CapabilityType.FdoCapabilityType_SupportsMultipleSpatialContexts);
                    List <SpatialContextInfo> targetSpatialContexts = null;
                    List <SpatialContextInfo> sourceSpatialContexts = null;

                    if (typeof(CreateTargetClassFromSource).IsAssignableFrom(_opts.PreCopyTargetModifier.GetType()))
                    {
                        using (var tsvc = _target.CreateFeatureService())
                            using (var ssvc = _source.CreateFeatureService())
                            {
                                targetSpatialContexts = new List <SpatialContextInfo>(tsvc.GetSpatialContexts());
                                sourceSpatialContexts = new List <SpatialContextInfo>(ssvc.GetSpatialContexts());
                                var ct = (CreateTargetClassFromSource)_opts.PreCopyTargetModifier;

                                Info("Getting current schema from target");
                                var schema = tsvc.GetSchemaByName(_opts.TargetSchema);
                                if (schema.Classes.IndexOf(ct.Name) >= 0)
                                {
                                    Info("Class " + _opts.TargetSchema + ":" + ct.Name + " already exists. Nothing to do here");
                                }
                                else
                                {
                                    List <SpatialContextInfo> createScs = new List <SpatialContextInfo>();

                                    var cls = ssvc.GetClassByName(ct.Schema, ct.Name);
                                    Info("Creating a cloned copy of source class " + ct.Schema + ":" + ct.Name);

                                    var cloned     = FdoSchemaUtil.CloneClass(cls);
                                    var propList   = new List <string>(_opts.CheckSourceProperties);
                                    var removeList = new List <string>();
                                    foreach (PropertyDefinition prop in cloned.Properties)
                                    {
                                        string propName = prop.Name;
                                        if (!propList.Contains(propName))
                                        {
                                            removeList.Add(propName);
                                        }
                                    }

                                    if (removeList.Count > 0)
                                    {
                                        Info("Removing " + removeList.Count + " unused properties from cloned class");
                                        var props = cloned.Properties;
                                        var ids   = cloned.IdentityProperties;
                                        foreach (var name in removeList)
                                        {
                                            if (ids.Contains(name))
                                            {
                                                ids.RemoveAt(ids.IndexOf(name));
                                            }

                                            if (props.Contains(name))
                                            {
                                                props.RemoveAt(props.IndexOf(name));
                                            }
                                        }
                                        Info(removeList.Count + " unused properties removed");
                                    }

                                    foreach (var prop in ct.PropertiesToCreate)
                                    {
                                        Info("Adding property to cloned class: " + prop.Name);
                                        PropertyDefinition clonedProp = FdoSchemaUtil.CloneProperty(prop);
                                        cloned.Properties.Add(clonedProp);
                                    }

                                    //Add an auto-generated identity property if none exist
                                    if (cloned.IdentityProperties.Count == 0)
                                    {
                                        var id = new DataPropertyDefinition("FID", "Auto-Generated Feature Id");
                                        id.IsAutoGenerated = true;
                                        id.Nullable        = false;
                                        //This may not be valid for target connection, but FdoFeatureService
                                        //will fix this for us.
                                        id.DataType = DataType.DataType_Int32;

                                        cloned.Properties.Add(id);
                                        cloned.IdentityProperties.Add(id);

                                        Info("Adding an auto-generated id (FID) to this cloned class");
                                    }

                                    Info("Checking this class for incompatibilities");
                                    IncompatibleClass ic;
                                    if (!tsvc.CanApplyClass(cloned, out ic))
                                    {
                                        Info("Altering this class to become compatible with target connection");
                                        cloned = tsvc.AlterClassDefinition(cloned, ic);
                                        Info("Class successfully altered");
                                    }

                                    Info("Checking if any spatial contexts need to be created and/or references modified");
                                    foreach (PropertyDefinition pd in cloned.Properties)
                                    {
                                        if (pd.PropertyType == PropertyType.PropertyType_GeometricProperty)
                                        {
                                            AddSpatialContextsToCreate(targetSupportsMultipleSpatialContexts, targetSpatialContexts, sourceSpatialContexts, createScs, (GeometricPropertyDefinition)pd);
                                        }
                                    }

                                    //We have to create spatial contexts first before applying the schema
                                    if (createScs.Count > 0)
                                    {
                                        //The ones we create should be unique so no overwriting needed
                                        ExpressUtility.CopyAllSpatialContexts(createScs, _target, false);

                                        foreach (var sc in createScs)
                                        {
                                            Info("Created spatial context: " + sc.Name);
                                        }
                                    }

                                    Info("Adding cloned class to target schema");
                                    schema.Classes.Add(cloned);
                                    Info("Applying schema back to target connection");
                                    tsvc.ApplySchema(schema);
                                    Info("Updated schema applied to target connection");
                                }
                            }
                    }
                    else if (typeof(UpdateTargetClass).IsAssignableFrom(_opts.PreCopyTargetModifier.GetType()))
                    {
                        var ut = (UpdateTargetClass)_opts.PreCopyTargetModifier;
                        using (var tsvc = _target.CreateFeatureService())
                            using (var ssvc = _source.CreateFeatureService())
                            {
                                targetSpatialContexts = new List <SpatialContextInfo>(tsvc.GetSpatialContexts());
                                sourceSpatialContexts = new List <SpatialContextInfo>(ssvc.GetSpatialContexts());
                                var schema = tsvc.GetSchemaByName(_opts.TargetSchema);
                                var cidx   = schema.Classes.IndexOf(ut.Name);
                                if (cidx < 0)
                                {
                                    throw new InvalidOperationException("Target class to be updated " + _opts.TargetSchema + ":" + ut.Name + " not found");
                                }
                                else
                                {
                                    List <SpatialContextInfo> createScs = new List <SpatialContextInfo>();

                                    var cls = schema.Classes[cidx];
                                    foreach (var prop in ut.PropertiesToCreate)
                                    {
                                        if (cls.Properties.IndexOf(prop.Name) < 0)
                                        {
                                            Info("Adding property to class: " + prop.Name);
                                            var clonedProp = FdoSchemaUtil.CloneProperty(prop);
                                            if (clonedProp.PropertyType == PropertyType.PropertyType_GeometricProperty)
                                            {
                                                AddSpatialContextsToCreate(targetSupportsMultipleSpatialContexts, targetSpatialContexts, sourceSpatialContexts, createScs, (GeometricPropertyDefinition)clonedProp);
                                            }
                                            cls.Properties.Add(clonedProp);
                                        }
                                        else
                                        {
                                            Info("Skipping property " + prop.Name + " because it already exists");
                                        }
                                    }

                                    //We have to create spatial contexts first before applying the schema
                                    if (createScs.Count > 0)
                                    {
                                        //The ones we create should be unique so no overwriting needed
                                        ExpressUtility.CopyAllSpatialContexts(createScs, _target, false);

                                        foreach (var sc in createScs)
                                        {
                                            Info("Created spatial context: " + sc.Name);
                                        }
                                    }

                                    Info("Applying modified schema " + schema.Name + " to target connection");
                                    tsvc.ApplySchema(schema);
                                    Info("Modified schema " + schema.Name + " applied to target connection");
                                }
                            }
                    }

                    _counter++;
                }
                return(rows);
            }
Esempio n. 3
0
        internal static FdoClassCopyOptions FromElement(FdoCopyTaskElement el, FeatureSchemaCache cache, FdoConnection sourceConn, FdoConnection targetConn, out TargetClassModificationItem mod)
        {
            mod = null;
            if (!cache.HasConnection(el.Source.connection))
            {
                throw new TaskLoaderException("The referenced source connection is not defined");
            }

            if (!cache.HasConnection(el.Target.connection))
            {
                throw new TaskLoaderException("The referenced target connection is not defined");
            }

            FdoClassCopyOptions opts = new FdoClassCopyOptions(el.Source.connection, el.Target.connection, el.Source.schema, el.Source.@class, el.Target.schema, el.Target.@class);

            opts.DeleteTarget = el.Options.DeleteTarget;
            opts.SourceFilter = el.Options.Filter;
            if (!el.Options.FlattenGeometriesSpecified)
            {
                opts.FlattenGeometries = false;
            }
            else
            {
                opts.FlattenGeometries = el.Options.FlattenGeometries;
            }

            if (!el.Options.ForceWKBSpecified)
            {
                opts.ForceWkb = false;
            }
            else
            {
                opts.ForceWkb = el.Options.ForceWKB;
            }

            if (!string.IsNullOrEmpty(el.Options.BatchSize))
            {
                opts.BatchSize = Convert.ToInt32(el.Options.BatchSize);
            }
            opts.Name = el.name;
            opts.CreateIfNotExists = el.createIfNotExists;

            ClassDefinition srcClass = cache.GetClassByName(el.Source.connection, el.Source.schema, el.Source.@class);
            ClassDefinition dstClass = cache.GetClassByName(el.Target.connection, el.Target.schema, el.Target.@class);

            if (!el.createIfNotExists && dstClass == null)
            {
                throw new InvalidOperationException("Target class " + el.Target.@class + " does not exist and the createIfNotExist option is false");
            }

            SpatialContextInfo           defaultSc          = null;
            FunctionDefinitionCollection availableFunctions = (FunctionDefinitionCollection)sourceConn.Capability.GetObjectCapability(CapabilityType.FdoCapabilityType_ExpressionFunctions);

            using (var svc = targetConn.CreateFeatureService())
            {
                defaultSc = svc.GetActiveSpatialContext();
            }

            if (dstClass != null)
            {
                foreach (FdoPropertyMappingElement propMap in el.PropertyMappings)
                {
                    if (srcClass.Properties.IndexOf(propMap.source) < 0)
                    {
                        throw new TaskLoaderException("The property mapping (" + propMap.source + " -> " + propMap.target + ") in task (" + el.name + ") contains a source property not found in the source class definition (" + el.Source.@class + ")");
                    }

                    //Add to list of properties to check for
                    if (propMap.createIfNotExists && dstClass.Properties.IndexOf(propMap.target) < 0)
                    {
                        if (mod == null)
                        {
                            mod = new UpdateTargetClass(dstClass.Name);
                        }

                        opts.AddSourcePropertyToCheck(propMap.source);

                        //Clone copy of source property of same name
                        var srcProp = srcClass.Properties[srcClass.Properties.IndexOf(propMap.source)];
                        srcProp = FdoSchemaUtil.CloneProperty(srcProp);
                        mod.AddProperty(srcProp);
                    }
                    else
                    {
                        if (dstClass.Properties.IndexOf(propMap.target) < 0)
                        {
                            throw new TaskLoaderException("The property mapping (" + propMap.source + " -> " + propMap.target + ") in task (" + el.name + ") contains a target property not found in the target class definition (" + el.Target.@class + ")");
                        }

                        PropertyDefinition sp = srcClass.Properties[propMap.source];
                        PropertyDefinition tp = dstClass.Properties[propMap.target];

                        if (sp.PropertyType != tp.PropertyType)
                        {
                            throw new TaskLoaderException("The properties in the mapping (" + propMap.source + " -> " + propMap.target + ") are of different types");
                        }

                        //if (sp.PropertyType != PropertyType.PropertyType_DataProperty)
                        //    throw new TaskLoaderException("One or more properties in the mapping (" + propMap.source + " -> " + propMap.target + ") is not a data property");

                        DataPropertyDefinition sdp = sp as DataPropertyDefinition;
                        DataPropertyDefinition tdp = tp as DataPropertyDefinition;

                        opts.AddPropertyMapping(propMap.source, propMap.target);

                        //Property mapping is between two data properties
                        if (sdp != null && tdp != null)
                        {
                            //Types not equal, so add a conversion rule
                            if (sdp.DataType != tdp.DataType)
                            {
                                FdoDataPropertyConversionRule rule = new FdoDataPropertyConversionRule(
                                    propMap.source,
                                    propMap.target,
                                    sdp.DataType,
                                    tdp.DataType,
                                    propMap.nullOnFailedConversion,
                                    propMap.truncate);
                                opts.AddDataConversionRule(propMap.source, rule);
                            }
                        }
                    }
                }

                //
                foreach (FdoExpressionMappingElement exprMap in el.ExpressionMappings)
                {
                    if (string.IsNullOrEmpty(exprMap.target))
                    {
                        continue;
                    }

                    opts.AddSourceExpression(exprMap.alias, exprMap.Expression, exprMap.target);
                    //Add to list of properties to check for
                    if (exprMap.createIfNotExists)
                    {
                        //Class exists but property doesn't
                        if (dstClass.Properties.IndexOf(exprMap.target) < 0)
                        {
                            if (mod == null)
                            {
                                mod = new UpdateTargetClass(el.Target.@class);
                            }

                            var prop = FdoSchemaUtil.CreatePropertyFromExpressionType(exprMap.Expression, srcClass, availableFunctions, defaultSc.Name);
                            if (prop == null)
                            {
                                throw new InvalidOperationException("Could not derive a property definition from the expression: " + exprMap.Expression);
                            }

                            prop.Name = exprMap.target;
                            mod.AddProperty(prop);
                        }
                    }
                    else //Conversion rules can only apply if both properties exist.
                    {
                        FdoPropertyType?pt = ExpressionUtility.ParseExpressionType(exprMap.Expression, sourceConn);
                        if (pt.HasValue)
                        {
                            DataType?srcDt = ValueConverter.GetDataType(pt.Value);
                            if (srcDt.HasValue)
                            {
                                PropertyDefinition     tp  = dstClass.Properties[exprMap.target];
                                DataPropertyDefinition tdp = tp as DataPropertyDefinition;
                                if (tdp != null)
                                {
                                    if (srcDt.Value != tdp.DataType)
                                    {
                                        FdoDataPropertyConversionRule rule = new FdoDataPropertyConversionRule(
                                            exprMap.alias,
                                            exprMap.target,
                                            srcDt.Value,
                                            tdp.DataType,
                                            exprMap.nullOnFailedConversion,
                                            exprMap.truncate);
                                        opts.AddDataConversionRule(exprMap.alias, rule);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else //class doesn't exist
            {
                mod = new CreateTargetClassFromSource(el.Source.schema, el.Target.@class);

                foreach (var propMap in el.PropertyMappings)
                {
                    opts.AddPropertyMapping(propMap.source, propMap.target);

                    if (propMap.createIfNotExists)
                    {
                        opts.AddSourcePropertyToCheck(propMap.source);
                    }
                }

                foreach (var exprMap in el.ExpressionMappings)
                {
                    opts.AddSourceExpression(exprMap.alias, exprMap.Expression, exprMap.target);

                    if (exprMap.createIfNotExists)
                    {
                        opts.AddSourcePropertyToCheck(exprMap.alias);
                    }

                    var prop = FdoSchemaUtil.CreatePropertyFromExpressionType(exprMap.Expression, srcClass, availableFunctions, defaultSc.Name);
                    if (prop == null)
                    {
                        throw new InvalidOperationException("Could not derive a property definition from the expression: " + exprMap.Expression);
                    }
                    prop.Name = exprMap.target;
                    mod.AddProperty(prop);
                }
            }

            return(opts);
        }
Esempio n. 4
0
        private ClassDefinition CreateMergedClass(ClassDefinition leftCls, ClassDefinition rightCls)
        {
            ClassDefinition cls = null;

            if (!string.IsNullOrEmpty(_options.GeometryProperty))
            {
                cls = new FeatureClass(_options.Target.ClassName, "");
            }
            else
            {
                cls = new Class(_options.Target.ClassName, "");
            }

            var props = cls.Properties;

            foreach (PropertyDefinition p in leftCls.Properties)
            {
                int idx = props.IndexOf(p.Name);
                if (idx < 0)
                {
                    var prop = FdoSchemaUtil.CloneProperty(p);
                    props.Add(prop);
                }
            }
            foreach (PropertyDefinition p in rightCls.Properties)
            {
                int idx = props.IndexOf(p.Name);
                if (idx < 0)
                {
                    var prop = FdoSchemaUtil.CloneProperty(p);
                    props.Add(prop);
                }
            }

            //Strip off autogeneration because we want to preserve original values
            foreach (PropertyDefinition p in props)
            {
                if (p.PropertyType == PropertyType.PropertyType_DataProperty)
                {
                    DataPropertyDefinition dp = (DataPropertyDefinition)p;
                    dp.IsAutoGenerated = false;
                }
            }

            DataPropertyDefinition fid = new DataPropertyDefinition("FID", "Autogenerated ID");

            fid.DataType        = DataType.DataType_Int32;
            fid.IsAutoGenerated = true;
            fid.Nullable        = false;

            props.Add(fid);
            cls.IdentityProperties.Add(fid);

            if (!string.IsNullOrEmpty(_options.GeometryProperty))
            {
                //If prefixed, we need to qualify it to match what's in the merged class
                string pn = _options.GeometryProperty;
                if (_options.Side == JoinSide.Left)
                {
                    if (!string.IsNullOrEmpty(_options.LeftPrefix))
                    {
                        pn = _options.LeftPrefix + pn;
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(_options.RightPrefix))
                    {
                        pn = _options.RightPrefix + pn;
                    }
                }

                int idx = props.IndexOf(pn);
                if (idx < 0)
                {
                    throw new FdoETLException("Property not found in merged class: " + _options.GeometryProperty);
                }
                else
                {
                    var p = props[idx];
                    if (p.PropertyType != PropertyType.PropertyType_GeometricProperty)
                    {
                        throw new FdoETLException("Designated property is not a geometry property: " + _options.GeometryProperty);
                    }

                    ((FeatureClass)cls).GeometryProperty = (GeometricPropertyDefinition)p;
                }
            }

            return(cls);
        }